Servlet概念框架
以 Servlet 3.0 源代码为基础。Servlet 是 Javaweb 应用的基础框架,犹如孙子兵法之于作战指挥官,不可不知。
概念框架
-
机制: 事件 Event, 监听器 Listener
-
数据: 配置 Config, 上下文 Context, 会话 Session,Cookie; 属性 Attribute, 参数 Parameter, 首部 Header
-
服务: 核心 Servlet, 过滤 Filter, 转发 Dispatcher
-
IO: 请求 Request, 响应 Response ; 输入流 InputStream, 输出流 OutputStream
-
行为: 链 Chain, 注册 Register
-
方式: 同步 Syn , 异步 Asyn
-
协议: HTTP, SSL
-
其他: Characterset, URL, URI, Path, Encode, Decode
概念组合
-
Servlet: init(ServletConfig) -> service(ServletRequest,ServletResponse) -> destroy() ;Servlet 必须是线程安全的;
-
ServletConfig: Servlet配置数据,在初始化Servlet实例后获得, 包括 ServletName, ServletContext, initParameters;
-
ServletRequest: 客户端请求数据,包括 属性名值,参数名值,字符编码集,内容长度及类型,输入流,Servlet信息, Locale等;
-
ServletResponse:服务端返回数据,包括 字符编码集,内容长度及类型,输出流,Locale,Buffer及操作等。
-
ServletInputStream: 从客户端请求中读取字节流数据;从 ServletRequest 中获取。
-
ServletOutStream: 将字节流数据写入响应内容中;从 ServletResponse 中获取。
-
ServletContext:Servlet运行时上下文,主要与 Servlet容器通信。
-
Filter: init(FilterConfig) -> doFilter(ServletRequest,ServletResponse,FilterChain) -> destroy() ; Filter在Servlet处理之前对客户端请求作预处理,在Servlet处理之后对响应数据做后处理。实际应用中通常包括字符编码、日志审计、安全访问控制等过滤器。
-
FilterConfig: Filter 配置数据,在初始化Filter实例后获得,包括 FilterName, ServletContext, initParameters
-
FilterChain: 在过滤器中调用 chain.doFilter(ServletRequest,ServletResponse), 将请求传递给过滤器链上的下一个过滤器进行处理。
-
HttpServlet: 子类化 HttpServlet 用于定义处理请求的服务程序;一般覆写 doGet 或 doPost 方法。
-
HttpServletRequest:Servlet请求数据,包括请求头、Cookie, 请求方法,请求路径,登录用户,Session等。
-
HttpServletResponse: HTTP响应码定义,添加、设置或获取【响应头,Cookie,状态码,错误码】,重定向,URL编码等。
-
HttpSession: 包括 ID,创建时间,最近访问时间,ServletContext, 会话失效时间,属性名值,属性名集,属性值集等。
-
Cookie: 客户端标识信息,Servlet 实例可以在 HttpServletResponse.addCookie 方法中添加 Cookie 信息并发送给客户端。Cookie 在请求头或响应头里添加。
- ServletRequestEvent, ServletRequestListener, ServletRequestAttributeEvent, ServletRequestAttributeListener,ServletContextEvent, ServletContextListener, ServletContextAttributeEvent, ServletContextAttributeListener, HttpSessionEvent, HttpSessionListener, HttpSessionBindingEvent, HttpSessionBindingListener, HttpSessionAttributeListener: 当相应的对象或值改变时对应的事件及监听器。
Servlet3.0增强
注解
有了注解,就不需要在 web.xml 部署文件中声明 servlet, filter, listener 等,减少部署文件的体积,提高可维护性。
-
WebServlet: 声明一个 Servlet,属性主要有 name, value, urlPatterns, initParams, asyncSupported, description, displayName;
-
WebFilter: 声明一个 Filter, 属性主要有 name, value, urlPatterns, initParams, servletNames, dispatcherTypes
asyncSupported, description, displayName;
-
WebListener: 声明一个Web监听器,属性为name, 值为【ServletContextListener, ServletContextAttributeListener, javax.servlet.ServletRequestListener,ServletRequestAttributeListener,HttpSessionListener,HttpSessionAttributeListener】之一。
-
WebInitParam: 在 Servlet, Filter 上声明初始化参数,属性有name, value, description
-
MultipartConfig: 应用于 Servlet 用于处理文件上传,属性有location, maxFileSize, maxRequestSize,fileSizeThreshold
-
ServletSecurity: 声明 Servlet 的安全约束,属性有value, httpMethodConstraints
-
HandlesTypes: 声明 ServletContainerInitializer 的实现类的方法参数中所能处理的类型集合。
异步
-
AsyncEvent: 当调用 servletRequest.startAsync方法或该方法【完成|超时|产生错误】时,将产生一个异步事件。
-
AsyncListener:异步事件监听器,需要实现 【onStartAsync|onComplete|onTimeout|onError】(AsyncEvent)方法。
-
AsyncContext: 异步上下文。
-
ServletRequest.startAsyn方法提供了在Servlet中进行异步处理的特性。
Servlet要点
事件机制
-
当事件源发生某种变化时,运行容器将分派对应的监听器处理程序来处理相应的事件。Servlet里的事件源主要有Request, Context, Attribute 等。
-
事件机制的底层实现可基于观察者/订阅者模式,使用多线程或多进程与信号机制实现。主线程或主进程执行具体逻辑产生事件并发送信号来通知变化,守护线程或守护进程监听到信号和通知后分派相应的监听器程序来处理。可以在应用启动时预先注册事件类型与监听器程序的对应关系,亦可在运行中动态绑定或解绑。
-
以 ServletRequestAttributeEvent 为例。只要编写相应的监听器类 RequestAttributeListenerImpl (实现 ServletRequestAttributeListener ) , 并在 web.xml listener 元素 ( 或使用注解 WebListener ) 声明该监听器后,当在应用中写下 request.setAttribute(name, value) 或 request.removeAttribute(name,value) 就会自动触发 RequestAttributeListenerImpl 里的逻辑。
数据信息
-
Servlet, Filter 可以从请求 Request (参数 Parameter)、配置 Config 、环境 Context、环境或自定义属性 Attribute 以及会话 (Session, Cookie) 中获取处理请求所需要的信息;
-
Dispatcher 可以从部署文件或项目配置文件中读取 URL 映射配置, 将来源于客户端的 URL 请求映射到指定的 Servlet / Controller 。
输入输出
-
最底层是字节流(InputStream, OutputStream) 和 字符流 (Reader, Writer)
-
其上是各种源的字节流和字符流。源主要有: String, File, NetworkResource 等
-
语义层面是请求与响应: HttpServletRequest , HttpServletResponse。
会话追踪
- 为了始终如一地标识和处理同一个客户端发出的有紧密业务关联的请求链,使用客户端 Cookie 和 服务端 Session 机制。浏览器可以检测客户端Cookie 以判断用户是否登录, 服务器可以检测 Session 里的登录信息判断用户是否登录。
Ajax与异步Servlet
-
Ajax 是浏览器实现的通信封装。当与服务器通信时,在发送请求后会立即返回,不阻塞用户后续操作;而在之后会检查请求状态,在完成后获取服务器返回的数据并更新页面。Ajax 是客户端异步技术,改善客户端响应体验。
-
Ajax 通常应用于富客户端应用场景。在这种场景中,静态内容和交互设计占据页面内容的绝大部分,而动态内容仅占其中一小部分。如果服务端每次都返回整个页面内容,势必耗费大量网络带宽。而 Ajax 通信仅返回客户端刷新所需要的数据。在 Ajax 应用中,服务端提供的是一段数据, 而不是页面或文件。
-
Servlet 本身是同步的。处理客户端请求之后才返回响应。异步 Servlet 则会将请求中耗时长的部分抽离出来异步处理,耗时短的部分完成后就退出线程,减少长耗时请求对Servlet线程的占用,改善应用系统的吞吐量和负载。异步 Servlet 是服务端异步技术。【异步Servlet 待实验】
首部
-
请求头:主要包括 【Host, Connection, Cache-Control, Accept, Upgrade-Insecure-Requests, User-Agent, Accept-Encoding, Accept-Language, If-Modified-Since】
-
响应头: 主要包括【Content-Length,Content-Type,Server,Set-Cookie】
-
请求头示例:【Host=localhost:8082;Connection=keep-alive;Cache-Control=;max-age=0;Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Upgrade-Insecure-Requests=1;User-Agent=Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36;Accept-Encoding=gzip, deflate, sdch;Accept-Language=zh-CN,zh;q=0.8;If-Modified-Since=Wed, 17 Feb 2016 02:20:01 GMT】
- 响应头示例:【Content-Type: text/plain;charset=UTF-8;Set-Cookie: me=qinshuq;Domain=localhost;Content-Length: 5;Server: Jetty(7.2.2.v20101205)】
路径
Request: http://localhost:8082/servlets/AutoCompleteServlet?inputText=sh
-
RequestUrl = http://localhost:8082/servlets/AutoCompleteServlet ; RequestUrl: [协议]😕/servName:servPort/contextPath/servletPath ; RequestUrl 不包括 QueryString 。
-
RequestURI = /servlets/AutoCompleteServlet ; 资源标识符。 ContextPath (不含) 到 QueryString (不含) 之间的部分。
-
ServletPath = /servlets/AutoCompleteServlet ; 映射到 Servlet 实例的路径标识。
-
ContextPath = ; 应用路径,可在Servlet服务器部署文件中指定。若Servlet在根路径下,默认为空字符串“” ;若 请求为 http://localhost:8082/autocomplete/servlets/AutoCompleteServlet?inputText=sh , 则 ContextPath = /autocomplete
-
QueryString: inputText=sh 。 查询字符串,通常是请求中问号之后的部分。
-
若请求为 Request: http://localhost:8082/, 则: RequestUrl = http://localhost:8082/ , RequestURI = /, ServletPath = /,ContextPath = “”, QueryString = null
示例
代码阅读小记
-
边读代码边做笔记是一个好习惯。
-
概念-属性-联系-模型-架构。