• Servlet的配置


    配置Servlet映射

     <servlet>
            <servlet-name>TestServlet</servlet-name>
            <servlet-class>servlet.TestServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>TestServlet</servlet-name>
            <url-pattern>/TestServlet</url-pattern>
        </servlet-mapping>

    只能使用/TestServlet来访问,使用其他的比如/TestServlet/xxx是访问不了的。

    url-pattern必须以/开始,引用时引用url-pattern中/后面的部分。比如<url-pattern>/handlerServlet</url-pattern>,表单action="handlerServlet";比如<url-pattern>/servlet/handlerServlet</url-pattern>,表单action="servlet/handlerServlet"。

    引用的是url-pattern,不是servlet-name。

    可以使用. 

    <url-pattern>/servlet.TestServlet</url-pattern> 

    访问时以 /servlet.TestServlet 来访问。注意不是通过/servlet/TestServlet来访问。

    可以使用/

    <url-pattern>/servlet/TestServlet</url-pattern>

    访问时以 /servlet/TestServlet 来访问

    可以使用通配符*

    <url-pattern>/*</url-pattern>

    匹配所有请求。

      

    多重映射:一个Servlet配置多个<url-pattern>,可通过多个路径来访问。

    <servlet-mapping>
            <servlet-name>TestServlet</servlet-name>
            <url-pattern>/TestServlet1</url-pattern>
            <url-pattern>/TestServlet2</url-pattern>
        </servlet-mapping>

    既可通过/TestServlet1来访问,又可通过/TestServlet2来访问。

    配置 load-on-startup

    <servlet>
            <servlet-name>TestServlet</servlet-name>
            <servlet-class>servlet.TestServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>

    配置了<load-on-startup></load-on-startup>的Servlet会在Servlet容器(比如Tomcat)启动时就创建此Servlet的实例。

    参数是一个整数,值越小的越先创建(初始化)。

    默认Servlet

     <url-pattern>/</url-pattern>

    只有一个/,当找不到匹配的Servlet时,就执行这个默认的Servlet(用默认的Servlet来响应)。

    注意默认Servlet是/,不是/*。

    默认Servlet与Tomcat处理静态资源有很大联系。

    Tomcat处理请求的流程

    浏览器要访问某个web资源(页面),Tomcat是如何处理这个请求的呢?

    (1)Tomcat先在此WebApp的web.xml中根据<url-pattern>找有没有匹配的Servlet,有就调用来处理这个请求

    (2)如果没有,就查找此WebApp的web.xml中有没有配置默认Servlet,有就调用默认的Servlet来处理这个请求。

    这个就很有意思了,比如浏览器请求的是xxx.html,此WebApp下也有这个xxx.html,但你配置了一个默认的Servlet,那Tomcat会调用默认的Servlet来响应,而不是调用xxx.html来响应!

    (3)如果此WebApp没有配置默认的Servlet,那就到Tomcat -> conf -> web.xml 中查找,这个web.xml是Tomcat的全局配置,对所有WebApp均有效。

    先根据<url-pattern>找有没有匹配的Servlet,全局的web.xml中自然是找不到匹配的Servlet的;

    然后找有没有默认的Servlet,全局的web.xml中配置了一个默认的Servlet,此Servlet的处理方式是:在当前WebApp的资源找有没有请求的这个资源|文件,有就用这个资源|文件来响应,比如请求的是xxx.html,就在当前这个WebApp的资源中找有没有xxx.html这个资源|文件,有就用它来响应。如果当前WebApp中没有这个资源|文件,就报404错误。

    如果浏览器请求的是静态资源,比如xxx.html,这要走完整个流程。

    人家请求的是静态资源,你遍历2个web.xml,在一堆Servlet配置中找!简直傻X。

    所以说Tomcat处理静态资源不给力。处理静态资源一般用Nginx,不用Tomcat。

    配置某个Servlet的初始化参数

    <servlet>
            <servlet-name>TestServlet</servlet-name>
            <servlet-class>servlet.TestServlet</servlet-class>
            <init-param>
                <param-name>name</param-name>
                <param-value>张三</param-value>
            </init-param>
            <init-param>
                <param-name>age</param-name>
                <param-value>18</param-value>
            </init-param>
        </servlet>

    一个<init-param>设置一个参数。可以设置多个。

    在Servlet中使用ServletConfig获取当前Servlet的初始化参数

     1 public class TestServlet extends HttpServlet {
     2     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     3         doGet(request, response);
     4     }
     5 
     6     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     7         response.setContentType("text/html;charset=utf-8");  // //设置响应输出流的编码格式。若不设置,中文会乱码。
     8         PrintWriter writer = response.getWriter();  //获取响应输出流
     9         ServletConfig servletConfig=this.getServletConfig();  //this表示当前Servlet。可缺省this,直接调用getServletContext()
    10 
    11         //获取单个参数值
    12         String name = servletConfig.getInitParameter("name"); //返回值是String
    13         String age = servletConfig.getInitParameter("age");
    14         writer.write("name:"+name+"<br />");   //输出会以html的形式显示,所以可以使用html标签。
    15         writer.write("age:"+age);
    16 
    17         writer.write("<hr />");
    18 
    19         //遍历
    20         Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();  //里面的元素是参数名
    21         while (initParameterNames.hasMoreElements()){
    22             String paramName=initParameterNames.nextElement();  //参数名
    23             String paramValue=servletConfig.getInitParameter(paramName);  //参数值
    24             writer.write(paramName+":"+paramValue+"<br />");
    25         }
    26 
    27 
    28     }
    29 }

     

    说明

    • 如果响应中包含中文,需要设置设置响应的编码字符集。有2种设置方式

        response.setContentType("text/html;charset=utf-8");  
        response.setCharacterEncoding("utf-8");

    这两种方式都可以解决响应中文乱码的问题(准确来说不是乱码,是显示为?识别不了)。区别是:第一种设置了输出文档是html,所以可以输出html文档中的内容,比如:

        PrintWriter writer = response.getWriter();  
            writer.write("<h2>hello</h2>");   
            writer.write("<script>alert('hello')</script>");

    这些html标签都会被解析,js脚本是有效的。

    第二种只设置了响应字符集为utf-8,并没有设置响应是html文档,解析不了响应中的html标签。

    • 设置响应字符集的这句代码必须放在获取响应输出流的代码之前。

        response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();

    如果放在了获取响应输出流的代码之后,则设置的字符集无效。

    • 解决请求参数中的中文乱码

    request.setCharacterEncoding("utf-8");

    习惯上把设置request、response字符集的这两句代码放在doGet() | doPost() 里的最前面。

    • 如果我们想在响应输出流中输出换行,使用<br />,而非 。

         response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write("hello<br />");

    设置响应输出流是html文档,换行自然要用<br />, 在html中换不了行。

    配置整个web应用的初始化参数,所有Servlet共享

    既然是所有servlet公有的,那就应该直接放在<web-app>下。

    <context-param>
            <param-name>name</param-name>
            <param-value>chy</param-value>
        </context-param>
    
        <context-param>
            <param-name>age</param-name>
            <param-value>20</param-value>
        </context-param>

    一个<context-param>配置一个参数,可配置多个参数。

    在servlet中获取参数值

     1 response.setContentType("text/html;charset=utf-8");
     2         PrintWriter writer = response.getWriter();
     3         ServletContext context=this.getServletContext();  //可缺省this,直接调用getServletContext()
     4 
     5         //获取单个参数值
     6         String name = context.getInitParameter("name");
     7         String age = context.getInitParameter("age");
     8         writer.write("name:"+name+"<br />");
     9         writer.write("age:"+age);
    10 
    11         writer.write("<hr />");
    12 
    13         //遍历
    14         Enumeration<String> initParameterNames =context.getInitParameterNames();  //里面的元素是参数名
    15         while (initParameterNames.hasMoreElements()){
    16             String paramName=initParameterNames.nextElement();  //参数名
    17             String paramValue=context.getInitParameter(paramName);  //参数值
    18             writer.write(paramName+":"+paramValue+"<br />");
    19         }

    我们注意到通过ServletContext对象获取东西参数名、参数值、Enumeration对象的三个方法都是getInitParameterXxx()。为什么是init?

    ServletConfig表示当前Servlet的初始化配置。

    ServletContext表示整个Web应用中所有Servlet的共享数据。共享数据有2个部分:

    • 在xml中通过<context-param>配置的初始化参数,这部分数据要通过ServletContext实例的getInitParameterXxx()来获取
    • 另一部分共享数据是在web应用运行中通过setAttribute()添加|设置的,需要使用getAttribute()来获取。

    这2部分数据是分开的、独立的,操作数据的方法也是独立的一套。

    整个Web应用的共享数据

    在一个Servlet中:

        ServletContext context=getServletContext();  //可缺省this
            context.setAttribute("name","chy");
            context.setAttribute("age",20);  

    设置的数据是所有Servlet共享的,在其他Servlet中可以修改、获取这些数据。

    在另一个Servlet中使用:

     //获取单个属性值
            String name= (String) servletContext.getAttribute("name");  //获取的是属性值都是Object,需要强转
            int age= (int) servletContext.getAttribute("age");
            
            //遍历
            Enumeration<String> attributeNames = servletContext.getAttributeNames();
            while (attributeNames.hasMoreElements()){
                String attributeName=attributeNames.nextElement();  //属性名是String
                Object attributeValue = servletContext.getAttribute(attributeName);  //属性值是Object,需要强转
                //...
            }

    需要先访问前一个Servlet。先设置了数据,才取得出来。

    如果要移除某个共享数据,可以使用 removeAttribute(String name) 。

    获取ServletConfig对象、ServletContext对象,可以使用this,也可以缺省this,直接写getServletConfig|Context()。

    因为getServletConfig()获取的只能是当前Servlet的初始化配置,是唯一的;

    getServletContext()获取的只能是当前WebApp中的共享数据,也是唯一的;

    不需要this。

    获取当前Servlet的初始化参数时,可以不要ServletConfig对象,直接写 getInitParameter()、getInitParameterNames()。

    因为当前的Servlet是唯一的、确定的。

     使用ServletContext读取资源文件

    1 ServletContext servletContext = getServletContext();
    2         InputStream is = servletContext.getResourceAsStream("/test.properties"); 
    3         Properties properties = new Properties();
    4         properties.load(is);

    配置Tomcat数据源

    1、在tomcat->conf->context.xml中配置数据源

    <Context>
    
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
        <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
        <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    
     <Resource name="jdbc/mysql"
            type="javax.sql.DataSource"
            driverClassName="com.mysql.cj.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/my_db?serverTimezone=GMT"
            username="chy"
            password="abcd"  />
    
    </Context>

    <WatchedResource>是自带的,不用管。

    一个<Resource>配置一个资源,可同时配置多个资源。<Resource>的name属性唯一标识此资源,数据源的name常用jdbc/xxx来命名。Tomcat中配置的资源是全局的,所有webapp都可以通过name引用。

    type指定资源类型是数据源。Tomcat的内置数据源是DBCP,所以参数要是DBCP的参数,可在<Resource>中配置DBCP中可配置的所有参数。

    需要把数据库驱动添加到tomat的lib中。

    说明:tomcat自带java web常用的jar包。使用tomcat运行webapp时,默认会自动使用tomcatlib下的servlet-api.jar、jsp-api.jar这2个包,所以我们不必手动添加这2个包的依赖。当然把java ee的jar包添加进来也行。

    2、在WebApp的web.xml中引用Tomcat数据源

    <resource-ref>
            <res-ref-name>jdbc/mysql</res-ref-name>
            <res-type>javax.sql.DataSource</res-type>
        </resource-ref>

    配置在<web-app>中,一个<resource-ref>配置一个资源引用,<res-ref-name>指定要引用的资源的name(对应tomcat中资源的name),res-type指定所引用资源的类型。

    这2个子元素的位置可以互换,但在某些版本的IDEA中,如果type写在前,name写在后,type会报红,这是IDEA本身的问题,代码没有错。

    3、在Servlet中使用数据源

       InitialContext initialContext = new InitialContext();
                Context context = (Context) initialContext.lookup("java:comp/env");  //返回值是Object,需要强转。参数是固定的。
                DataSource dataSource = (DataSource)context.lookup("jdbc/mysql");  //获取数据源,参数是资源的name。返回值是Object,需要强转
                Connection connection = dataSource.getConnection();
                

    使用注解配置Servlet

    使用注解配置Servlet最常用,也最方便。

    @WebServlet(
      name = "testServlet",
      urlPatterns = { "/servlet/testServlet" },
      loadOnStartup = 1,
      initParams = {@WebInitParam(name = "name", value = "张三"),@WebInitParam(name="age",value="12")}
    )
    public class TestServlet extends HttpServlet {
      //......
    }

    name指定此Servlet的name,缺省时默认为此Servlet的全限定类名。

    urlPatterns、value指定映射,二者完全等价。多重映射写成字符串数组的形式,如果只有一个映射关系,可以直接写成字符串。

    loadOnStartup,即<load-on-startup>。

    initParams指定此Servlet的初始化参数,数组形式。一个@WebInitParam配置一个初始化参数,name、value均为String。

    以上参数均可缺省,但一般都要配置value | urlPatterns。

    参数只有value | urlPatterns时可以缺省value | urlPatterns,直接写参数值。

    @WebServlet("/servlet/testServlet")

    配置项目首页

    <welcome-file-list>
        <welcome-file>/login.jsp</welcome-file>
    </welcome-file-list>

    缺省时默认是index.xxx。

  • 相关阅读:
    CF57C Array
    P4739 [CERC2017]Donut Drone
    CF1455D Sequence and Swaps
    LG P4351 [CERC2015]Frightful Formula
    5. React-router1- react-router理解
    5. React-router0- spa理解和路由的理解
    axios案例学习总结
    axios源码和常用方法
    http8种请求方式
    axios-http,ajax的封装,axios的使用
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/11396823.html
Copyright © 2020-2023  润新知