博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Servlet3.0的新特性
阅读量:6436 次
发布时间:2019-06-23

本文共 19550 字,大约阅读时间需要 65 分钟。

注意:Servlet3.0的项目一定要使用Tomcat7.0才能看到效果!!

1、新增标注支持

    在Servlet3.0的部署描述文件web.xml的顶层标签<web-app>中有一个metadata-complete属性,如果把该属性的值设置为true,则容器在部署时只依赖于web.xml部署文件中的配置,会忽略所以的标注(同时也会跳过web-fragment.xml的扫描,即禁用可插性支持);如果把该属性的值设置为false或者不配置该属性,则表示启用标注支持和可插性支持。
    1)WebServlet标注
    @WebServlet用于将一个类声明为Servlet,该标注将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为Servlet。
    
    2)WebInitParam标注
    @WebInitParam标注通常不单独使用,而是配合@WebServlet或者@WebFilter使用。它的作业是为Servlet或者过滤器指定初始化参数,这等价于web.xml中<servlet>和<filter>的<init-param>子标签
属性名 类型 是否可选 描述
name String 指定参数的名字,等价于<param-name>
value String 指定参数的值,等价于<param-value>
description String 指定参数的描述,等价于<description>
 
创建一个Servlet3Annotation类:
package com.yyq.servlet3.annotation;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.annotation.WebInitParam;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;/** * Created by gao on 16-4-14. */@WebServlet(name = "servlet3annotation", urlPatterns = {"/servlet3"},        description = "servletinfo", displayName = "abc", asyncSupported = true, loadOnStartup = -1,        initParams = {@WebInitParam(name = "username", value = "YangYuqin")})public class Servlet3Annotation extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        doPost(req, resp);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        //获取ServletConfig的实例        ServletConfig config = this.getServletConfig();        //获取指定参数名称的值        String name = config.getInitParameter("username");        resp.setContentType("text/html;charset=utf-8");        PrintWriter out = resp.getWriter();        out.println("");        out.println("Servlet3应用实例");        out.println("");        out.print("获取InitParamServlet的初始化参数\"username\"的字符串值:" + name);        out.println("");        out.println("");    }    @Override    public void destroy() {        //空    }    @Override    public void init() throws ServletException {        //空    }}

 启动Tomcat,输入:

    3)WebFilter标注
    @WebFilter用于将一个类声明为过滤器,该标注将会在部署时被容器处理。以下属性均为可选属性,但是value、urlPatterns、servletNames三者必需至少包含一个,且value和urlPattern不能共存,如果同时指定,通常忽略value的取值。
属性名 类型 描述
filterName String 指定过滤器的name属性,等价于<filter-name>
value String[] 该属性等价于urlPatterns属性,两个属性不能同时使用
urlPatterns String[] 指定一组Servlet的URL匹配模式,等价于<url-pattern>标签
servletNames String[] @WebServlet中的name属性的取值,或者是web.xml中<servlet-name>的取值
initParams WebInitParam[] 指定一组Servlet初始化参数,等价于<init-param>标签
dispatcherTypes DispatcherType 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
asyncSupported boolean 声明过滤器是否支持异步操作模式,等价于<async-supported>标签
description String 该Servlet的描述信息,等价于<description>标签
displayName String 该Servlet的显示名,通常配合工具使用,等价于<display-name>标签
 
package com.yyq.servlet3.filter;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.annotation.WebInitParam;import java.io.IOException;/** * Created by gao on 16-4-14. */@WebFilter(servletNames = {"servlet3filterannotation"}, filterName = "characterFilter",        initParams = {@WebInitParam(name = "encoding", value = "UTF-8")})public class Servlet3FilterAnnotation implements Filter {    private FilterConfig filterConfig = null;    @Override    public void init(FilterConfig filterConfig) throws ServletException {        this.filterConfig = filterConfig;    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        //获取此Filter的初始参数的值        String encoding = filterConfig.getInitParameter("encoding");        System.out.println(encoding);        //设置请求数据的编码方式        servletRequest.setCharacterEncoding(encoding);        //把请求和响应对象传给过滤链中的下一个要调用的过滤器或Servlet        filterChain.doFilter(servletRequest,servletResponse);    }    @Override    public void destroy() {        //空    }}

 

  4)WebListener标注

    该标注用于将类声明为监听器。
属性名 类型 是否可选 描述
value String 该监听器的描述信息
监听类:
package com.yyq.servlet3.listener;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;import java.util.LinkedList;import java.util.List;/** * Created by gao on 16-4-14. */@WebListener("This is the Listener")public class Servlet3Listener implements ServletContextListener, HttpSessionAttributeListener, HttpSessionListener {    private ServletContext application = null;    //往会话中添加属性时回调的方法    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {        //取得用户名列表        List
online = (List
) this.application.getAttribute("online"); if ("username".equals(httpSessionBindingEvent.getName())) { //将当前用户名添加到列表中 online.add((String) httpSessionBindingEvent.getValue()); } //将添加后的列表重新设置到application属性中 this.application.setAttribute("online", online); } //以下方法用空实现 @Override public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) { } @Override public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) { } @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } //应用上下文初始化会回调的方法 @Override public void contextInitialized(ServletContextEvent servletContextEvent) { //初始化一个application对象 this.application = servletContextEvent.getServletContext(); //设置一个列表属性,用于保存在线用户名 this.application.setAttribute("online",new LinkedList
()); } //会话销毁时会回调的方法 @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { //取得用户名列表 List
online = (List
) this.application.getAttribute("online"); //取得当前用户名 String username = (String) httpSessionEvent.getSession().getAttribute("username"); //将此用户名从列表中删除 online.remove(username); //将删除后的列表重新设置到application属性中 this.application.setAttribute("online", online); }}

 登录Servlet类:

package com.yyq.servlet3.listener;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.List;/** * Created by gao on 16-4-14. */@WebServlet(name = "servlet3login",urlPatterns = {"/login"})public class Servlet3Login extends HttpServlet {    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        //设置响应内容类型        req.setCharacterEncoding("utf-8");        //获取请求参数中的用户名        String username = req.getParameter("username");        //往Session中添加属性        //会触发HttpSessionAttributeListener中的attributeAdded方法        if (username != null && !username.equals("")) {            req.getSession().setAttribute("username", username);        }        //从应用上下文中获取在线用户名列表        List
online = (List
) getServletContext().getAttribute("online"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println(""); out.println("
用户列表"); out.println(""); out.println("当前用户是:" + username); out.println("

在线用户列表

>"); int size = ((online == null) ? 0 : online.size()); for (int i = 0; i < size; i++) { if (i > 0) { out.println("
"); } out.println(i + 1 + "." + online.get(i)); } //注意:要对连接URL进行自动重写处理 out.println("

注销"); out.println(""); out.println(""); out.flush(); out.close(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 }}

注销Servlet类:

package com.yyq.servlet3.listener;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.List;/** * Created by gao on 16-4-14. */@WebServlet(name = "servlet3logout", urlPatterns = {"/logout"})public class Servlet3Logout extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        //设置响应内容类型        req.setCharacterEncoding("utf-8");        //销毁会话,会触发SessionLinstener中的sessionDestroyed方法        req.getSession().invalidate();        //从应用上下文中获取在线用户名列表        List
online = (List
)getServletContext().getAttribute("online"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println(""); out.println("
用户列表"); out.println(""); out.print("

在线用户列表

"); int size = ((online == null) ? 0 : online.size()); for (int i = 0; i < size; i++) { if (i > 0) { out.println("
"); } out.println(i + 1 + "." + online.get(i)); } out.println("

主页"); out.println(""); out.println(""); out.flush(); out.close(); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 }}

登录页面:index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>    
用户名:
    5)MultipartConfig标注
    该标注主要是为了辅助Servlet3.0中HttpServletRequest提供的对上传文件的支持。该标注标注在Servlet上,表示该Servlet希望处理的请求的MIME类型是multipart/form-data。
属性名 类型 是否可选 描述
fileSizeThreshold int 当数据量大于该值时,内容将被写入文件
location String 存放生成的文件地址
maxFileSize long 允许上传的文件最大值。默认值为-1,表示没有限制
maxRequestSize long 针对该multipart/form-data请求的最大数量,默认值为-1,表示没有限制

文件上传页面upload.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" pageEncoding="UTF-8" %><%    String path = request.getContextPath();    String basePath = request.getScheme() + "://" + request.getServerName() + ":"            + request.getServerPort() + path + "/";%>    Servlet3.0 上传文件
选择文件:
描述:
  

处理上传文件的Servlet:

package com.yyq.servlet3.multipartconfig;import javax.servlet.ServletException;import javax.servlet.annotation.MultipartConfig;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.File;import java.io.IOException;import java.io.PrintWriter;import java.util.UUID;/** * Created by gao on 16-4-14. */@WebServlet(name = "upFile", urlPatterns = {"/uploadfile"})@MultipartConfig(maxFileSize = 500000, maxRequestSize = -1)public class FileUploadServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        //resp.setContentType("text/html;charset=utf-8");        //获取请求参数值        Part part = req.getPart("file");        //存储路径        String storePath = req.getServletContext().getRealPath("/temp");        //Servlet3没有提供直接获取文件名,后缀名的方法,需要从请求头中解析出来        //获取请求头        String header = part.getHeader("content-disposition");        //获取文件后缀名        //String suffix = parseFileName(header);        String name = parseFileName(header);        //重新命名        //String name = UUID.randomUUID() + suffix;        //把文件写到指定路径        part.write(storePath + File.separator + name);//        PrintWriter out = resp.getWriter();//        out.println("上传成功");//        out.flush();//        out.close();        //获得文件描述信息        String description = req.getParameter("description");        req.setAttribute("f", name);        req.setAttribute("des", description);        req.getRequestDispatcher("info.jsp").forward(req, resp);    }    /*    *根据请求头解析出上传文件的后缀名称    */    /**     * 根据请求头解析出文件名     * 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"     * IE浏览器下:form-data; name="file"; filename="E:\snmp4j--api.zip"     *     * @param header 请求头     * @return 文件名     */    public String parseFileName(String header) {        //return header.substring(header.lastIndexOf("."), header.length() - 1);        /**         * String[] tempArr1 = header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别         * 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"}         * IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}         */        String[] tempArr1 = header.split(";");        /**         *火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}         *IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}         */        String[] tempArr2 = tempArr1[2].split("=");        //获取文件名,兼容各种浏览器的写法        String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");        return fileName;    }    @Override    public void destroy() {        //空    }    @Override    public void init() throws ServletException {        //空    }}

显示上传文件和描述信息的页面info.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" pageEncoding="UTF-8" %><%    String path = request.getContextPath();    String basePath = request.getScheme() + "://" + request.getServerName() + ":"            + request.getServerPort() + path +"/";%>    Servlet3.0 上传文件    

<%=request.getAttribute("des")%>

servlet3">

 

2、异步处理支持
    Servlet3.0支持异步处理支持,Servlet接收到请求之后,可能首先需要对请求携带的数据进行一些预处理;接着,Servlet线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时Servlet还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有ServletRequest和ServletResponse对象的引用),或者将请求继续转发给其他Servlet。
    1)对于使用传统的部署描述文件web.xml配置Servlet和过滤器的情况,Servlet3.0为<servlet>和<filter>标签增加了<async-supported>子标签,该标签的默认取值为false,要启用异步处理支持,则将其设为true即可。
DemoServlet
com.yyq.servlet3.asyncsupported.AsyncDemoServlet
true

   2)对于使用Servlet3.0提供的@WebServlet和@WebFilter进行Servlet或过滤器配置的情况,这两个标注都提供了asyncSupported属性,默认该属性的取值为false,要启动异步处理支持,只需将该属性设置为true即可。

package com.yyq.servlet3.asyncsupported;import javassist.bytecode.analysis.Executor;import javax.servlet.AsyncContext;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.Date;/** * Created by gao on 16-4-15. */@WebServlet(urlPatterns = {"/asyncdemo"}, asyncSupported = true)public class AsyncDemoServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        resp.setContentType("text/html;charset=utf-8");        PrintWriter out = resp.getWriter();        out.println("进入Servlet的时间:" + new Date() + ".");        out.flush();        //在子线程中执行业务调用,并由其负责输出响应,主线程退出        AsyncContext ctx = req.startAsync();        new Thread(new Executor(ctx)).start();        out.println("结束Servlet的时间:" + new Date() + ".");        out.flush();    }    public class Executor implements Runnable {        private AsyncContext ctx = null;        public Executor(AsyncContext ctx) {            this.ctx = ctx;        }        public void run() {            try {                //等待10秒钟,以模拟业务方法的执行                Thread.sleep(10000);                PrintWriter out = ctx.getResponse().getWriter();                out.println("业务处理完毕的时间:" + new Date() + ".");                out.flush();                ctx.complete();            }catch (Exception e){                e.printStackTrace();            }        }    }    @Override    public void destroy() {        //空    }    @Override    public void init() throws ServletException {        //空    }}

启动Tomcat,输入:http://localhost:8080/asyncdemo

 
3、可插性支持
    Servlet3.0新增的可插性(Pluggability)支持则将Servlet配置的灵活性提升到了新的高度。使用该特性,现在我们可以在不修改已有Web应用的前提下,只需将按照一定格式打包成的JAR包放到WEB-INF/lib目录下,即可实现新的功能的扩充,不需要额外的配置。Servlet3.0引入了称为“Web模块部署描述文件片段”的web-fragment.xml来实现可插性的。web-fragment.xml部署描述文件可以定义一切可以在web.xml中定义的内容。
1)新建的Servlet类:
package com.yyq.servlet3.pluggability;import javax.naming.NamingException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;/** * Created by gao on 16-4-15. */public class FragmentDemoServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        this.doPost(req, resp);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        resp.setContentType("text/html;charset=utf-8");        PrintWriter out = resp.getWriter();        out.println("这是我Servlet3.0的第一个可插性示例");        out.flush();    }    @Override    public void destroy() {        //空    }    @Override    public void init() throws ServletException {        //空    }}

 2)在web目录下新建一个目录META-INF,在该目录下新建一个web-fragment.xml模块部署描述符文件片段:

FragmentA
fragmentDemo
com.yyq.servlet3.pluggability.FragmentDemoServlet
fragmentDemo
/fragment
3)将FragmentDemoServlet和META-INF目录一起打包成JAR包,假如JAR包叫fragment.jar。
4)将fragment.jar放到其他Web项目中的WEB\lib目录中,然后访问
 
 

转载于:https://www.cnblogs.com/yangyquin/p/5428914.html

你可能感兴趣的文章
Git分支管理策略
查看>>
给每一辆车配上“×××”,老牌安企高新兴的交通新作
查看>>
VLAN与Trunk的配置
查看>>
瞎写 论售后服务
查看>>
求四边形的数量
查看>>
1111
查看>>
opencart,mycncart,google字体本地化详细处理方法。包括前后台。
查看>>
个人知识管理软件:Midear Note
查看>>
rpm安装软件包
查看>>
密信国密浏览器:推动SM2国密算法和国密SSL证书应用
查看>>
7月末周网络安全报告:发现放马站点增至204个
查看>>
解决deepin-scrot在gnome3截图顶部出现黑边问题
查看>>
c语言printf输出列宽度的控制
查看>>
数组的最大距离 Maximum Distance in Arrays
查看>>
mydumper安装
查看>>
CentOS Linux 6.4 配置Samba简明指南
查看>>
【转载】网络编程中 Nagle 算法和 Delayed ACK 的测试
查看>>
isKindOfClass和isMemberOfClass的区别
查看>>
android如何用程序实现启用gprs或者3g网络
查看>>
全栈技能之自学sketch指南
查看>>