1.注解定义servlet的时候如果 @WebServlet("some") 如果url-pattern前面不加 / 回报以下的错误,和web.xml中定义是一致的。
java.lang.IllegalArgumentException: Invalid [some] in servlet mapping
2.urlPatterns = {"/some" , "/aaa" , "/bbb"} 和 value= {"/some" , "/aaa" , "/bbb"} 的作用是一样的都是用来定义访问改Servlet的 url-pattern 但是只能用一个 不能两个同事出现
3.如果同一个Servlet的类 既在web.xml中定义 又通过注解@WebServlet定义 那么最终只会注册一个Servlet实例 url-pattern 为 web,xml的url-pattern 和 注解中url-pattern 的并集
例如: web.xml 中 url-pattern为 /ccc @WebServlet中定义的 url-pattern 为 /aaa /bbb .那么该Servlet的最终 url-pattern 为 /aaa /bbb /ccc
4.如果web.xml中Servlet配置如下
<servlet><servlet-name>Some-Servlet</servlet-name><servlet-class>com.fll.servletannotation.servlets.SomeServlet</servlet-class><init-param><param-name>address</param-name><param-value>北京</param-value></init-param>
</servlet><servlet-mapping><servlet-name>Some-Servlet</servlet-name><url-pattern>/ccc</url-pattern>
</servlet-mapping>
用注解配置如下
java">@WebServlet(urlPatterns = {"/some" , "/aaa" , "/bbb"} ,initParams = {@WebInitParam(name = "name" , value = "冯亮亮") , @WebInitParam(name = "age" , value = "20")})
public class SomeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");PrintWriter writer = response.getWriter();writer.write("我是通过注解定义的Servlet3.0 <br>");Enumeration<String> initParameterNames = this.getInitParameterNames();while (initParameterNames.hasMoreElements()){String name = initParameterNames.nextElement();String value = this.getInitParameter(name);writer.write("name=" + name + " value=" + value + "<br>");}}
}
那么当通过 /some /aaa /bbb 访问是返回的是:
我是通过注解定义的Servlet3.0
name=name value=冯亮亮
name=age value=20
当通过 /ccc 访问的时候 返回的是:
我是通过注解定义的Servlet3.0
name=address value=北京
4.如果 同一个 Filter的类 既在 web.xml url-pattern=/* 中定义了 Filter 又通过 @WebFilter("/*") 定义Filter那么相当于注册的两个独立的 Filter 实例。一个请求如果既符合 web.xml 中的url-pattern 又符合 @WebFilter("/*") 中的 url-pattern 那么这两个 Filter 都会被执行
5.如果同一个 Listener的类 同时在 web.xml 和 @WebListener中定义 Listener 那么只会注册一个 Listener 实例
6. 当 web.xml 中的 metadata-complete="true" 时所有注解的配置都会失效 false时 注解配置生效
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0" metadata-complete="true"></web-app>
7.上传文件
java">@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Part filePart = request.getPart("file");Collection<String> headers = filePart.getHeaderNames();for (String headerName : headers){String header = filePart.getHeader(headerName);System.out.println(headerName + "=================" + header);}//打印结果//content-disposition=================form-data; name="file"; filename="1501131329.png"//content-type=================image/png//获取该 part 的文件名String fileName = filePart.getSubmittedFileName();String realPath = this.getServletContext().getRealPath("/upload");String filePath = realPath + "/" + fileName;filePart.write(filePath);}
}
注意:(1)Servlet类上添加 @MultipartConfig
Annotation that may be specified on a {@link javax.servlet.Servlet} class, indicating that instances of the Servlet expect requests that conform to the multipart/form-data MIME type.
该注解的注释大概意思是: 该注解是被放在Servlet类上的,表明这个Servlet类的实例希望请求遵守 multipart/form-data MIME type.
8. Servlet异步
获取AsyncContext 对象的时候要用 AsyncContext asyncContext = request.startAsync();
千万不要使用AsyncContext asyncContext = request.getAsyncContext(); 这个方法是一个递归调用
如果该Servlet的属性 asyncSupported = false 的时候 执行上面的语句回报以下的错误
the processing chain do not support async [com.fll.servletannotation.servlets.AsyncServlet]
java.lang.IllegalStateException: 当前链的筛选器或servlet不支持异步操作。
9.具体代码
java">/*** @author fll*/
@WebServlet(urlPatterns = "/async" , asyncSupported = true)
public class AsyncServlet extends HttpServlet {private static Logger logger = LoggerFactory.getLogger(AsyncServlet.class);@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("================================");response.setContentType("text/html;charset=UTF-8");final PrintWriter writer = response.getWriter();writer.write("主线程开始<br>");//AsyncContext asyncContext = request.getAsyncContext();final AsyncContext asyncContext = request.startAsync();asyncContext.addListener(new AsyncListener() {@Overridepublic void onComplete(AsyncEvent event) throws IOException {logger.info("=============================== onComplete");}@Overridepublic void onTimeout(AsyncEvent event) throws IOException {logger.info("=============================== onTimeout");}@Overridepublic void onError(AsyncEvent event) throws IOException {logger.info("=============================== onError");}@Overridepublic void onStartAsync(AsyncEvent event) throws IOException {logger.info("=============================== onStartAsync");}});//asyncContext.setTimeout(3000);asyncContext.start(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(500);System.out.println("================ " + i);writer.write("================ " + i + "<br>");} catch (InterruptedException e) {e.printStackTrace();}}asyncContext.complete();//asyncContext.dispatch("show.jsp");//asyncContext.dispatch("show.jsp");等价于 request.getRequestDispatcher("show.jsp").include(request , response);同样有通知主线程子线程已经执行完毕的作用 也就是该方法也会将response中的数据写道浏览器中}});writer.write("主线程结束<br>");}}
以上代码 浏览器看到的内容是:
主线程开始
主线程结束
================ 0
================ 1
================ 2
================ 3
================ 4
================ 5
================ 6
================ 7
================ 8
================ 9
说明执行顺序是 主线程线执行完 然后等待asyncContext.complete();执行 一起把数据写到浏览器
如过将超时事件设置为 2秒 打印结果如下:
主线程开始
主线程结束
================ 0
================ 1
================ 2
================ 3
================ 4
说明 当超时的时候也会自动将response中的数据写到浏览器中
10.同步线程执行完成得通知 asyncContext.complete(); 如果不执行该语句 主线程会一直等待异步线程的执行完成 知道超时 默认的超时时间是 30秒。也可以asyncContext.setTimeout(3000);修改超时时间 超时之后监听器的onTimeout方法会被回调。