Servlet详解(与SpringMVC的联系)

Servlet的发展过程:

最先的服务器处理程序是CGI,其存在着每次须要对请求进行处理时新建一个CGI对象,因此在速度和内存方面都不是很让人满意;随着JAVA语言的兴起,其跨平台的特性,使得Servlet逐渐流行起来,而且Servlet是可复用的,因此Servlet逐渐取代CGI。html

Servlet是如何处理d对应的HTTP请求的呢?

  1. 客户端发起一个HTTP请求到服务器端;
  2. HTTP服务器收到HTTP请求,而后将请求转给Web容器进行处理;
  3. Web容器对HTTP请求内容进行解析,并将信息存储到HttpServletRequest中,并生成HttpResponse(用于存储要返回给客户端的信息),HttpSession(用于管理会话)等对象;
  4. Web容器根据请求的URL决定要转发给哪个具体的Servlet程序进行处理;
  5. 先由HttpServlet的service方法分析HTTP请求是Get,Post,Put,Delete等方法,而后决定调用选择的Servlet对应于每种请求对象的处理方法;
  6. Servlet处理完成后,将要返回的信息存储到HttpServletResponse对象种并返回给Web容器进行解析转换为HTTP响应并传回客户端。

Web容器是如何找到对应于具体URL的Servlet处理程序的呢?

那首先看Servlet的建立过程:

  1. 在Servlet3.0及之后开始支持经过@WebServelt标注给Web容器提供此Servlet对应的信息,如urlPatterns,name(没有定义时,默认值是Servlet的类名), loadOnStartup(用于表示该Servlet是预加载的,而不是等到须要用到再加载)等;使用web.xml配置同理;
  2. 用户编写的Servlet继承自HttpServlet,而后覆盖HttpServlet的doGet(),doPost()等该Servlet要覆盖的方法完成建立;
  3. 而后Web容器即可以读取这些注解提供的信息用于找到对应于具体URL的Servlet并进行加载用于处理。

如何经过HttpServlet的service方法进行HTTP方法的筛选呢?

用户编写的Servlet继承自HttpServlet,继承图以下:java

HttpServlet的内部字段以下:

  1. 首先final字符串常量定义了8种HTTP方法以及是否被修改的标识;
  2. 而后提供了对8种HTTP方法对应处理程序的默认实现,这些若是要用到会被覆盖;
  3. 因此着重看service方法,能够看到其输入参数为ServletRequest, ServletResponse,而没有Http的标识,这是由于在一开始设计Servlet时其面向的不止是处理HTTP请求,因此请求/相应对象的基本行为规范是在ServletRequest(包是javax.servlet),与HTTP相关的行为则由其子接口HttpServletRequest(包是javax.servlet,httpd)定义,因此在HttpServlet中要对该对象进行类型的强转;
  4. 在service方法中经过调用HttpServletRequest.getMethod()方法用于获得HTTP方法,并经过if语句进行相应处理方法的跳转。

如何经过HttpServletResponse对象将处理完的信息传回客户端呢?

经过向Response对象中写入HTML文档信息进行信息传输。

Servlet是可复用的:

了解完Web容器对HTTP消息的处理流程后,以前提到Servlet是可复用的,那是否意味着是线程共享的,那是否会产生线程不安全呢?web

理清这个问题咱们首先要看Web容器时如何加载Servlet的:

  1. 首先要知道的一点是Web容器是一段Java程序,运行在JVM之上,是JVM的一个进程,能够想一想是否是经过localhost:8080端口访问的Tomcat容器呢?
  2. 而后与传统的Java容器不一样的是,Web容器不只持有对象,还负责对象的生命周期与相关服务的链接。
  3. Web容器会为每个请求加载对应的Servlet实例(若是尚未加载过),并分配一个线程,因此可能存在多个线程共享一个Servlet实例的问题,能够用ThreadLocal解决,或者将对URL请求的处理与对数据业务逻辑的处理分隔开,即便用MVC框架,而后在数据业务逻辑中使用锁等机制保证数据的安全性。

使用Servlet实现MVC框架:

  1. 首先实现Model(即一个普通的POJO),而后提供get,set机制;
  2. Controller:一个Servlet
@WebServlet("/HelloController")
public class HelloController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private HelloModel model = new HelloModel();
     
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		Cookie[] cookies = request.getCookies();
		if(cookies != null) {
			for(Cookie cookie : cookies) {
				String cookieName = cookie.getName();
				String cookieValue = cookie.getValue();
				request.setAttribute("name", cookieName);
				request.setAttribute("value", cookieValue);
			}
		}
		else {
			Cookie cookie = new Cookie("user", "cjc");
			cookie.setMaxAge(7 * 24 * 60 *60);
			response.addCookie(cookie);
		}
		String name = request.getParameter("user");
		String message = model.doHello(name);
		request.setAttribute("message", message);

		request.getRequestDispatcher("HelloServlet").forward(request, response);
	}
}
复制代码

与SpringMVC一致,Controller处理完后须要返回model给View进行渲染,此处使用的是将model数据放入HttpServletRequest对象的属性中,而后经过RequestDispatcher对象将该请求(forward)转给HelloServlet进行处理,HelloServlet便是咱们的View; 3. View:一个Servlet,负责完善HttpServletResponse对象并返回给客户端;安全

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String user = request.getParameter("user");
		String message = (String) request.getAttribute("message");
		String cookieName = (String)request.getAttribute("name");
		String cookieValue = (String)request.getAttribute("value");
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Hello Servlet</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h1> Hello!" + user + "!</h1>");
		out.println(message);
		out.println("<h1> cookieName" + cookieName + cookieValue + "!</h1>");
		out.println("</body>");
		out.println("</html>");
		
		out.close();
	}

}

复制代码

至此,咱们经过Servlet实现了一个MVC框架,将处理URL的逻辑,业务逻辑和页面渲染逻辑分离开来,本来这些是经过一个Servlet完成的,这样可使系统解耦合,架构更加清晰,更容易维护。bash

相关文章
相关标签/搜索