Java——Servlet

一、什么是Servlet

servlet是java ee最早提出的web组件模型。Servlet只能运行在java ee的web容器中。

 

二、Servlet工作流程

1、初始化

每个servlet都对应一个url地址。当Web容器接受对url地址的请求信息后,根据url地址与servlet之间的映射关系将请求转发到指定的servlet来处理。如果该Web容器不存在此servlet的实例,web容器将动态装入并实例化servlet。

2、请求处理

针对客户端的请求,web容器将产生一个新的线程来调用servlet的service() 方法。service() 方法检查http请求类型(GET\POST\PUT\DELETE等),然后调用相应的doGet()\doPost()\doPut()\doDelete()等方法。最常见的请求类型是GET和POST。二者区别是:如果以GET请求方式传输,请求参数会直接附加在请求的url上;如果以POST请求方式传输,则参数会被打包在数据包中传送给服务器。

注意:一个servlet同时只有一个实例,并且它在servlet的使用期间将一直保留。当有多个请求发送到同一个servlet时,服务器将会为每个请求创建一个新的线程来处理客户端的请求。

3、退出

当处理完客户端请求后,servlet的实例并不会立即被web容器销毁。只有web应用程序关闭或servlet已经空闲很长时间,web容器才会将servlet视力从内存移除。移除之前web容器会调用servlet的destroy() 方法。

servlet可以使用这个方法关闭数据库连接、中断后台线程、向磁盘写入Cookie列表及执行其他清理动作。注:若web容器出现意外而被关闭,则无法保证destroy()方法被调用。

从上面servlet工作流可以看出,客户端和servlet并没有直接交互,无论客户机对servlet的请求还是servlet对客户端的相应,都是通过web容器来实现的,这确保了servlet组件的可移植性。

web容器的职责归纳为:

  1. 管理servlet组件的生命周期,负责servlet组建的初始化、销毁等;
  2. 将请求映射到对应的servlet,并将生成的响应返回给指定的 客户端。

Servlet的工作流充分体现了java ee“组件-容器”的核心编程思想。

 

三、Servlet API

  • HttpServlet:基于web的servlet组件通常继承此接口,完成对客户端请求的处理。
  • HttpServletRequest:代表发送到servlet组件的请求。
  • HttpServletResponse:代表从servlet组件返回客户机的响应。
  • HttpSession:代表在web应用运行过程中用来保存特定客户端状态信息的空间。
  • ServletContext:代表servlet组件的运行环境信息。
  • ServletConfig:代表servlet组件的配置信息。
  • ServletException:代表servlet组件运行过程中抛出的意外对象。
  • RequestDispatcher:请求转发器,可以将客户端请求从一个servlet转发到另外其他的服务器资源如其他servlet、静态html页面等。

四、第一个Servlet

编写servlet组件:

  1. 创建一个实现javax.servlet.http.HttpServlet接口的类。
  2. 重写doGet() 或doPost()方法,实现对HTTP请求信息的动态响应。

自Java EE5 规范以后,可使用注解代替复杂的配置文件。 

下面是个例子:

@WebServlet("/servlet-first")
public class Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charest=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Servlet First</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h1>Hello! This is first Servlet!</h1>");
		out.println("</body>");
		out.println("</html>");
		out.close();		
	}
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

}

运行tomcat,浏览器打开输入”http://localhost:8080/ServletDemo/servlet-first“即可。

注:在类前定义一个注解@WebServlet,它包含两个属性name和URLPattern,分别用来定义servlet组件的名称和URL模式。当部署此组件时,web容器会根据此注解自动完成对此servlet组件的部署配置。使用注解@WebServlet,需引用javax.servlet.annotation.WebServlet。

 

五、处理请求

下面是个例子:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>处理请求</title>
</head>
<body>
<form name = "form1" method="post" action="getInf">
	<table>
		<tr><td>姓名</td><td><input type="text" name="name"></td></tr>
		<tr><td>年龄</td><td><input type="text" name="age"></td></tr>
		<tr><td>出生日期(yyyy-mm-dd)</td><td><input type="text" name="birthday"></td></tr>
		<tr><td>爱好兴趣</td></tr><tr><td><input type="checkbox" name="checkbox1" value="阅读">阅读
							    <input type="checkbox" name="checkbox1" value="运动">运动  
							    <input type="checkbox" name="checkbox1" value="音乐">音乐  
							    <input type="checkbox" name="checkbox1" value="美食">美食
							   </td></tr>
	</table>
	<input type="submit" name="Submit" value="提交">
</form>
</body>
</html>

 

@WebServlet("/getInf")
public class GetInf extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		try {
			String name = request.getParameter("name");
			String age = request.getParameter("age");
			String dateString = request.getParameter("birthday");
			SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");	
			java.util.Date birth = format.parse(dateString);
			String[] paraValues = request.getParameterValues("checkbox1");
			String hobbies = new String("");
			for(int i =0; i<paraValues.length;i++){
				hobbies += paraValues[i]+"";
			}
			out.println("<html>");
			out.println("<head>");
			out.println("<title>Servlet GetInf</title>");
			out.println("</head>");
			out.println("<body>");
			out.println("<h1>姓名"+ name +"</h1>");
			out.println("<h1>年龄"+ age +"</h1>");
			out.println("<h1>出生日期"+ birth +"</h1>");
			out.println("<h1>爱好"+ hobbies +"</h1>");		
			out.println("</body>");
			out.println("</html>");
		} catch (ParseException e) {
			e.printStackTrace();
		} finally{
			out.close();
		}
		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

六、使用Filter过滤请求

除了利用servlet组件直接处理客户端请求外,java ee还提供一个组件来实现对请求信息的过滤处理,称为Filter。与servlet不同,他无法生成对客户端的响应,但filter能够拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间的交换数据。filter可以改变一个请求或者修改响应。filter与servlet的关联由web应用的配置文件或注解来明确。

用户发送请求给servlet时,在servlet处理请求前,首先由于此servlet关联的filter执行,然后才是servlet的执行。如果一个servlet有多个filter,则根据配置的前后次序执行。

Filter主要用于以下场景:

  • 访问特定资源(web、jsp、servlet)时验证身份。
  • 访问资源的记录跟踪。
  • 访问资源的转换。

一个Filter必须实现javax.servlet.Filter接口,即实现以下三个方法:

  1. doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 。用来实现过滤行为的方法。引入的FilterChain对象提供了后续Filter所要调用的信息。
  2. init(FilterConfig fConfig)。由容器所调用的Filter出师方法。
  3. destroy() 。

下面是个例子:

@WebFilter(filterName="/IPFilter", urlPatterns={"/*"})
public class IPFilter implements Filter {

	private FilterConfig fConfig = null;

	public void destroy() {
		this.fConfig  = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		String ipAddress = request.getRemoteAddr();
		System.out.println("IP" + ipAddress +", Time" + new Date().toString());
		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {
		this.fConfig  = fConfig;
	}

}

 注:

  过滤器有两种映射模式:

  •   对URL模式的映射,这也是默认的映射模式。在URL模式中可以试用通配符,如"/*"。
  •   对servlet的映射。这时过滤器关联的是servlet的逻辑名称。

与servlet一样,新版本的java ee规范中,提供了注解@WebFilter来部署Filter组件,其属性filterName为Filter的逻辑名称, 属性urlPatterns为Filter的URL模式。

程序包含了Filter必须实现的三个接口方法:init()、destroy()和doFilter()。当容器第一次加载该过滤器时,init()方法被调用。该类这个方法包含了一个指向FilterConfig对象的引用。对请求和响应的过滤功能主要由doFilter()实现。web容器在垃圾收集之前调用destroy()方法,以便能够执行任何必须清理的代码。

posted @ 2015-09-22 16:52  iCcccy  阅读(284)  评论(0编辑  收藏  举报