前言
Servlet3.0
使用了注解来配置web
应用,极大缩减了web.xml
的配置。
新增注解
注解 |
作用 |
@WebServlet |
修饰一个Servlet 类 |
@WebFilter |
修饰一个Filter 类 |
@WebListener |
修饰一个Listener 类 |
@WebInitParam |
为Servlet 、Filter 类配置参数 |
@MultipartConfig |
指定Servlet 处理文件上传 |
对Web模块支持
Servlet3.0
不再要求所有Web
组件全部写在web.xml
中。
需要在META-INF
中添加Web
模块部署描述符web-fragment.xml
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?xml version="1.0" encoding="GBK" ?> <web-fragment 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 version="3.0"> <name>模块名</name> <ordering> <after> <name>模块1</name> <others/> </after> <before> <name>模块2</name> <others/> </before> </ordering> </web-fragment>
|
也可以在web.xml
中指定加载顺序
1 2 3 4 5 6
| <web-app> <absolute-ordering> <name>模块名</name> <others/> </absolute-ordering> </web-app>
|
注解配置Web组件
不能在web.xml
的<web-app/>
指定metadata-complete="true"
如果metadata-complete
设置为true
,部署工具必须必须忽略存在于应用的类文件中的所有servlet
注解和web fragments
。
如果metadata-complete
属性没有指定或设置为false
,部署工具必须检查应用的类文件的注解,并扫描web fragments
。
1 2 3 4 5 6 7 8 9
| @Servlet public class MyServlet extends HttpServlet{ } @WebFilter public class MyFilter implements Filter{ } @WebListener public class MyListener implements ServletContextAttributeListener{ }
|
动态注册Web组件
Servlet3.0
提供了ServletContext
添加组件的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public ServletRegistration.Dynamic addServlet(String servletName, String className); public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet); public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass);
public FilterRegistration.Dynamic addFilter(String filterName, String className); public FilterRegistration.Dynamic addFilter(String filterName, Filter filter); public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass);
public void addListener(String className); public <T extends EventListener> void addListener(T t); public void addListener(Class<? extends EventListener> listenerClass);
|
通过ServletContextListener注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class MyServlet extends HttpServlet{ }
public class InitListener implements ServletContextListener{ public void contextDestroyed(ServletContextEvent event) { System.out.println("服务器关闭时会调用该方法"); } @Override public void contextInitialized(ServletContextEvent event) { System.out.println("服务器启动时会调用该方法"); ServletContext context = contextEvent.getServletContext(); ServletRegistration register = context.addServlet("helloServlet", HelloServlet.class); register.addMapping("/hello", "/servlet/hello"); register.setInitParameter("logPath", "/app/log"); register.setInitParameter("savePath", "/app/upload"); } }
|
通过ServletContainerInitializer注册
添加META-INF/services/javax.servlet.ServletContainerInitializer
文件。
文件内容为
1
| com.ahao.demo.MyServletContainerInitializer
|
指定自定义的ServletContainerInitializer
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @HandlesTypes({ WebApplicationInitializer.class })
public class MyServletContainerInitializer implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext servletContext) throws ServletException { ServletContext context = sce.getServletContext(); ServletRegistration.Dynamic servlet = context.addServlet("myServlet", MyServlet.class); dynamicServlet.addMapping("/myServlet"); dynamicServlet.setAsyncSupported(true); dynamicServlet.setLoadOnStartup(1); FilterRegistration.Dynamic filter = context.addFilter("MyFilter", MyFilter.class); context.addListener("com.ahao.demo.MyListener"); } }
|
文件上传
HttpServletRequest
提供处理文件上传的支持。
Part getPart(String name)
Collection<Part> getParts()
Part
对应一个文件上传域,支持访问文件类型、大小、输入流等。
文件上传需要给form
表单添加enctype
属性,该属性有三个值:
属性值 |
说明 |
application/x-www-form-urlencoded |
默认编码方式,对form 的value 属性进行URL 编码 |
multipart/form-data |
二进制方式处理表单数据,上传文件用 |
text/plain |
适用于直接通过表单发送邮件 |
1 2 3 4
| <form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="myfile" /> <input type="submit"/> </form>
|
在Servlet
中处理上传数据,使用@MultipartConfig
修饰,或者在web.xml
中<servlet>
标签中添加<multipart-config/>
子标签
1 2 3 4 5 6 7 8 9 10
| @WebServlet(name="upload",urlPatterns={"/upload"}) @MultipartConfig public class UploadServlet extends HttpServlet{ public void doPost(HttpServletRequest request,HttpServletResponse response){ Part part = request.getPart("myfile"); out.println("文件类型:"+part.getContentType()+"<br/>"); out.println("文件大小:"+part.getSize()+"<br/>"); part.write(getServletContext().getRealPath("/uploadFiles")+"/"+"myfile"); } }
|
异步处理
支持Servlet
、Filter
。
当Servlet
执行耗时操作时,必须等完成操作才能生成响应。
Servlet3.0
允许Servlet
创建一个线程去执行耗时操作。
先要给Servlet
配置允许异步操作
- 在
xml
中配置:1 2 3 4
| <servlet> <servlet-name>MyServlet</servlet-name> <async-supported>true</async-supported> </servlet>
|
- 在注解中配置:
1 2 3
| @WebServlet(urlPattern="/async",asyncSupported=true) public class AsyncServlet extends HttpServlet{ }
|
通过ServletRequest创建AsyncContext对象
通过AsyncContext
类实现,重复调用创建方法得到同一个AsyncContext
对象。
1 2 3 4 5 6 7 8 9
| @WebServlet(urlPattern="/async",asyncSupported=true) public class AsyncServlet extends HttpServlet{ public void doGet(HttpServletRequest request,HttpServletResponse response){ AsyncContext actx = request.startAsync(); actx.setTimeout(3000); actx.start(new Executor(actx)); } }
|
异步监听
当需要了解异步操作执行细节时,可以使用AsyncListener
监听器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MyAsyncListener implements AsyncListener{ public void onStartAsync(AsyncContext event){ System.out.println("异步调用开始"); } public void onComplete(AsyncContext event){ System.out.println("异步调用完成"); } public void onError(AsyncContext event){ System.out.println("异步调用异常"); } public void onTimeout(AsyncContext event){ System.out.println("异步调用超时"); } }
|