天天看點

Web開發 web.xml中metadata-complete屬性

無論是Servlet,還是Filter,Listener等,在自定義Filter時,要想使它起作用,那麼必須要對它進行配置,一般都有兩種配置的方式,一種是基于

配置式

的,另一種則是基于

注解式

的。

以Servlet為例:

在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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>mys</servlet-name>
        <servlet-class>com.mycat.web.MyFirstServlet</servlet-class>
        <init-param>
            <param-name>tom</param-name>
            <param-value>123</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>mys</servlet-name>
        <url-pattern>/myser</url-pattern>
    </servlet-mapping>
</web-app>
           
類上注解式:(基于配置式的話,就不要使用它的配置式了,即不要同時配置該Servlet的web.xml的servlet配置和類上注解添加)
package com.mycat.web;

import javax.servlet.*;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 自定義的Servlet必須實作Servlet接口
 */
@WebServlet(value = "/myser",initParams = @WebInitParam(name="tom",value="123"))
public class MyFirstServlet implements Servlet {

    private ServletConfig servletConfig;
    private ServletRequest servletRequest;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
        System.out.println("Servlet的初始化方法...");
    }

    @Override
    public ServletConfig getServletConfig() {

        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        this.servletRequest=servletRequest;

        System.out.println("service....運作時方法");
        PrintWriter writer = servletResponse.getWriter();

        System.out.println("獲得Servlet的配置對象:"+this.getServletConfig());
        System.out.println("變量tom的值:"+servletConfig.getInitParameter("tom"));
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        writer.println("===============================");
        writer.println("<a href='myser2?username=2'>去myser2</a>");
    }

    @Override
    public String getServletInfo() {
        return servletRequest.getServletContext().getServerInfo();
    }

    @Override
    public void destroy() {
        System.out.println("Servlet的銷毀方法...");
    }
}
           

1.為什麼基于注解的方式可以被識别,并且可以被通路

1)先來看看@WebServlet這個注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    String name() default "";
    String[] value() default {};
    String[] urlPatterns() default {};
    int loadOnStartup() default -1;
    WebInitParam[] initParams() default {};  // 使用:@WebInitParam(參數清單)
    boolean asyncSupported() default false;
    String smallIcon() default "";
    String largeIcon() default "";
    String description() default "";
    String displayName() default "";
}
           
對于Servlet來說,他有 name, value, urlpattern, loadOnStatus, initParams, asyncSupported, smallIcon, largeIcon, description, displayName 共10的屬性

name: 自定義Servlet的名稱 ,String類型。對應于web.xml中< servlet-name>的配置

value: 自定義 Servlet的映射模式,即等價于urlPattern屬性,與urlPattern屬不同同時使用,多個的話,使用逗号分隔開。參數是String[]。

urlPattern:自定義 Servlet的映射模式,即等價于value屬性,與value屬不同同時使用,對應于web.xml中< url-pattern>标簽的配置。多個的話,使用逗号分隔開。參數是String[]。

loadOnStartup: 指定Servlet的加載順序,等同于web.xml中< load-on-startup>标簽的配置,整型數值

initParams:指定一組Servlet的初始化參數,相當于web.xml中的< init-param>标簽,可以看做是Servlet的全局變量。

asyncSupported: 聲明Servlet是否支援異步操作模式,等同于web.xml中< asyn-supported>标簽

description: 對于Servlet的描述,等同于web.xml中< description>标簽

displayName: 該Servlet的顯示名,通常配合工具使用,等價于web.xml中< display-name>标簽

smallIcon和largeIcon: 表示的是Servlet的顯示圖示,即标簽頁左側的小圖示。這裡隻是表示兩個尺寸的,值為String類型的,即小圖示的位址。

使用示例:

loadOnStartUp: 即隻是Servlet法人加載順序,當其值為負數時,表示隻有在第一次請求這個Servlet,才會被加載,當其值為0或者整數時則表示整個應用程式啟動時就立即加載,而且 loadOnStartUp 越小的越先被加載。
//一個參數時,預設是value,是以可以也寫成@WebServlet("/myser2"))
@WebServlet(value = "/myser2"))   
public class MySecondServlet extends HttpServlet {
    ....
           
@WebServlet(value = "/myser2",initParams = @WebInitParam(name="tom",value="123"))
public class MySecondServlet extends HttpServlet {
    ....
           
// 多個初始化參數  initParams={@WebInitParam(...),@WebInitParam(...)...}
@WebServlet(value = "/myser2",initParams = {@WebInitParam(name="username",value="tom"),@WebInitParam(name="password",value="123")})
public class MySecondServlet extends HttpServlet {
    ....
           
@WebServlet(value = "/myser2",initParams = @WebInitParam(name="tom",value="123"))
public class MySecondServlet extends HttpServlet {
    ....
           
@WebServlet(value = "/myser2",loadOnStartup = -1)
public class MySecondServlet extends HttpServlet {
    ....
           

分析總結:

無論是基于配置配置式的,還是基于注解式的,都會提供給對應的參數,讓引擎來解析為一個Servlet,但是注解的話,應該有個配置啥的來掃描:那就是web.xml中< web-app>标簽的metadata-complete屬性。
2)< web-app>标簽的metadata-complete屬性
metadata-complete屬性表示部署時目前的配置是否完全,值為true,表示完全,隻會應用web.xml的配置,而不會去掃描類似@WebServlet,@WebFilter,@WebListener等注解和web-frame.xml配置。

預設值

是metadata-complete=false,即不完全,會對項目中類進行掃描,是否有相關的注解配置,同時也會加載web-frame.xml等插件配置。

示例代碼:

four.jsp連結到映射到/myser4的Servlet

①預設情況:(metadata-complete=false)

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_4_0.xsd"
         version="4.0">
</web-app>
           
MyFourServlet代碼:
package com.mycat.web;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("/myser4")
public class MyFourServlet implements Servlet {
    private ServletRequest servletRequest;
    private ServletConfig servletConfig;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
        System.out.println("Servlet名稱:"+servletConfig.getServletName());
        System.out.println("應用上下文路徑:"+servletConfig.getServletContext().getContextPath());
    }

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        this.servletRequest=servletRequest;
        System.out.println("運作方法...");
    }

    @Override
    public String getServletInfo() {
        return servletConfig.getServletContext().getServerInfo();
    }

    @Override
    public void destroy() {}
}
           
測試結果:(正常運作)

Servlet名稱:com.mycat.web.MyFourServlet

應用上下文路徑:/my

運作方法…

②自定義值為true情況:(metadata-complete=true)

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_4_0.xsd" metadata-complete=true
         version="4.0">
</web-app>
           
MyFourServlet代碼:
不變
測試結果:(頁面運作狀态 404 ,運作出錯,找不到對應的Servlet)

Type Status Report

Message /my/myser4

Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

3.關于metadata-complete屬性使用結論

本意是中繼資料書否完全(web.xml中),如果需要注解方式定義元件時,顯然必須設定為false,也就是預設值