1. Web容器为每个请求分配一个线程
2. Web容器默认采用单Servlet实例处理请求.
3. Servlet3.0中可以使用注解定义Servlet匹配的URL, web.xml中的配置会覆盖Servlet中的标注配置
1 @WebServlet("/index") 2 public class IndexServlet extends HttpServlet { }
更高级的配置
1 @WebServlet(name = "index", //默认为Servlet类的完整名称 2 urlPatterns = {"/index", "/index.view"}, //可以匹配多个URL 3 initParams = { //配置多个初始化参数 4 @WebInitParam(name="username", value="admin"), 5 @WebInitParam(name="password", value="admin") 6 }, 7 loadOnStartup = 1 //默认为-1, 请求该Servlet时才加载 8 ) 9 public class IndexServlet extends HttpServlet { }
且需将web.xml文件头设置为
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> </web-app>
4. @WebServlet 属性列表
name | String | 指定Servlet的name属性, 等价于<servlet-name>, 如果没有显示指定, 则为类的全限定名 |
value | String[] | 该属性等价于urlPartterns属性, 两个属性不能同时使用 |
urlPatterns | String[] | 指定一组Servlet的URL匹配模式, 等价于<url-pattern> |
loadOnStartup | int | 指定Servlet加载顺序, 等价于<load-on-startup>. 大于等于0时, 表示应用启动时就加载; 小于0或未指定时表示请求时才加载; 正数值越小, 优先级越高 |
initParams | WebInitParam[] | 指定一组Servlet初始化参数, 等价于<init-param> |
asyncSupported | boolean | 声明Servlet是否支持异步操作模式, 等价于<async-supported> |
description | String | 该Servlet的描述信息, 等价于<description> |
displayName | String | 该Servlet的显示名, 通常配合工具使用, 等价于<display-name> |
5. WEB-INF中的文件和目录对外界是封闭的, 如果想访问其中的内容, 需要通过JSP或Servlet的请求转发(Forward)
6. 命令行打war包, 在项目目录下运行 jar cvf ../HelloWorld.war *
7. requestURI = contextPath + servletPath + pathInfo
分别对应HttpServletRequest的方法 req.getRequestURI(); req.getContextPath(); req.getServletPath(); req.getPathInfo();
8. 类的查找路径: /WEB-INF/classes --> /WEB-INF/lib --> 容器实现本身存放类或Jar的目录(如:Tomcat安装目录下的lib目录)
9. Servlet3.0中, JAR文件可以作为Web应用程序的模块(web-fragment.xml放在jar文件的META-INF目录). 可以在Eclipse中新建 Web Fragment Project
10. 在获取任何HttpServletRequest请求参数(req.getParameter("xxx"))前, 调用 req.setCharacterEncoding("UTF-8"); 设置字符集, 可以避免乱码. 只对请求body中的字符有效, 所以如果请求方法为Get, 则需如此转换 String name = new String(req.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");
11. 通过HttpServletRequest读取请求body
1 BufferedReader reader = req.getReader(); 2 String requestBody = ""; 3 String input = null; 4 while ((input = reader.readLine()) != null) { 5 requestBody += input; 6 }
12. Servlet3.0 中使用 req.getPart("xxx"); 处理上传文件, 但Servlet要加 @MultipartConfig 注解
13. 调用RequestDispatcher的 forward() 方法前不能有任何响应确认(向客户端输出); 使用 include() 时, 被包含Servlet中任何对请求头的设置都会被忽略.
14. 设置响应字符编码: resp.setLocale(Locale.SIMPLIFIED_CHINESE) 或 resp.setCharacterEncoding() 或 resp.setContentType(), 后两种会覆盖第一种.
15. 注销session: req.getSession().invalidate();
16. HttpSession并非线程安全
17. Servlet3.0中可以通过 getServletContext().getSessionCookieConfig() 获取SessionCookieConfig对象, 从而对保存SessionId的cookie进行相关操作, 如设置cookie的名字, 存活期限等, 但操作SessionCookieConfig必须在ServletContext初始化之前, 所以可以 1) 在web.xml中设定; 2) 实现ServletContextListener
18. Web容器启动后, 会读取Servlet设置信息, 将Servlet加载并实例化, 并为每个Servlet设置信息产生一个ServletConfig对象, 然后调用Servlet接口的init()方法, 并将产生的ServletConfig对象传入. 这个过程只会在创建Servlet实例后发生一次, 以后每次请求到来, 会调用Servlet实例的service()方法.
19. ServletContextListener接口, 在Web应用程序初始化或即将结束销毁前, 会调用该接口实现类的 contextInitialized() 和 contextDestoryed(), 并传入 ServletContextEvent, 其中封装了ServletContext
Servlet3.0中可以使用 @WebListener 注解
1 @WebListener 2 public class MyContextListener implements ServletContextListener { }
否则需要在web.xml中声明
<listener> <listener-class>tonny.study.listener.MyContextListener</listener-class> </listener> <servlet>...<servlet/>
20. ServletContextAttributeListener接口, 当ServletContext中的属性被设置(attributeAdded()), 移除(attributeRemoved()), 替换(attributeReplaced())时获取通知, 并传入ServletCAttributeEvent对象. 需要加标注 @WebListener 或在 web.xml 中声明
21. HttpSessionListener接口, 当HttpSession对象创建(sessionCreated())或结束(sessionDestroyed())时获取通知, 并传入HttpSession对象. 需要加标注 @WebListener 或在 web.xml 中声明
22. HttpSessionAttributeListener接口, 当HttpSession中加入(attributeAdded()), 移除(attributeRemoved()), 替换(attributeReplaced())属性时获取通知, 并传入 HttpSessionBindingEvent 对象. 需要加标注 @WebListener 或在 web.xml 中声明
23. HttpSessionBindingListener接口, 如果某个对象实现了该接口, 则当该对象被加入(valueBound()), 移除(valueUnbound())HttpSession时收到通知, 并传入 HttpSessionBindingEvent 对象.
24. HttpSessionActivationListener接口, 在分布式环境中用到, 此时应用程序的对象可能分散在多个JVM中.
25. ServletRequestListener接口, 当HttpServletRequest对象生成(requestInitialized())或销毁(requestDestroyed())时获取通知, 并传入ServletRequestEvent对象. 需要加标注 @WebListener 或在 web.xml 中声明
26. ServletRequestAttributeListener接口, 当HttpServletRequest中加入(attributeAdded()), 移除(attributeRemoved())或替换(attributeReplaced())属性时获取通知, 并传入ServletRequestAttributeListener对象. 需要加标注 @WebListener 或在 web.xml 中声明
27. 实现Filter接口实现过滤器, 使用 @WebFilter 标注或在 web.xml 中声明.
1 //@WebFilter("/LoginFilter") 2 @WebFilter( 3 filterName = "loginFilter", 4 urlPatterns = {"/admin", "/user"}, 5 servletNames = {"IndexServlet", "AdminServlet"} 6 ) 7 public class LoginFilter implements Filter { }
<filter> <filter-name>loginFilter</filter-name> <filter-class>tonny.study.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/admin</url-pattern> <servlet-name>index</servlet-name> </filter-mapping> <servlet> ... </servlet>
@WebFilter的常用属性
filterName | String | 指定过滤器的 name 属性, 等价于 <filter-name> |
value | String[] | 该属性等价于 urlPatterns 属性。但是两者不应该同时使用 |
urlPartterns | String[] | 指定一组过滤器的 URL 匹配模式。等价于 <url-pattern> 标签 |
servletNames | String[] | 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 <servlet-name> 的取值 |
dispatcherType | DispatcherType | 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST, 默认是Request, 即浏览器发出请求时触发过滤器 |
initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 <init-param> 标签 |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签 |
description | String | 该过滤器的描述信息,等价于 <description> 标 |
displayName | String | 该过滤器的显示名,通常配合工具使用,等价于 <display-name> 标签 |
28. 如果调用了 FilterChain 的doFilter()方法, 就会运行下一个过滤器, 如果没有则调用目标Servlet的service方法, 从而实现对service() 方法的前置处理. 在陆续调用完Filter实例的doFilter()和Servlet的Service()(如果请求没被拦截的话)之后, 流程会议堆栈顺序返回, 从而实现对 service() 方法的后置处理.z
1 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 2 //service()前置处理, 比如记录此时的时间,然后在后置处理中计算方法的耗时 3 chain.doFilter(request, response); 4 //service()后置处理 5 }
29. 使用HttpServletRequestWrapper, HttpServletResponseWrapper配合Filter.
1 /** 2 * 编码过滤器 3 * HttpServletRequestWrapper实现了HttpServletRequest接口, 继承它以后, 只需覆盖想重新编写的方法即可. 4 * 在Filter中将原始HttpservletRequest对象转成自定义对象, 并传递给doFilter方法, 从而实现自定义逻辑 5 * @author kaitang.yi 6 * @date 2013-7-31 下午5:45:02 7 */ 8 public class EncodingWrapper extends HttpServletRequestWrapper { 9 private String encoding; 10 11 public EncodingWrapper(HttpServletRequest request, String encoding) { 12 super(request); //必须调用父类构造器 13 this.encoding = encoding; 14 } 15 16 @Override 17 public String getParameter(String name) { 18 String value = getRequest().getParameter(name); 19 20 if(value != null) { 21 try { 22 byte[] bytes = value.getBytes("ISO-8859-1"); 23 value = new String(bytes, encoding); //按指定编码重新构造字符串 24 } catch (UnsupportedEncodingException e) { 25 e.printStackTrace(); 26 } 27 } 28 29 return value; 30 } 31 } 32 33 34 @WebFilter( 35 urlPatterns = {"/*"}, 36 initParams = { 37 @WebInitParam(name = "encoding", value = "UTF-8") 38 } 39 ) 40 public class EncodingFilter implements Filter { 41 private String encoding; 42 43 public void init(FilterConfig fConfig) throws ServletException { 44 encoding = fConfig.getInitParameter("encoding"); 45 } 46 47 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 48 HttpServletRequest req = (HttpServletRequest) request; 49 50 if ("GET".equals(req.getMethod())) { 51 req = new EncodingWrapper(req, encoding); 52 } else { 53 req.setCharacterEncoding(encoding); //只对请求body中的字符有效, 所以有了上面的判断 54 } 55 56 chain.doFilter(request, response); 57 } 58 59 public void destroy() { 60 } 61 }
参考:
《JSP&Servlet学习笔记(第二版)》