Проблема с настройкой web.xml в проекте jsf [duplicate]

Бит опоздал на вечеринку, но я изучал этот вопрос сегодня и заметил, что многие ответы не полностью касаются того, как Javascript обрабатывает области, что по существу то, что это сводится к.

So как упоминалось многими другими, проблема в том, что внутренняя функция ссылается на одну и ту же переменную i. Итак, почему бы нам просто не создать новую локальную переменную на каждой итерации и вместо этого иметь ссылку на внутреннюю функцию?

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '

' + msg + '

';}; var funcs = {}; for (var i = 0; i < 3; i++) { var ilocal = i; //create a new local variable funcs[i] = function() { console.log("My value: " + ilocal); //each should reference its own local variable }; } for (var j = 0; j < 3; j++) { funcs[j](); }

Точно так же раньше, когда каждая внутренняя функция выдавала последнее значение, присвоенное i, теперь каждая внутренняя функция просто выводит последнее значение, назначенное на ilocal. Но не должна ли каждая итерация иметь свою собственную ilocal?

Оказывается, в этом и проблема. Каждая итерация разделяет одну и ту же область, поэтому каждая итерация после первого просто переписывается ilocal. Из MDN :

Важно: JavaScript не имеет области блока. Переменные, введенные с блоком, привязаны к содержащейся функции или скрипту, а эффекты их настройки сохраняются за пределами самого блока. Другими словами, операторы блоков не вводят область. Хотя «автономные» блоки являются допустимым синтаксисом, вы не хотите использовать автономные блоки в JavaScript, потому что они не делают то, что, по вашему мнению, они делают, если вы думаете, что они делают что-то вроде таких блоков на C или Java.

blockquote>

Повторяется для акцента:

JavaScript не имеет области блока. Переменные, введенные с блоком, привязаны к содержащейся функции или скрипту

blockquote>

. Мы можем увидеть это, проверив ilocal, прежде чем объявить его на каждой итерации:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '

' + msg + '

';}; var funcs = {}; for (var i = 0; i < 3; i++) { console.log(ilocal); var ilocal = i; }

Именно поэтому эта ошибка настолько сложна. Несмотря на то, что вы обновляете переменную, Javascript не будет вызывать ошибку, и JSLint даже не выдаст предупреждение. Именно поэтому лучший способ решить эту проблему - воспользоваться преимуществами закрытия, что по сути является идеей, что в Javascript внутренние функции имеют доступ к внешним переменным, потому что внутренние области «заключают» внешние области.

Closures [/g13]

Это также означает, что внутренние функции «удерживают» внешние переменные и сохраняют их, даже если внешняя функция возвращается. Чтобы использовать это, мы создаем и вызываем функцию-оболочку только для создания новой области, объявляем ilocal в новой области и возвращаем внутреннюю функцию, которая использует ilocal (более подробное объяснение ниже):

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '

' + msg + '

';}; var funcs = {}; for (var i = 0; i < 3; i++) { funcs[i] = (function() { //create a new scope using a wrapper function var ilocal = i; //capture i into a local var return function() { //return the inner function console.log("My value: " + ilocal); }; })(); //remember to run the wrapper function } for (var j = 0; j < 3; j++) { funcs[j](); }

Создание внутренней функции внутри функции-обертки дает внутренней функции частную среду, доступ к которой может получить только «закрытие». Таким образом, каждый раз, когда мы вызываем функцию-оболочку, мы создаем новую внутреннюю функцию с ее собственной отдельной средой, гарантируя, что переменные ilocal не сталкиваются и не перезаписывают друг друга. Несколько незначительных оптимизаций дают окончательный ответ, который дали многие другие пользователи SO:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '

' + msg + '

';}; var funcs = {}; for (var i = 0; i < 3; i++) { funcs[i] = wrapper(i); } for (var j = 0; j < 3; j++) { funcs[j](); } //creates a separate environment for the inner function function wrapper(ilocal) { return function() { //return the inner function console.log("My value: " + ilocal); }; }

Обновить

С ES6 теперь mainstream, теперь мы можем использовать новое ключевое слово let для создания переменных с блочным диапазоном:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '

' + msg + '

';}; var funcs = {}; for (let i = 0; i < 3; i++) { // use "let" to declare "i" funcs[i] = function() { console.log("My value: " + i); //each should reference its own local variable }; } for (var j = 0; j < 3; j++) { // we can use "var" here without issue funcs[j](); }

Посмотрите, как легко это сейчас! Для получения дополнительной информации см. этот ответ , на котором основана моя информация.

10
задан BalusC 17 May 2016 в 07:39
поделиться

1 ответ

Когда вы сталкиваетесь с «странным» исключением, указывающим на то, что классы / методы / файлы / компоненты / теги отсутствуют или различаются, хотя они явно включены в веб-приложение, такое как приведенные ниже,

java.lang.ClassFormatError: Отсутствует атрибут кода в методе, который не является родным или абстрактным в файле класса javax / faces / webapp / FacesServlet

java.util.MissingResourceException: Не удается найти javax.faces.LogStrings bundle

com.sun.faces.vendor.WebContainerInjectionProvider не может быть cast to com.sun.faces.spi.InjectionProvider

com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED

Тег с именем inputFile из пространства имен http: & # x2f; /xmlns.jcp.org/jsf/html имеет нулевой класс обработчика.

< / blockquote>

java.lang.NullPoint erException в javax.faces.CurrentThreadToServletContext.getFallbackFactory

java.lang.AbstractMethodError в javax.faces.application.ViewHandlerWrapper.getWebsocketURL

< / blockquote>

или когда вы сталкиваетесь с «странным» временем выполнения, таким как сломанные сеансы HTTP (jsessionid отображается в URL-адресах по всему месту) и / или сломанная область видимости JSF (она ведет себя как область запроса) и / или сломанные ресурсы CSS / JS / image, тогда вероятность велика, что путь к классу среды выполнения Webapp загрязнен дублированными разными версиями JAR-файлов.

В вашем конкретном случае с ClassFormatError на FacesServlet, это означает, что файл JAR, содержащий упомянутый класс, был найден в первый раз, фактически является «файлом JAR-файла API», предназначенным для поставщиков решений (таких как разработчики, работающие в Mojarra и MyFaces). Он содержит файлы классов с только сигнатурами классов и методов, без каких-либо структур кода и файлов ресурсов. Именно это означает «отсутствующий атрибут кода».

Всегда отмечайте серверные библиотеки как provided

Все зависимости, помеченные как « Спецификации Java » в Maven и имеющие -api суффикс в идентификаторе артефакта - эти API-интерфейсы. Их не должно быть в пуле классов. Вы должны всегда отмечать их <scope>provided</scope>, если вам действительно нужно иметь его в своем пом. Известным примером является API-интерфейс Java EE (Web) :

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version><!-- 6.0 or 7.0 or newer --></version>
    <scope>provided</scope>
</dependency>

Если область provided отсутствует, то этот JAR окажется в файле /WEB-INF/lib webapp [ , вызывая все проблемы, с которыми вы сталкиваетесь сейчас. В этом конкретном случае у вас есть ненужная зависимость JSF API :

<dependency>
    <groupId>javax.faces</groupId>
    <artifactId>javax.faces-api</artifactId>
</dependency>

вызывает проблему, потому что в ней содержится класс чертежа FacesServlet. Удалите его и опираясь на API-интерфейс provided Java EE (Web), как показано выше, должны решить его.

Tomcat как баскетбольный контейнер JSP / Servlet уже предоставляет JSP, Servlet и EL (а также 8 WebSocket). Поэтому вы должны отмечать как минимум jsp-api, servlet-api и el-api как provided. Tomcat не предоставляет JSF (и JSTL ). Таким образом, вам нужно будет установить его через webapp.

Полноценные серверы Java EE, такие как WildFly, TomEE, GlassFish, Payara, WebSphere и т. Д., Уже предоставляют весь API Java EE, включая JSF , Поэтому вам абсолютно не нужно устанавливать JSF через webapp. Это приведет только к конфликтам, если сервер уже предоставит другую версию и / или версию из коробки. Единственная зависимость, в которой вы нуждаетесь, - это javaee-web-api, как показано выше.

Установка JSF на Tomcat

. Правильный способ установки JSF в Tomcat упоминается в нашей JSF wiki - Установка JSF . Существует 2 реализации JSF, Mojarra и MyFaces . Вы должны выбрать один из них и, следовательно, не оба.

Установка Mojarra на Tomcat:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version><!-- Check https://javaserverfaces.github.io --></version>
</dependency>

Вы также можете проверить org.glassfish:javax.faces репозиторий для текущей последней версии (которая в настоящее время 2.2.13). См. Также собственные инструкции по установке Mojarra .

Установка MyFaces на Tomcat:

<dependency>
    <groupId>org.apache.myfaces.core</groupId>
    <artifactId>myfaces-api</artifactId>
    <version><!-- Check http://myfaces.apache.org --></version>
</dependency>
<dependency>
    <groupId>org.apache.myfaces.core</groupId>
    <artifactId>myfaces-impl</artifactId>
    <version><!-- Check http://myfaces.apache.org --></version>
</dependency>

Вы также можете проверить репозиторий org.apache.myfaces.core:myfaces-bundle для текущей версии последней версии (в настоящее время 2.2.10).

Обратите внимание, что Tomcat 6 как контейнер Servlet 2.5 поддерживает максимальный JSF 2.1. Не забудьте также установить JSTL. См. Также наш JSF wiki - Установка JSF .

См. Также:

25
ответ дан BalusC 25 August 2018 в 16:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: