《Head First Servlet&JSP》读书笔记

《Head First Servlet&JSP》读书笔记

自己最近在看《How Tomcat Works》这本书。Tomcat是Servlet容器,在这本书里面大量使用到了Servlet,但是自己对Servlet不是好清晰,所以花了2天时间读了这本书。

1. 概述

1.1 总结
总体的来说,《Head First Servelt&JSP》这本书还是非常不错的,对Servlet&Jsp介绍的挺细的且有主次区分,让人理解起来轻松。因为《Head First》系列都是通过半漫画形式讲解,所以书较厚,不过读起来轻松。因为自己之前就了解Servelt&Jsp,所以读起来挺快的。

1.2 目录

  1. 为什么使用Servlet&Jsp
  2. Web应用体系框架
  3. MVC迷你教程
  4. 作为Servlet
  5. 作为Web应用
  6. 会话状态
  7. 作为JSP
  8. 没有脚本的页面
  9. 强大的定制标记
  10. JSTL也有力不及的时候...
  11. 部署Web应用
  12. 要保密,要安全
  13. 过滤器的威力
  14. 企业设计模式

自己看了第1、2、3、4、5、6、7、11、13、14章。关于JSP方面自己看的较少,一来自己觉得现在流行前后端分离,使用JSP技术应该越来越少;二来自己就不喜欢类型View方面的东西,还是喜欢代码 ^ - ^

1.3 章节解释
第一章(为什么使用Servlet&Jsp):主要解释了Web客户端、服务器做了什么,以及它们之间的通信:HTTP协议。
第二、三章(Web应用体系框架、MVC迷你教程):个人觉得这一章讲的挺好的,也挺有用的。尤其对于知道怎么使用Servlet&Jsp或者使用Servlet框架(SpringMVC或Struts2),它将会让你了解整个Java Web的大体框架。如:一个HTTP请求的大体流程是什么样的;Web.xml的作用;为什么Web-INFO下是安全目录等等。
第四章(作为Servlet):主要讲了Servlet的生命周期、Servlet如何处理请求等等。
第五章(作为Web应用):主要讲了ServletConfig与ServletContext、8个监听器的使用、以及4个对象(ServletContext、ServletRequest 、ServletResponse、HttpSession)的生命周期、线程安全、作用域等等。
第六章(会话状态):主要讲了会话如何工作、如何创建、如何添加属性等等。
第七章(作为JSP):主要讲了JSP与Servlet的关系,一些JSP的基本用法等等。
第十一章(部署Web应用):主要讲了把Java Web项目部署到Servlet容器中使用(如Tomcat),与第一二章食用更佳。
第十三章(过滤器的威力):主要讲了Servlet中的Filter(过滤器)的使用。
第十四章(企业设计模式):讲了讲企业开发中的一些组件、以及Struts的MVC模式(有点老了,现在版本与它说的都不一样了)。

2. 一些总结吧


2.1 什么是容器?
容器是用来部署Servlet的容器,处理一切与Servelt相关的请求。如果Web服务器应用(如Apache)得到一个指向Servelt的请求(而不是其它请求,如请求静态资源),这时服务器会把该请求交给部署该Servlet的容器,由容器向Servlet提供请求与响应对象,调用Servlet的service()方法处理请求。注:Tomcat实际上Web服务器与Servlet容器的结合体,它既处理静态资源请求,也处理Servelt请求。

2.2 容器能提供什么?

  • 通信支持:Servlet不直接与客户端通信,而是由容器与客户端进行通信。所以Servlet中只需要写业务逻辑(解耦)。
  • Servlet生命周期的管理:注每个Servlet在容器中只有一个实例。
  • 多线程的支持:容器会自动为每个请求分配一个线程,并处理它。
  • JSP的支持:会把JSP自动编译为Servlet,并管理它。

2.3 容器如何管理Servlet

  • 容器会加载web.xml文件初始化一些信息(如Servelt与URL的对应关系),信息保存在ServletContext对象中。也就是说一个web.xml对应一个ServeltContext对象。
  • 容器会在请求到来之前实例化Servlet并初始化一些信息,可通过loadOnStartup字段配置什么时候实例化Servelt。
  • 容器调用Servelt的init()方法处理化一些信息,如配置Servlet时的init-Param信息。这些信息在ServletConfig对象中。也就是说每个Servlet都有自己对应的ServletConfig对象。
  • 容器会在请求到来时创建一个ServletRequest、ServletResponse对象,分配一个线程,调用对应的Servlet对象的service()方法进行处理。注意:Servlet只有一个对象实例,容器会为每个请求分配线程并调用Servlet的service(ServletReqeust req, ServletResponse resp)方法进行处理。
  • 容器调用Servlet的destory()方法进行销毁Servlet。

2.4 ServletContext与ServletConfig

  • ServeltContext应该叫做WebContext更好,它代表一个Web程序的上下文。我们可以在web.xml文件中context-param字段中初始化一些数据,但这些数据是线程不安全的。
  • ServletConfig代表Servelt配置的一些信息。其在Servlet的init(ServletConfig config)方法中进行初始化。在SSM框架中,我们就会在DispatcherServlet配置中初始化所有的spring容器中的对象。如下:

 

 1 <!-- 配置DispatcherServlet -->
 2 <servlet>
 3     <servlet-name>seckill-dispatcher</servlet-name>
 4     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 5     <!-- 配置springMVC需要加载的配置文件
 6     spring-dao.xml spring-service.xml spring-web.xml
 7     mybatis -> spring -> springMVC-->
 8     <init-param>
 9         <param-name>contextConfigLocation</param-name>
10         <param-value>classpath:spring/spring-*.xml</param-value>
11     </init-param>
12     <load-on-startup>1</load-on-startup>
13 </servlet>
14 <servlet-mapping>
15     <servlet-name>seckill-dispatcher</servlet-name>
16     <!-- 默认匹配所有的请求 -->
17     <url-pattern>/</url-pattern>
18 </servlet-mapping>

 

2.5 Servlet

  • Servlet的生命周期可以看上面的:容器如何管理Servlet。
  • Servlet处理请求时,容器通过调用其service()方法来处理请求,而service()方法通过查询Http的请求方法来调用对于的Servlet方法,如GET-->doGet(),POST-->doPost()。所以我们写Servlet时,需要继承HttpServlet,然后重写其doGet()、doPost()或doDelete()等方法,具体要看该Servlet处理什么请求方法。

注:Servlet需要在web.xml中注册

2.6 请求与响应

  • 容器会在HTTP请求到来时创建ServletRequest、ServletResponse对象。请求的所有信息都会保存在ServletRequest对象中,具体看它的API。响应的信息(包括响应头)都会写入ServletResponse对象。注:我们在使用ServletResponse对象直接发送给客户端消息时,必须设置Content-Type信息,否则客户端不能够解析该信息。

 

 1 @WebServlet(loadOnStartup=1, urlPatterns={"/test"})
 2 public class TestServlet extends HttpServlet {
 3     @Override
 4     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 5         HttpSession session = req.getSession();
 6         Map<String, String[]> map = req.getParameterMap();
 7         System.out.println("HTTP Query String:");
 8         for (Map.Entry<String, String[]> entry : map.entrySet()) {
 9             System.out.print("key: " + Arrays.toString(entry.getValue()));
10             System.out.println(" value: " + Arrays.toString(entry.getValue()));
11     }
12     String content = "<html>
" +
13                 "<head>
" +
14                 "</head>
" +
15                 "<body>
" +
16                 "Hello World" +
17                 "</body>
" +
18                 "</html>";
19         PrintWriter writer = resp.getWriter();
20         resp.setContentType("text/html");
21         writer.write(content);
22         writer.flush();
23     writer.close();
24     }
25 }
26 ----------萌萌的分割线---------
27 Request:
28 GET /test?id=10086&name=kanyuxia HTTP/1.1
29 Host: localhost:8080
30 Connection: keep-alive
31 Cache-Control: max-age=0
32 Upgrade-Insecure-Requests: 1
33 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36
34 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
35 Accept-Encoding: gzip, deflate, sdch, br
36 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
37 Cookie: JSESSIONID=jp3o7r8iufda1c2dykdfzlk5t
38 
39 ----------萌萌的分割线--------
40 Response:
41 HTTP/1.1 200 OK
42 Date: Wed, 19 Apr 2017 07:39:58 GMT
43 Content-Type: text/html;charset=ISO-8859-1
44 Transfer-Encoding: chunked
45 Server: Jetty(8.1.14.v20131031)
46 Request Headers
47 view parsed
48 
49 <html>
50 <head>
51 </head>
52 <body>
53 Hello World</body>
54 </html>
55 ----------萌萌的分割线---------
56 server console:
57 HTTP Query String:
58 key: [kanyuxia] value: [kanyuxia]
59 key: [10086] value: [10086]
View Code

 

2.7 重定向与转发

  • Servelt中的重定向可以使用HttpServletResponse的sendRedirect()方法,该方法相当于在响应头部中设置响应码301、响应头中的Location字段为重定向字段。
  • Servlet转发通过HttpServletRequest的getReqeustDispatcher()方法获得RequestDispatcher对象,然后通过该对象转发请求与响应对象。

具体使用可以看:《Spring实战》读书笔记--SpringMVC之forward与redirect

2.7 监听器
Servlet中有8下监听器,如下:

监听器接口事件类型
ServletContextListener ServletContextListener
ServletContextAttributeListener ServletContextAttributeEvent
HttpSessionListener HttpSessionEvent
HttpSessionBindingListener HttpSessionBindingEvent
HttpSessionAttributeListener HttpSessionBindingEvent
HttpSessionAcctivatioinListener HttpSessionEvent
ServletRequestListener ServletRequestEvent
ServletRequestAttributeListener ServletRequestAttributeEvent

具体使用看API吧。注:监听器需要在web.xml中注册

 1 @WebListener(value="TestListener")
 2 public class TestListener implements HttpSessionListener {
 3     public void sessionCreated(HttpSessionEvent se) {
 4         HttpSession session = se.getSession();
 5         System.out.println("服务器创建了HttpSession, Session Id 为:" + session.getId());
 6     }
 7     public void sessionDestroyed(HttpSessionEvent se) {
 8     HttpSession session = se.getSession();
 9     System.out.println("服务器销毁了HttpSession, Session Id 为:" + session.getId());
10     }
11 }
12 ----------萌萌的分割线---------
13 response:
14 Content-Type:text/html;charset=ISO-8859-1
15 Date:Wed, 19 Apr 2017 07:44:56 GMT
16 Expires:Thu, 01 Jan 1970 00:00:00 GMT
17 Server:Jetty(8.1.14.v20131031)
18 Set-Cookie:JSESSIONID=km2ogboi1e8i184272wq13myz;Path=/
19 Transfer-Encoding:chunked
20 
21 ----------萌萌的分割线---------
22 server console:
23 服务器创建了HttpSession, Session Id 为:1ttrgbo9io8gs11o9vwic1zvwx

2.8 Session与Cookies
Http协议是无状态协议,不能都保存相关信息。所以创建了Cookies、Session来保存相关信息。

  • Cookies是保存在保存在客户端的信息,每次Http请求都会把该URL下的所有Cookies发给服务器,服务器可以访问。但其不安全,因为保存在客户端,用户可以自行删除。服务器可以在响应头的Set-Cookies字段中设置Cookies。
  • Session可以对同一个客户在一定时间内保存一些信息。Session信息保存在服务器上面的,所以安全。Session是基于Cookies的,服务器第一下使用Session时,会给客户端发送Set-Cookies: JSESSIONID=***,设置一个SessionId。以后每次客户端发送请求都会发送该Cookies该服务器,所以服务器就知道该请求是谁的请求。
  • Servlet中HttpSession对象表示会话对象,我们可以HttpServletRequest对象的getSession()方法获得HttpSession对象,然后可以使用其方法处理相关逻辑。具体可以查看HttpSession的API。
  • HttpSession可以设置时间来控制其生命周期,也可以在web.xml中配置默认的HttpSession生命周期长度。

2.9 JSP

  • JSP会被容器自动转换、编译为Servlet类,所以其与Servlet类没有多大的区别。

3.0 过滤器 Filter
我们可以配置Filter拦截请求,Filter与Struts2中的Intercept原理一样。注:需要在web.xml中注册

  • FilterChain类型于栈。Filter在调用FilterChain的doFilter()方法之前拦截请求,之后拦截响应。
  • 如果直接给Servlet传递ServletResponse对象,Servlet响应会直接返回给客户端,不会经过Filter。所以如果要拦截响应,则需要FilterChain的doFilter()方法传递HttpServletResponseWrapper对象,最后响应才会进过Filter。其中:HttpServletWrapper使用了装饰器设计模式。
 1 @WebFilter(urlPatterns = "/*")
 2 public class EncodeFilter implements Filter {
 3     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
 4     request.setCharacterEncoding("UTF-8");
 5     chain.doFilter(request, response);
 6     }
 7     public void destroy() {
 8     }
 9     public void init(FilterConfig arg0) throws ServletException {
10     }
11 }
原文地址:https://www.cnblogs.com/maying3010/p/6734324.html