Servlet3.0新特性全解
Servlet3.0新特性全解
tomcat 7以上的版本都支持Servlet 3.0
Servlet 3.0 新增特性
- 注解支持;Servlet、Filter、Listener无需在web.xml中进行配置,可以通过对应注解进行配置;
- 支持Web模块;
- Servlet异步处理;
- 文件上传API简化;
Servlet3.0的注解
- @WebServlet :修饰Servlet类,用于部署该Servlet类。
- @WebFilter:修饰Filter类,用于部署该Filter类
- @WebInitParam:与@WebServlet或@WebFilter注解连用,为它们配置参数
- @MultipartConfig:修饰Servlet类,指定该Servlet类负责处理multipart/form-data类型的请求(主要用于处理上传文件)
- @ServletSecurity:修饰Servlet类,与JAAS(Java验证和授权API)有关的注解
- @HttpConstrait:与@ServletSecurity连用
- @HttpMethodConstrait:与@ServletSecurity连用
示例代码片: 修饰过滤器Filter:
@WebFilter( filterName="log", urlPatterns={"/*"}, initParams={ @WebInitParam(name="encoding",value="GBK"), @WebInitParam(name="loginPage",value="/login.jsp") }) public class MyFilter implements Filter { //内容省略...... }
修饰Servlet
@WebServlet(name="test", urlPatterns={"/basic.do"}, initParams={ @WebInitParam(name="userName",value="peter"), @WebInitParam(name="age",value="100") }) public class TestServlet extends HttpServlet{ //内容省略.... }
修饰监听器Listener:
@WebListener public class MyRequestListener implements ServletRequestListener{ //内容省略... }
Servlet3.0的Web模块支持
原来一个web应用的任何配置都需要在web.xml中进行,因此会使得web.xml变得很混乱,而且灵活性差。现在可通过Web模块来部署管理它们。
Web模块对应一个Jar包,即Servlet 3.0可以将每个Servlet、Filter、Listener打成jar包,然后放在WEB-INF\lib中。
每个模块都有自己的配置文件,这个配置文件的名称为 web-fragment.xml 。
制作一个Servlet模块的步骤:
正常编写Servlet,并编译;
将此编译class文件及所在包通过jar包命令打成jar包;
将此jar包用winrar打开,将META-INF中的manifest删除后添加 web-fragment.xml;
将此jar包放入WEB-INF\lib中即可;
web-fragment.xml说明:
<web-fragment>
为根元素;<name></name>
表示模块名称(模块的唯一标识);<ordering></ordering>
定义模块加载顺序的标签,当然可以不设置模块加载顺序;<before><others/></before>
表示在所有模块前面加载(第一个加载);<after><name>A</name></after>
表示在A模块后面加载;可以在里面部署listener、filter、servlet
值得注意的是,web.xml中用
<absolute-ordering>
标签指定的模块加载顺序将会覆盖web模块的web-fragment.xml文件中指定的加载顺序。如何用myEclipse打jar包(有些人不知道) 右键你web项目里的编写的servlet(或filter或listener)类——>Export…——>JAR file——>NEXT——>(Browse)填写导出名字和存放位置——>finish 这样就生成了我们需要的jar包了
示例 servlet类代码片:
@WebServlet(name="test",urlPatterns={"/basic.do"}) public class TestServlet extends HttpServlet{ //使用该方法可响应客户端的所有请求 public void service(HttpServletRequest req, HttpServletResponse resp)throws IOException{ System.out.println("进servlet了"); PrintStream out = new PrintStream(resp.getOutputStream()); //向页面输入下面字符串 out.print("1234567890"); } }
web-fragment.xml代码片
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"> <!-- 指定模块名称 :唯一标识--> <name>mySerModule</name> <!-- 加载顺序 --> <ordering> <!-- 在其它模块之前加载 --> <before> <others/> </before> </ordering> </web-fragment>
在web-fragment.xml里的配置和之前的web.xml里类似,如果是注解实现的servlet的配置,则在web-fragment.xml里就将不再写配置了,如果不是,则还需要写配置。 打成jar包放在一个项目里面启动后,就可通过上面servlet注解配置的/basic.do路径访问上面的servle了。
servlet3.0提供的异步处理
提供异步原因
在以前的servlet中,如果作为控制器的servlet调用了一个较为耗时的业务方法,则servlet必须等到业务执行完后才会生成响应,这使得这次调用成了阻塞式调用,效率比较差
实现异步原理
重新开一个线程单独去调用耗时的业务方法。
配置servlet类成为异步的servlet类
- 通过注解asyncSupported=true实现
- 通过web.xml配置
<servlet> <servlet-name>test1</servlet-name> <servlet-class>com.zrgk.servlet.AsyncServlet</servlet-class> <async-suppored>true</async-suppored> </servlet> <servlet-mapping> <servlet-name>test1</servlet-name> <url-pattern>/basic.do</url-pattern> </servlet-mapping>
具体实现
java代码:
@WebServlet(name="AsyncServlet",urlPatterns={"/testAsyn.do"},asyncSupported=true) public class AsyncServlet extends HttpServlet{ public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{ //解决乱码 request.setCharacterEncoding("GBK"); response.setContentType("text/html;charset=GBK"); //通过request获得AsyncContent对象 AsyncContext actx = request.startAsync(); //重点方法** //设置异步调用超时时长 actx.setTimeout(30*3000); //启动异步调用的线程 actx.start(new MyThread(actx));//重点方法** // 直接输出到页面的内容(不等异步完成就直接给页面) //但这些内容必须放在标签内,否则会在页面输出错误内容,这儿反正我测试是这样,具体不知对不对?? PrintWriter out = response.getWriter(); out.println("<h1>不等异步返回结果就直接返到页面的内容</h1>"); out.flush(); } } //异步处理业务的线程类 public class MyThread implements Runnable { private AsyncContext actx; //构造 public MyThread(AsyncContext actx){ this.actx = actx; } public void run(){ try{ //等待5秒,模拟处理耗时的业务 Thread.sleep(4*1000); //获得request对象,添加数据给页面 ServletRequest req = actx.getRequest(); req.setAttribute("content","异步获得的数据"); //将请求dispath到index.jsp页面,该页面的session必须设为false actx.dispatch("/index.jsp"); }catch(Exception e){ e.printStackTrace(); } } }
页面代码(页头里session设为false,表时该页面不会再创建session):
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" session="false"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <body> <a href="<%=basePath%>/testAsyn.do">测试异步调用</a> 异步结果:${content} </body> </html>
异步监听器
异步监听器用来监听异步Servlet的异步处理事件,通过实现AsyncListener接口实现,代码如下:
public class MyAsyncListener implements AsyncListener{ //异步调用完成时触发 @Override public void onComplete(AsyncEvent event) throws IOException { // 省略.... } //异步调用出错时触发 @Override public void onError(AsyncEvent event) throws IOException { // 省略.... } //异步调用开始触发 @Override public void onStartAsync(AsyncEvent event) throws IOException { // 省略.... } //异步调用超时触发 @Override public void onTimeout(AsyncEvent event) throws IOException { // 省略.... } }
还需要在异步Servlet里注册异步监听器,即添加如下代码即可:
actx.addListener(new MyAsyncListener());
Filter异步调用与Servlet一样。
改进的ServletAPI(上传文件)
改进内容
HttpServletRequest增加了对上传文件的支持
ServletContext允许通过编程的方式动态注册Servlet、Filter
HttpServletRequest提供了如下两个方法处理文件的上传
Part getPart(String name)
根据名称获取文件上传域Collection<Part> getParts()
获取所有文件上传域上传文件时一定要为表单域设置enctype属性,它表示表单数据的编码方式,有如下三个值:
application/x-www-form-urlencoded (默认),它只处理表单里的value属性值,它会将value值处理成URL编码方式。如果此时表单域里有上传文件的域(type=”file”),则只会获取该文件在上传者电脑里的绝对路径串,该串没什么实际意义。
multipart/form-data 此处编码方式会以二制流的方式来处理表单数据,此时会将文件内容也封装到请求参数里。
texst/plain 当表单的action属性为mailto:URL的形式时比较方便,主要适用于直接通过表单发送邮件的方式
上传文件的Servlet需要加上@MultipartConfig注解
通过request获取的Part对象就可以操作文件域了
示例
@WebServlet(name="uploadServlet",urlPatterns="/upload.do") @MultipartConfig public class UploaderServlet extends HttpServlet { public void service(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{ //获得Par对象(每个Part对象对应一个文件域) Part part = request.getPart("file"); long size = part.getSize(); //获取上传文件大小 String info = part.getHeader("content-disposition");//获得包含原始文件名的字符串 //获取原始文件名 String fileName = info.substring(info.indexOf("filename="")+10,info.length()-1); //将文件上传到某个位置 part.write(getServletContext().getRealPath("/uploadFiles")+"/"+fileName); } }
ServletContext提供了如下方法动态注册Servlet、Filter addServlet(); 动态注册Servlet addFilter(); 动态注册Filter addListener(); 动态注册Listener setInitParameter(String name ,String value); 为Web应用设置初始化参数。
以上就是Servlet3.0新特性全解的详细内容,更多关于Servlet3.0新特性的资料请关注脚本之家其它相关文章!
相关文章
SpringBoot使用Redisson实现延迟执行的完整示例
这篇文章主要介绍了SpringBoot使用Redisson实现延迟执行的完整示例,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下2024-06-06
最新评论