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