報錯現(xiàn)場還原
web.xml文件頭部聲明如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
報錯的 servlet 元素如下:
<servlet>
<description>Enter Dispatcher</description>
<servlet-name>xxxMVC</servlet-name>
<servlet-class>com.xxx.web.servlet.RequestDispatcher</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>xxxName</param-name>
<param-value>xxxValue</param-value>
</init-param>
</servlet>
報錯提示在 <init-param> 那一行,具體報錯內(nèi)容如下:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One of '{"http://xmlns.jcp.org/xml/ns/javaee":enabled,
"http://xmlns.jcp.org/xml/ns/javaee":async-supported, "http://xmlns.jcp.org/xml/ns/javaee":run-as, "http://xmlns.jcp.org/xml/ns/javaee":security-
role-ref, "http://xmlns.jcp.org/xml/ns/javaee":multipart-config}' is expected.
解決方法
將 init-param 元素整體移動到 load-on-startup 元素之前,修改后,內(nèi)容如下:
<servlet>
<description>Enter Dispatcher</description>
<servlet-name>xxxMVC</servlet-name>
<servlet-class>com.xxx.web.servlet.RequestDispatcher</servlet-class>
<init-param>
<param-name>xxxName</param-name>
<param-value>xxxValue</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
報錯原因分析
因為是 servlet 元素報錯,所以,我們嘗試找到對應的xsd文件,來看下報錯的地方違反了哪條限制或約束。根據(jù)xml文件頭部聲明,我們知道對應的xsd文件是 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd ,但是從 web-app_3_1.xsd 文件中,我們并沒有找到對應的約束定義。但是,我們發(fā)現(xiàn)如下代碼片段:
<xsd:include schemaLocation="web-common_3_1.xsd"/>
所以,我們嘗試繼續(xù)在 web-common_3_1.xsd 中尋找對應的限制或約束,我們找到如下兩個代碼片段:
<xsd:element name="servlet" type="javaee:servletType"/>
<xsd:complexType name="servletType">
......
<xsd:sequence>
......
<xsd:element name="init-param"
type="javaee:param-valueType"
minOccurs="0"
maxOccurs="unbounded"/>
<xsd:element name="load-on-startup"
type="javaee:load-on-startupType"
minOccurs="0">
</xsd:element>
......
</xsd:sequence>
......
</xsd:complexType>
從上面兩段代碼,我們知道,針對 servlet 元素,通過 <xsd:sequence> 限制了子元素的出現(xiàn)順序,init-param 必須出現(xiàn)在 load-on-startup 之前。到這里,我們終于明白了錯誤的原因是我們將子元素的前后順序設置錯了。