Servlet总结
@ kingkiller | Thursday, Jan 28, 2021 | 6 minutes read | Update at Thursday, Jan 28, 2021

javaee 中servlet的简单教学,虽说j2ee已经是遥远时代,但是java web开发依然无法离开servlet,从底层学起,详细了解web实际的运行过程,会对将来学习框架更有帮助

Servlet总结

1.Servlet接口

创建HelloServlet实现Servlet接口,作为实例代码

1.Servlet生命周期方法:以下方法都是Servlet容器负责调用(tomcat就是一个Servlet容器)

​ 1.构造方法

​ 只要第一次请求Servlet时,创建实例,调用构造器.说明Servlet是单实例的

    public HelloServlet() {
        // TODO Auto-generated constructor stub
        System.out.println("HelloServlet's constructor");
    }

​ 2.init()方法:只被调用一次,在创建好实例后立即被调用.用于初始化当前的构造方法

  @Override
    public void init(ServletConfig config) throws ServletException {
    }

3.service()方法:被调用多次,每次请求都会调用service方法.实际用于响应请求

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("service");
        
    }

4.destroy()方法:只被调用一次,在当前Servlet所在的WEB应用被卸载前调用.用于释放当前Servlet所占用的资源

@Override
    public void destroy() {
        // TODO Auto-generated method stub
        System.out.println("destroy");
    }

2.servlet配置web.xml

每创建一个Servlet需要在web.xml中配置相关信息

<servlet>
	<!-- Servlet的名字 -->
    <servlet-name>helloServlet</servlet-name>
    <!-- Servlet的java文件的路径 -->
    <servlet-class>com.kingkiller.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <!-- Servlet的名字,需和上面的相同 -->
    <servlet-name>helloServlet</servlet-name>
      <!-- Servlet的url路径 -->
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

load-on-startup参数:

1.配置在servlet节点中 2.可以指定Servlet被创建的时机,若为负数,则在第一次请求时被创建,若为0或正数,则在当前WEB应用被Servlet容器加载时创建实例,且数值越小越早被创建

  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.kingkiller.HelloServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

3..Servlet映射的细节

1.同一个Servlet可以被映射到多个URL上,即多个元素的子元素的设置可以是同一个Servlet的注册名。 2.在Servlet映射到URL中也可以使用通配符,但是只能有两种固定的格式,一种格式是".拓展名",另一种格式是以正斜杠(/)开头并以"/*“结尾

2.ServletConfig

封装了Servlet的配置信息,并且可以获取ServletContext对象

1.获取参数的方法

​ 1.getInitParameter(String name):获取指定参数名的初始化参数

​ 2.getInitParameterNames():获取参数名组成的Enumeration对象

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        String user = config.getInitParameter("user");
        System.out.println("user:"+user);
        Enumeration<String> names = config.getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            System.out.println("name"+name);
        }
  	}

2.获取Servlet名字的方法

​ 1.getServletName:获得注册的Servlet的名字

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		String servletName = config.getServletName();
         System.out.println(servletName);
  	}

3.获取Context的方法

​ 1.getServletContext:返回这个Servlet的ServletContext对象。

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		ServletContext servletContext = config.getServletContext();	
  	}

3.ServletContext接口

1.可以由servletConfig获取 2.对象代表当前WEB应用:可以认为ServletContext是当前WEB应用的一个大管家,可以从中获取到WEB应用的各个方面的信息

1.获取当前WEB应用的初始化参数

1.在web.xml配置当前WEB应用的初始化参数

<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.kingkiller.HelloServlet</servlet-class>
    <init-param>
      <param-name>user</param-name>
      <param-value>root</param-value>
    </init-param>
    <init-param>
      <param-name>password</param-name>
      <param-value>1234</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

注意放在load-on-startup前

2.常用方法:

​ getInitParameter(): Returns a String containing the value of the named context-wide initialization parameter, or null if the parameter does not exist.

​ getInitParameterNames(): Returns the names of the context’s initialization parameters as an Enumeration of String objects, or an empty Enumeration if the context has no initialization parameters.

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		ServletContext servletContext = config.getServletContext();
         String driver = servletContext.getInitParameter("driver");
         System.out.println("driver:"+driver);
         Enumeration<String> names2 = servletContext.getInitParameterNames();
         while (names2.hasMoreElements()) {
            String name = names2.nextElement();
            System.out.println(" -->" + name);
         }
  	}

2.获取当前web应用的某一个文件在服务器上的绝对路径,而不是部署前的路径

1.getRealPath(String path): Returns a String containing the real path for a given virtual path.

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		ServletContext servletContext = config.getServletContext();
         String realPath = servletContext.getRealPath("/note.txt");
         System.out.println(realPath);
  	}

3.获取当前WEB应用的名称

1.getContextPath(): Returns the context path of the web application.

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		ServletContext servletContext = config.getServletContext();
         String contextPath = servletContext.getContextPath();
         System.out.println(contextPath);
  	}

4.获取当前WEB应用的某一个文件对应的输入流

1.getResourceAsStream(String):Returns the resource located at the named path as an InputStream object.

 @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
		ServletContext servletContext = config.getServletContext();
          try {
            ClassLoader classLoader = getClass().getClassLoader();
            InputStream is = classLoader.getResourceAsStream("jdbc.properties");
            System.out.println("1." + is);
        } catch (Exception e) {
            // TODO: handle exception
        }
        try {
            InputStream is2 = servletContext.getResourceAsStream("/WEB-INF/classes/jdbc/properties");
            System.out.println("2." + is2);
        } catch (Exception e) {
            // TODO: handle exception
        }
  	}

path的”/“为当前WEB应用的根目录

5.和attribute相关的方法

4.在Servlet中获取请求信息

​ Servlet的service()方法用于应答请求:因为每次请求都会调用service()方法 ​ ServletRequest:封装了请求信息.可以从中获取到任何的请求信息. ​ ServletResponse:封装了响应信息,如果想给用户什么响应,具体可以使用该借口的方法实现 ​ 这两个接口的实现类都是服务器给予实现的,并在服务器调用service方法时传入

​ 下面将会详细讲述ServletRequest和ServletResponse这两个接口

创建login.html做测试

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<form action="longinServlet" method="post">
		user:<input type="text" name="user"/>
		password:<input type="password" name="password"/>
		<br><br>
		interesting:
		<input type="checkbox" name="interesting" value="reading"/>Reading
		<input type="checkbox" name="interesting" value="game"/>Game
		<input type="checkbox" name="interesting" value="party"/>Party
		<input type="checkbox" name="interesting" value="shopping"/>Shopping
		<input type="checkbox" name="interesting" value="sport"/>Sport
		<input type="checkbox" name="interesting" value="tv"/>TV
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

5.ServletRequest接口

1.获取请求参数

1.String getParameter(String name):以一个String返回指定的参数的值,如果这个参数不存在返回空值.但若接收的参数值为多个时,只能接收第一个的值

2.Enumeration getParameterNames():返回所有的参数名的String对象列表,如果没有输入参数,则该返回一个空值

3.String[] getParameterValues(String name):通过一个String对象的数组返回指定参数的值,如果这个参数不存在,该方法返回一个空值

4.Map getParameterMap():返回请求参数的键值对,key:参数名,value:参数值.

    @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("请求来了");
        System.out.println(request);
        String user = request.getParameter("user");
        String password = request.getParameter("password");
        System.out.println(user+":"+password);
        String interesting = request.getParameter("interesting");
        System.out.println(interesting);
        String[] interestings = request.getParameterValues("interesting");
        for (String interest : interestings) {
            System.out.println(interest);
        }
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String val = request.getParameter(name);//因为这里用的是getParameter所有在传入多个参数时只获取到第一个
            System.out.println(name + ":" + val);
        }
        Map<String, String[]> map = request.getParameterMap();
        for (Entry<String, String[]>  entry : map.entrySet()) {
            System.out.println(entry.getKey() + ":" + Arrays.asList(entry.getValue()));
        }
     }

2.获取请求的url

需要强转成其子类HttpServletRequest,再调用getRequestURI()方法

    @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String requestURI = httpServletRequest.getRequestURI();
        System.out.println(requestURI);
     }

3.获取请求方式

1.getMethod:也是HttpServletRequest里的方法

 @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String method = httpServletRequest.getMethod();
        System.out.println(method);
     }

4.若是一个GET请求,获取请求参数对应的字符串

即url中?后的部分

getQueryString()

 @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String queryString = httpServletRequest.getQueryString();
        System.out.println(queryString);
     }

5.获取Servlet的请求路径

即url-pattern

getServletPath()

 @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String servletPath = httpServletRequest.getServletPath();
        System.out.println(servletPath);
     }

6.和attribute相关的几个方法

6.ServletResponse接口

1.getWriter()

返回PrintWriter对象,调用该对象的print方法

 @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        PrintWriter out = response.getWriter();
        out.println("helloworld");
     }

2.设置响应的内容类型:

responseContentType()

 @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("application/msword");//设置响应类型为WORD文档,发送request请求后,会直接下载一个含有response内容的word文档
        PrintWriter out = response.getWriter();
        out.println("helloworld");
     }

3.请求重定向

void sendRedirect(String location):此方法定义在HttpServletResponse中定义

7.GenericServlet

1.是一个Servlet,是Servlet接口和ServletConfig接口的实现类.但是是一个抽象类,其中的service方法为抽象方法 2.如果新建的Servlet程序直接继承GenericServlet会使开发更加的简洁 3.具体实现: 1.在GenericServlet里面,声明了一个ServletConfig类型的成员变量, 在init(ServletConfig)方法中对其初始化 2.利用了servletConfig成员变量的方法实现了ServletConfig接口的方法 3.还定义了一个init()方法,在init(ServletConfig)方法中对其调用,子类可以直接重写init(),在其中实现对Servlet的初始化 4.不建议直接覆盖init(Servlet),因为如果忘记编写super(ServletConfig),则会出现空指针异常 5.新建的init()并非Servlet的生命周期方法,而init(ServletConfig)是生命周期方法

下面我们自已创建一个MyGenericServlet(不包含两个日志方法)

import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class MyGenericServlet implements Servlet,ServletConfig{
    /**
     * 下面是实现Servlet的方法
     */
    private ServletConfig config;
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return config;
    }
    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        this.config = config;
        init();
    }
    private void init() {
        // TODO Auto-generated method stub
    }
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
    /**
             * 下面是实现ServletConfig的方法
     */
    @Override
    public String getInitParameter(String name) {
        // TODO Auto-generated method stub
        return config.getInitParameter(name);
    }
    @Override
    public Enumeration<String> getInitParameterNames() {
        // TODO Auto-generated method stub
        return config.getInitParameterNames();
    }
    @Override
    public ServletContext getServletContext() {
        // TODO Auto-generated method stub
        return config.getServletContext();
    }
    @Override
    public String getServletName() {
        // TODO Auto-generated method stub
        return config.getServletName();
    }
}

8.HttpServlet

​ 1.是一个Servlet,继承自GenericServlet,针对HTTP协议定制 ​ 2.在service()方法中直接把ServletRequest和ServetResponse转为HttpServletRequest和HttpServletResponse ​ 并调用了重载的service(HttpServletRequest,HttpServletResponse)方法 ​ 在service(HttpServletRequest,HttpServletResponse)获取了侵权方式:request.getMethod()根据请求方式又创建 doPost,doGet方法 ​ 3.实际开发中,直接继承HttpServlet,并根据请求方式覆写doXxx()方法接口 ​ 4.好处:直接由针对性的覆盖doXxx()方法;直接使用HttpServletRequest合HttpServletResponse,不再需要强转

下面我们创建自己的MyHttpServlet进行测试

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 针对HTTP协议定义的一个Servlet基类
 * @author Administrator
 *
 */
public class MyHttpServlet extends MyGenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        if (req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest)req;
            if (res instanceof HttpServletResponse) {
                HttpServletResponse response = (HttpServletResponse) res;
                service(request, response);
            }
        }
    }
    public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求方式
        String method = request.getMethod();
        //2.根据请求方式再调用对应的处理方法
        if ("GET".equalsIgnoreCase(method)) {
            doGet(request,response);
        }
        if ("POST".equalsIgnoreCase(method)) {
            doPost(request,response);
        }
    }
    public void doPost(HttpServletRequest request,
            HttpServletResponse response) {
        // TODO Auto-generated method stub
    }

    public void doGet(HttpServletRequest request,
            HttpServletResponse response) {
        // TODO Auto-generated method stub      
    }
}

java
Save as image