Servlet3.x新特性

Servlet3.x新特性

介绍

Servlet标准一直在推进,Servlet3.0相比之前的版本有很多特性和改进。

学习Java Web开发,Servlet绝对是最重要也是最应该好好掌握和深入理解的部分。

一、注解式开发支持

Servlet3.x之前开发Servlet需要在web.xml中配置对应的映射地址,但是从3.x之后这样的配置将不再是必须的了。

常用注解:@WebServlet、@WebListener、@WebFilter、@WebInitParam

Servlet3.x支持的注解都在javax.servlet.annotation包下.

案例

/**
 * <h3>Servlet3.x注解式开发案例</h3>
 * 
 * @author xuyi3
 * @2016年9月8日 @上午10:27:53
 * @GetController
 * @功能说明:<br>
 * @春风十里不如你
 * @备注
 */
@WebServlet(urlPatterns = "/getController", 
    initParams = { @WebInitParam(name = "key1", value = "value1"),
    @WebInitParam(name = "key2", value = "value2") })
//配置单个servlet初始化参数
//@WebInitParam(name="key",value="xxx")
public class GetController extends HttpServlet
{

    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(GetController.class);

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        logger.info("doGet...");
    }

}

二、异步处理支持

Servlet3.x之前的针对每个请求都是阻塞的,只要服务器没有处理完任务时不会响应客户端的,这样的体验并不好。

解决方法可以是借组消息中间件来异步处理,Servlet3.x开始支持开启新线程异步处理,无需等待新线程处理完成即可响应客户端。

案例

/**
 * <h3>Servlet3.x异步处理简单案列</h3>
 * 
 * @author xuyi3
 * @2016年9月8日 @上午10:21:08
 * @AsyncController
 * @功能说明:<br>
 * @春风十里不如你
 * @备注
 */
@WebServlet(urlPatterns = "/asyncController", asyncSupported = true)
public class AsyncController extends HttpServlet
{

    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        //处理耗时任务...

        AsyncContext asyncContext = request.startAsync();//启动异步处理线程
        asyncContext.setTimeout(5000);//设置异步处理超时时间
        asyncContext.start(new Runnable()//异步处理的新线程处理的任务
        {
            public void run()
            {
                for (int i = 0; i < 4; i++)
                {
                    try
                    {
                        Thread.sleep(1000);
                        logger.info("=====处理耗时任务{}=====", (i + 1));
                    } catch (InterruptedException e)
                    {
                        logger.error("", e);
                    }
                }
            }
        });

        //响应前端

        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println(JsonUtils.getDefaultJsonString());
        writer.flush();
        writer.close();
    }
}

备注:要深入学习Servelt3.x的异步处理的话,请查看AsyncContext源码实现。
备注:是否采用这种方式还是要看公司已有的技术架构,个人推荐使用消息中间件来达到异步处理任务。

异步处理支持:有了该特性,Servlet线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该Servlet线程。

在接收到请求之后,Servlet线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。

针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。

三、文件上传下载新方式支持

Servlet3.x之前对于文件上传并不友好,编写相对麻烦。Servlet3.x之后提供了Part类来表示上传文件对象,完全可以借助该对象实现上传功能。

备注:可以去查看Part的源码和其中的方法

案例

/**
 * <h3>使用Servlet3.x新特性,实现单个和多个文件上传</h3>
 * 
 * @author xuyi3
 * @2016年9月8日 @下午1:57:24
 * @UploadController
 * @功能说明:<br>
 * @春风十里不如你
 * @备注
 */
@WebServlet(urlPatterns = "/uploadController")
@MultipartConfig//备注上传不要忘记配置
public class UploadController extends HttpServlet
{

    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);

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

        Collection<Part> parts = request.getParts();
        logger.info("=====上传文件数:{}=====", parts.size());
        for (Part part : parts)
        {
            if (part != null && part.getSize() > 0)
            {
                //获得文件名
                String fileName = getFileName(part);
                //获得文件后缀
                String suffix = getSuffix(part);

                InputStream inputStream = part.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(new File("e:/" + fileName + "." + suffix));
                //备注:通常上传的文件名字由我们服务端自己定义,只要和用户关联就行,至于命名规则我们定义(比如对用户id、用户名计算MD5等)

                //上传文件操作
                IOUtils.copy(inputStream, outputStream);
            }
        }
    }

    /**
     * 获得上传文件的后缀
     * @param part
     * @return
     */
    private String getSuffix(Part part)
    {
        //上传文件名
        String submitFileName = part.getSubmittedFileName();
        int beginIndex = submitFileName.lastIndexOf(".");
        int endIndex = submitFileName.length();
        String suffix = submitFileName.substring(beginIndex + 1, endIndex);

        return suffix;
    }

    /**
     * 获得上传文件名字
     * @param part
     * @return
     */
    private String getFileName(Part part)
    {
        //上传文件名
        String submitFileName = part.getSubmittedFileName();
        int endIndex = submitFileName.lastIndexOf(".");
        String suffix = submitFileName.substring(0, endIndex);

        return suffix;
    }

}

需要注意点:
        1、配置MIME 类型是 multipart/form-data
        2、配置MultipartConfig

//备注:通常想要实现文件上传功能都不会由我们自己写,大部分web mvc框架都会提供更简便方式来实现。
比如spring mvc、struct2.x框架

参考

1、https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/
2、https://en.wikipedia.org/wiki/Servlets
3、http://www.journaldev.com/2015/servlet-interview-questions-and-answers
4、http://www.journaldev.com/2114/servlet-jsp-tutorial

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值