Servlet3.0 新特性全解

简介: Servlet3.0 新特性全解

Servlet3.0新特性全解


tomcat 7以上的版本都支持Servlet 3.0


Servlet 3.0 新增特性


  1. 注解支持;Servlet、Filter、Listener无需在web.xml中进行配置,可以通过对应注解进行配置;
  2. 支持Web模块;
  3. Servlet异步处理;
  4. 文件上传API简化;


Servlet3.0的注解


  1. @WebServlet :修饰Servlet类,用于部署该Servlet类。
  2. @WebFilter:修饰Filter类,用于部署该Filter类
  3. @WebInitParam:与@WebServlet或@WebFilter注解连用,为它们配置参数
  4. @MultipartConfig:修饰Servlet类,指定该Servlet类负责处理multipart/form-data类型的请求(主要用于处理上传文件)
  5. @ServletSecurity:修饰Servlet类,与JAAS(Java验证和授权API)有关的注解
  6. @HttpConstrait:与@ServletSecurity连用
  7. @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模块支持


  1. 原来一个web应用的任何配置都需要在web.xml中进行,因此会使得web.xml变得很混乱,而且灵活性差。现在可通过Web模块来部署管理它们。
  2. Web模块对应一个Jar包,即Servlet 3.0可以将每个Servlet、Filter、Listener打成jar包,然后放在WEB-INF\lib中。
  3. 每个模块都有自己的配置文件,这个配置文件的名称为 web-fragment.xml 。
  4. 制作一个Servlet模块的步骤:
  • 正常编写Servlet,并编译;
  • 将此编译class文件及所在包通过jar包命令打成jar包;
  • 将此jar包用winrar打开,将META-INF中的manifest删除后添加 web-fragment.xml;
  • 将此jar包放入WEB-INF\lib中即可;
  1. 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文件中指定的加载顺序。
  1. 如何用myEclipse打jar包(有些人不知道)

右键你web项目里的编写的servlet(或filter或listener)类——>Export…——>JAR file——>NEXT——>(Browse)填写导出名字和存放位置——>finish

这样就生成了我们需要的jar包了

  1. 示例

servlet类代码片:

@WebServlet(value = "/hello/snow")
public class HelloWorldServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("DO GEt..." + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

}

访问:

servlet3.0提供的异步处理


提供异步原因


在以前的servlet中,如果作为控制器的servlet调用了一个较为耗时的业务方法,则servlet必须等到业务执行完后才会生成响应,这使得这次调用成了阻塞式调用,效率比较差


实现异步原理


重新开一个线程单独去调用耗时的业务方法。


配置servlet类成为异步的servlet类


  1. 通过注解asyncSupported=true实现
  2. 通过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(上传文件)


  1. 改进内容

HttpServletRequest增加了对上传文件的支持

ServletContext允许通过编程的方式动态注册Servlet、Filter


  1. HttpServletRequest提供了如下两个方法处理文件的上传

Part getPart(String name) 根据名称获取文件上传域

Collection<Part> getParts() 获取所有文件上传域


  1. 上传文件时一定要为表单域设置enctype属性,它表示表单数据的编码方式,有如下三个值:


application/x-www-form-urlencoded (默认),它只处理表单里的value属性值,它会将value值处理成URL编码方式。如果此时表单域里有上传文件的域(type=”file”),则只会获取该文件在上传者电脑里的绝对路径串,该串没什么实际意义。

  • multipart/form-data 此处编码方式会以二制流的方式来处理表单数据,此时会将文件内容也封装到请求参数里。
  • texst/plain 当表单的action属性为mailto:URL的形式时比较方便,主要适用于直接通过表单发送邮件的方式


  1. 上传文件的Servlet需要加上@MultipartConfig注解


  1. 通过request获取的Part对象就可以操作文件域了


  1. 示例
@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应用设置初始化参数。


需要导包

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
</dependency>
相关文章
若依框架----登录界面美化
若依框架----登录界面美化
1455 0
|
6月前
|
Java 数据库连接 数据库
Java 组件详细使用方法与封装实战指南
本指南详解Java核心组件使用与封装技巧,涵盖跨平台开发、面向对象编程、多线程、数据库操作等关键内容,并提供工具类、连接池、异常及响应结果的封装方法。结合Spring框架、MyBatis、Spring Boot等主流技术,助你掌握高质量Java组件设计与开发实践。
205 2
|
Java 测试技术 API
Zookeeper开源客户端Curator之基本功能讲解
Zookeeper开源客户端Curator之基本功能讲解
754 0
Zookeeper开源客户端Curator之基本功能讲解
|
XML 缓存 Java
一文讲明Mybatis 的使用 超详细 【爆肝两万字教程】
文章提供了一份详尽的Mybatis使用教程,涵盖了Mybatis的简介、环境搭建、基本操作、配置解析、日志使用、分页、注解开发、多对一和一对多关系处理、动态SQL以及缓存机制等方面的内容,并提供了相应的代码示例和测试用例。
一文讲明Mybatis 的使用 超详细 【爆肝两万字教程】
|
6月前
|
搜索推荐 Linux iOS开发
qBittorrent:专业级磁力种子下载工具,高速稳定 + 全功能资源管理
qBittorrent 是一款免费、开源且无广告的 P2P BitTorrent 客户端,支持 Windows、Mac 和 Linux 系统。它功能强大,包含 DHT、Peer Exchange、加密等技术,支持下载优先级设置、RSS 订阅和远程控制。用户可通过 Torrent 文件或磁力链接下载资源,并能优化连接设置以提升速度。常见问题如“元数据下载”或 DHT 连接不佳时,建议使用热门种子或调整 trackers。
4479 0
|
12月前
|
消息中间件 RocketMQ
2024最全RocketMQ集群方案汇总
在研究RocketMQ集群方案时,发现网上存在诸多不一致之处,如组件包含NameServer、Broker、Proxy等。通过查阅官方文档,了解到v4.x和v5.x版本的差异。v4.x部署模式包括单主、多主、多主多从(异步复制、同步双写),而v5.x新增Local与Cluster模式,主要区别在于Broker和Proxy是否同进程部署。Local模式适合平滑升级,Cluster模式适合高可用需求。不同模式下,集群部署方案大致相同,涵盖单主、多主、多主多从等模式,以满足不同的高可用性和性能需求。
1652 0
|
存储 Java 数据处理
Spring揭秘:ClassPathScanningProvider接口应用场景及实现原理!
ClassPathScanningCandidateComponentProvider是Spring框架中一个非常核心的类,它主要用于在类路径下扫描并发现带有特定注解的组件,支持诸如@ComponentScan、@Component、@Service、@Repository和@Controller等注解的自动扫描和注册。
468 0
Spring揭秘:ClassPathScanningProvider接口应用场景及实现原理!
|
Web App开发 XML Java
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解(1)
Servlet执行流程&生命周期&方法介绍&体系结构、Request和Response的功能详解
404 2
|
存储 NoSQL 容灾
怎样保证Redis 保证数据不丢失?
Redis 数据不丢失主要靠持久化(RDB、AOF、混合)和集群运行(主从同步、哨兵、Cluster)。RDB是快照,恢复速度快但可能丢失部分数据;AOF记录所有命令,实时性好但写性能较低;混合持久化结合两者优点。集群通过多服务器分布数据,提高可用性和数据安全性。
513 5
|
C语言
C语言程序设计——if与else if的区别及用法
C语言程序设计——if与else if的区别及用法