JavaWeb之Servlet一

作者:刘婧怡

时间:2019.03.27

主机环境:MacBookPro


 

Servlet

1. Servlet简介

  • Servlet是JavaWeb的三大组件之一,属于动态资源

  • Servlet的功能

    • 接受请求数据

    • 处理请求:每个Servlet都是唯一的,能处理的请求都是不同的

    • 完成响应

  • Servlet需要我们自己编写

2. 实现Servlet的方式(三种)

  • 实现javax.servlet.Servlet接口

  • 继承javax.servlet.GenericServlet类

  • 继承javax.servlet.http.HttpServlet类,它是GenericServlet的子类

 

3. Servlet接口

  • 接口中的方法,生命周期方法是Tomcat自动调用的方法

publicclassMyServletimplementsServlet{
   
   //是生命周期方法
   //会在Servlet对象被创建后马上执行,并只执行一次
   publicvoidinit(ServletConfigservletConfig) throwsServletException;
   
   //可以用来获取Servlet的配置信息
   publicServletConfiggetServletConfig();
​
   //是生命周期方法
   //会被调用多次
   //每次处理请求都会被调用
   publicvoidservice(ServletRequestservletRequest, ServletResponseservletResponse) throwsServletException, IOException;
   
   //可以获取Servlet的信息
   publicStringgetServletInfo();
   
   //是生命周期方法
   //会在Servlet被销毁之前调用,并且只会被调用一次
   //该方法不能销毁Servlet
   publicvoiddestroy();
}
​
  • 在web.xml文件中配置Servlet

<servlet>
       <!--xxx可以随便写-->
       <servlet-name>xxx</servlet-name>
       <servlet-class>servlet.MyServlet</servlet-class>
</servlet><servlet-mapping>
       <servlet-name>xxx</servlet-name>
       <!--必须以/开头,后面随便写-->
    <url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
  • ServletConfig接口 

    • 一个ServletConfig对象对应一段web.xml中的Servlet配置信息

    • API:

      • String getServletName():获取<servlet.name>的内容

      • ServletContext getServletContext():获取Servlet上下文的对象

      • String getInitParament():通过名称获取指定初始化参数的值

      • Enumeration getInitParamentName():获取所有初始化参数的名称

<servlet>
   <servlet-name>One</servlet-name>
   <servlet-class>cn.itcast.servlet.OneServlet</servlet-class>
   <init-param>
    <param-name>paramName1</param-name>
     <param-value>paramValue1</param-value>
   </init-param>
   <init-param>
     <param-name>paramName2</param-name>
     <param-value>paramValue2</param-value>
   </init-param>
 </servlet>

 

4. GenericServlet类

  • GenericServlet是Servlet接口的实现类,我们可以通过继承GenericServlet来编写自己的Servlet。

    下面是GenericServlet类的源代码

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable 
{
    private static final long serialVersionUID = 1L;
    
    private transient ServletConfig config;
    
    public GenericServlet() {}
    
    @Override
    public void destroy() {}
    
    @Override
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }
    
    @Override
    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }
    
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    
    @Override
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    
    @Override
    public String getServletInfo() {
        return "";
    }
    
    @Override
    public void init (ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    
    public void init () throws ServletException {}
    
    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
    
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
            
    @Override
    public String getServletName() {
        return config.getServletName();
    }
}
  • init()方法

    • init()方法是用来在继承GenericServlet类时,解决想要覆盖init(ServletConfig config)方法忘记给config赋值的问题。此时,只需要覆盖init()方法即可。

    • init()方法不是生命周期方法,但想要在构造Servlet时让Tomcat调用该方法,需要在init(ServletConfig config)中调用init()方法

  • GenericServlet实现了所有ServletConfig的方法。

 

5. HttpServlet类

  • HttpServlet是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。

  • HttpServlet覆盖了service()方法

    • HttpServlet中有两个service()方法,一个service(ServletRequest,ServletResponse),另一个为service(HttpServletRequest,HttpServletResponse),前者为覆盖,后者不是覆盖。

    • service(ServletRequest,ServletResponse)是生命周期方法,由Tomcat自动调用,在该方法中

      • 首先对两个参数强制转换,将类型转换为Http协议相关的类型,

      • 再调用service(HttpServletRequest,HttpServletResponse)方法,

      • 该方法会通过request得到当前请求的请求方式(GET或POST),

      • 再根据请求方式调用相应的doGet()和doPost()方法。

    • 所以,不用重写service()方法只需要重写doGet()和doPost()方法如果没有覆盖doGet()和doPost()方法,并且被调用了,会出现405。

 

6. Servlet细节

  • Servlet只有一个实例对象,就有可能会现时出一个Servlet同时处理多个请求

    Servlet不是线程安全的。这说明Servlet的工作效率很高,但也存在线程安全问题!所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

    做到以下几点:

    • 不要在Servlet中创建成员,创建局部变量即可

    • 可以创建无状态成员,即只声明

    • 可以创建有状态的成员,但状态必须为只读的

  • 默认情况下,服务器会在某个Servlet第一次收到请求时创建它。也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。

<servlet>
<servlet-name>hello1</servlet-name>
<servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello1</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping><servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>

  <load-on-startup>中,给出一个非负整数。值小的先被创建,即hello1先创建,hello2后创建。

  • <url-pattern>

    • 用来指定Servlet的访问路径,可以在<servlet-maping>中有多个

    • 可以使用通配符*,通配符要么为前缀,要么为后缀,不能出现在URL中间位置,也不能只有通配符

      路径匹配:<url-pattern>/servlet/*</url-pattern>,可以匹配/servlet/a、/servlet/b等

      扩展名匹配:<url-pattern>*.do</url-pattern>,可以匹配/abc/def/ghi.do、/a.do等

      啥都匹配:<url-pattern>/*</url-pattern>,可以匹配所有url

  • web.xml文件的“继承”

    • 每一个JavaWeb应用都有一个web.xml,都“继承”conf/web.xml

<?xmlversion="1.0" encoding="ISO-8859-1"?><web-appxmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 version="3.0">
    <servlet>
       <servlet-name>default</servlet-name><!--他的优先级最低,如果请求没人处理,那么它就会来处理,显示404-->
       <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
       <init-param>
           <param-name>debug</param-name>
           <param-value>0</param-value>
       </init-param>
       <init-param>
           <param-name>listings</param-name>
           <param-value>false</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
</servlet><servlet>
       <servlet-name>jsp</servlet-name>
       <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
       <init-param>
           <param-name>fork</param-name>
           <param-value>false</param-value>
       </init-param>
       <init-param>
           <param-name>xpoweredBy</param-name>
           <param-value>false</param-value>
       </init-param>
       <load-on-startup>3</load-on-startup>
   </servlet><servlet-mapping>
       <servlet-name>default</servlet-name>
       <url-pattern>/</url-pattern>  <!--没有url能匹配上,就会匹配这个-->
   </servlet-mapping><servlet-mapping>
       <servlet-name>jsp</servlet-name>
       <url-pattern>*.jsp</url-pattern>
       <url-pattern>*.jspx</url-pattern>
   </servlet-mapping><session-config>  <!--session的过期时间为30分钟-->
       <session-timeout>30</session-timeout>
   </session-config><!-- 这里省略了大概4000多行的MIME类型的定义,这里只给出两种MIME类型的定义 -->
   <mime-mapping>
       <extension>bmp</extension>
       <mime-type>image/bmp</mime-type>
   </mime-mapping>
   <mime-mapping>
       <extension>htm</extension>
       <mime-type>text/html</mime-type>
   </mime-mapping><welcome-file-list>
       <welcome-file>index.html</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
</web-app>
 

7. ServletContext

  • 概述

    • 一个项目只有一个ServletContext对象,我们可以在很多个Servlet中来获取这个唯一的对象,使用它可以给Servlet传递数据,完成共享数据。

    • ServletContext对象在Tomcat启动时创建,在Tomcat关闭时销毁

  • 获取ServletContext

    在Servlet接口中,init(ServletConfig config)方法可以获取ServletConfig对象,该对象有getServletContext()方法可以获取ServletContext对象

public class MyServlet implements Servlet {
    public void init(ServletConfig config) {    
        ServletContext context = config.getServletContext();
    }
    …
}    
  在GenericServlet类中,有成员变量ServletConfig,有getServletContext()方法可以获取ServletContext对象
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
    ServletContext context = this.getServletContext();
  }
}
  • 域对象的功能

    • 域对象是用来在多个Servlet中传递数据,所以域对象必须要有存和取数据的功能。JavaWeb中包含四个域对象,分别是ServletContext、PageContext、HttpSession、ServletRequest

    • ServletContext对象用来操作数据的方法

      • void setAttribute(String name, Object value):用来存储一个对象,相当于在ServletContext中有一个Map对象,所以在存储时name值不能相同

      • Object getAttribute(String name):用来获取数据,因为返回值为Object对象,需要强制转换

      • void removeAttribute(String name):删除一个对象

      • Enumeration getAttributeNames():获取所有域属性的名称

  • 获取初始化参数

    • Servlet也可以获取初始化参数,但它只能获取局部的初始化参数,即只能获取自己的初始化参数

    • 使用ServletContext可以配置公共的初始化参数

<web-app...>
...
 <context-param>
<param-name>paramName1</param-name>
<param-value>paramValue1</param-value>
 </context-param>
 <context-param>
<param-name>paramName2</param-name>
<param-value>paramValue2</param-value>
 </context-param>
</web-app>
ServletContext context = this.getServletContext();
String value1 = context.getInitParameter("paramName1");
String value2 = context.getInitParameter("paramName2");
System.out.println(value1 + ", " + value2);
  • 获取相关资源的方法

    • 获取真实路径

      • 获取a.txt的真实路径String realPath = this.getServletContext.getRealPath("/a.txt");

      • windows系统下这种方法获取的路径是代盘符的

    • 获取资源流

      • 获取a.txt的t资源流:InputStream in = this.getServletContext.getResourceAsStream("/a.txt");

    • 获取指定目录下所有资源路径

      • 获取/WEB-INF下所有资源的路径:Set set = this.getServletContext.getResourcePaths("/WEB-INF");

猜你喜欢

转载自www.cnblogs.com/jyliu/p/10606657.html