Servlet3 简单测试

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配置如下

 
    Some-Servlet
    com.fll.servletannotation.servlets.SomeServlet
    
        address
        北京
    



   Some-Servlet
   /ccc

 用注解配置如下

@WebServlet(urlPatterns = {"/some" , "/aaa" , "/bbb"} ,
            initParams = {@WebInitParam(name = "name" , value = "冯亮亮") , @WebInitParam(name = "age" , value = "20")})
public class SomeServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter writer = response.getWriter();
        writer.write("我是通过注解定义的Servlet3.0 
"); Enumeration initParameterNames = this.getInitParameterNames(); while (initParameterNames.hasMoreElements()){ String name = initParameterNames.nextElement(); String value = this.getInitParameter(name); writer.write("name=" + name + " value=" + value + "
"); } } }

那么当通过 /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时 注解配置生效




 7.上传文件

@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        Part filePart = request.getPart("file");
        Collection 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.具体代码

/**
 * @author fll
 */
@WebServlet(urlPatterns = "/async" , asyncSupported = true)
public class AsyncServlet extends HttpServlet {

    private static Logger logger = LoggerFactory.getLogger(AsyncServlet.class);


    @Override
    protected 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("主线程开始
"); //AsyncContext asyncContext = request.getAsyncContext(); final AsyncContext asyncContext = request.startAsync(); asyncContext.addListener(new AsyncListener() { @Override public void onComplete(AsyncEvent event) throws IOException { logger.info("=============================== onComplete"); } @Override public void onTimeout(AsyncEvent event) throws IOException { logger.info("=============================== onTimeout"); } @Override public void onError(AsyncEvent event) throws IOException { logger.info("=============================== onError"); } @Override public void onStartAsync(AsyncEvent event) throws IOException { logger.info("=============================== onStartAsync"); } }); //asyncContext.setTimeout(3000); asyncContext.start(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(500); System.out.println("================ " + i); writer.write("================ " + i + "
"); } 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("主线程结束
"); } }

以上代码 浏览器看到的内容是:
主线程开始
主线程结束
================ 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方法会被回调。

 

你可能感兴趣的:(servlet,java)