servlet3_servlet3.0 - CSDN
精华内容
参与话题
  • servlet2和servlet3

    千次阅读 2018-04-30 20:59:29
    servlet是用java编写的服务端程序,主要功能在于交互式的浏览和修改程序,生成动态Web内容。...服务器将请求信息发送至servlet 3.servlet生成响应内容并将其传给服务器,响应内容动态生成,通常取决...
        servlet是用java编写的服务端程序,主要功能在于交互式的浏览和修改程序,生成动态Web内容。
    狭义的servlet是指java语言实现的一个接口,广义的servlet是指任何实现了这个servlet接口的类。这个过程为:
        1.客户端发送请求至服务器端
        2.服务器将请求信息发送至servlet
        3.servlet生成响应内容并将其传给服务器,响应内容动态生成,通常取决于客户端的请求
        4.服务器将响应返回给客户端
        servlet在实例化时会调用init()方法初始化,当一个客户端的请求到达server时,server创建一个请求对象和一个响应对象,并以此为参数调用servlet的service()方法。一般servlet只初始化一次,即只有一个对象,对于更多的客户端请求,Server创建新的请求和响应对象。每个请求由一个独立的线程处理。

    servlet2规范:
        servlet2.5特性介绍:支持annotations。
        1.项目目录必须要有WEB-INF、web.xml等文件夹和文件。
        2.在web.xml中配置servlet、filter、listener,以web.xml为java web项目的统一入口

    servlet3规范:
        1.项目中可以不需要WEB-INF、web.xml等文件夹和文件,在没有web.xml文件的情况下,通过注解实现servlet、filter、listener的声明,例如:@WebServlet,@WebListener,@WebFilter,当使用注解时,容器自动进行扫描。
        2.关于一些异步请求的改动
        3.关于ServletContainerInitializer的使用
    servlet3新特性:
        1.异步处理支持:servlet线程不再需要一直阻塞,直到业务处理完毕才再输出响应,最后才结束该servlet线程,
    在接收到请求后,servlet可以将耗时的操作委派给另一个线程去完成,自己在不生成响应的情况下返回至容器。
            servlet3之前,一个普通servlet的主要工作流程大致如下:首先,servlet接受到请求以后,可能需要对请求携带的数据进行一些预处理,接着,调用业务接口的某些方法,以完成业务处理。最后,根据处理的结果提交响应,servlet线程结束。其中业务处理通常是非常耗时的,主要体现在数据库操作以及跨网络调用等,在此过程中servlet线程一直处于阻塞状态,直到业务方法执行完毕。对于并发较大的应用,这有可能造成性能瓶颈。
            servlet3针对这个问题提供了异步处理支持,Servlet请求将请求转交给另一个线程去执行业务逻辑,线程本身返回至容器,此时servlet还没有生成响应数据。异步线程处理完业务以后,可以直接生成响应结果或者转交给其它servlet处理。如此一来,servlet不再一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程后可以立即返回。
            异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用:
    对于使用传统的部署描述文件 (web.xml) 配置 Servlet 和过滤器的情况,Servlet 3.0 为 <servlet> 和 <filter> 标签增加了 <async-supported> 子标签,该标签的默认取值为 false,要启用异步处理支持,则将其设为 true 即可
    <servlet>
        <servlet-name>DemoServlet</servlet-name>
        <servlet-class>footmark.servlet.Demo Servlet</servlet-class>
        <async-supported>true</async-supported>
    </servlet>   
    对于使用 Servlet 3.0 提供的 @WebServlet 和 @WebFilter 进行 Servlet 或过滤器配置的情况,这两个注解都提供了 asyncSupported 属性,默认该属性的取值为 false,要启用异步处理支持,只需将该属性设置为 true 即可。以 @WebFilter 为例,其配置方式如下所示:

    @WebFilter(urlPatterns = "/demo",asyncSupported = true)
    public class DemoFilter implements Filter{...}
    一个简单的模拟异步处理的servlet:
    @WebServlet(urlPatterns = "/demo", asyncSupported = true)
    public class AsyncDemoServlet extends HttpServlet {
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException, ServletException {
            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 {
                //等待十秒钟,以模拟业务方法的执行
                Thread.sleep(10000);
                PrintWriter out = ctx.getResponse().getWriter();
                out.println("业务处理完毕的时间:" + new Date() + ".");
                out.flush();
                ctx.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
       除此之外,Servlet 3.0 还为异步处理提供了一个监听器,使用 AsyncListener 接口表示。它可以监控如下四种事件:
    异步线程开始时,调用 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
    异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event) 方法;
    异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
        异步执行完毕时,调用 AsyncListener 的 onComplete(AsyncEvent event) 方法;
    要注册一个AsyncListener,只需要将准备好的AsyncListener对象传递给AsyncContext对象的addListener()方法。
    AsyncContext ctx = req.startAsync();
    ctx.addListener(new AsyncListener() {
        public void onComplete(AsyncEvent asyncEvent) throws IOException {
            // 做一些清理工作或者其他
        }
        ...
    });
         2.新增注解支持:简化servlet,filter,listener的声明,使得web.xml不再是必需的了。

    @WebServlet

    @WebServlet 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值):

    表 1. @WebServlet 主要属性列表

    属性名类型描述
    nameString指定 Servlet 的 name 属性,等价于 <servlet-name>。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。
    valueString[]该属性等价于 urlPatterns 属性。两个属性不能同时使用。
    urlPatternsString[]指定一组 Servlet 的 URL 匹配模式。等价于 <url-pattern> 标签。
    loadOnStartupint指定 Servlet 的加载顺序,等价于 <load-on-startup> 标签。
    initParamsWebInitParam[]指定一组 Servlet 初始化参数,等价于 <init-param> 标签。
    asyncSupportedboolean声明 Servlet 是否支持异步操作模式,等价于 <async-supported> 标签。
    descriptionString该 Servlet 的描述信息,等价于 <description> 标签。
    displayNameString该 Servlet 的显示名,通常配合工具使用,等价于 <display-name> 标签。

    下面是一个简单的示例:
    @WebServlet(urlPatterns = {"/simple"}, asyncSupported = true,
    loadOnStartup = -1, name = "SimpleServlet", displayName = "ss",
    initParams = {@WebInitParam(name = "username", value = "tom")}
    )
    public class SimpleServlet extends HttpServlet{ … }
    如此配置之后,就可以不必在 web.xml 中配置相应的 <servlet> 和 <servlet-mapping> 元素了,容器会在部署时根据指定的属性将该类发布为 Servlet。它的等价的 web.xml 配置形式如下:
    <servlet>
        <display-name>ss</display-name>
        <servlet-name>SimpleServlet</servlet-name>
        <servlet-class>footmark.servlet.SimpleServlet</servlet-class>
        <load-on-startup>-1</load-on-startup>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>username</param-name>
            <param-value>tom</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SimpleServlet</servlet-name>
        <url-pattern>/simple</url-pattern>
    </servlet-mapping>

    @WebInitParam

    该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数,这等价于 web.xml 中 <servlet> 和 <filter> 的 <init-param> 子标签。@WebInitParam 具有下表给出的一些常用属性:
    表 2. @WebInitParam 的常用属性

    属性名类型是否可选描述
    nameString指定参数的名字,等价于 <param-name>。
    valueString指定参数的值,等价于 <param-value>。
    descriptionString关于参数的描述,等价于 <description>。

    @WebFilter

    @WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 ):
    表 3. @WebFilter 的常用属性

    属性名类型描述
    filterNameString指定过滤器的 name 属性,等价于 <filter-name>
    valueString[]该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
    urlPatternsString[]指定一组过滤器的 URL 匹配模式。等价于 <url-pattern> 标签。
    servletNamesString[]指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 <servlet-name> 的取值。
    dispatcherTypesDispatcherType
    指定过滤器的转发模式。具体取值包括:

    ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
    initParamsWebInitParam[]指定一组过滤器初始化参数,等价于 <init-param> 标签。
    asyncSupportedboolean声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签。
    descriptionString该过滤器的描述信息,等价于 <description> 标签。
    displayNameString该过滤器的显示名,通常配合工具使用,等价于 <display-name> 标签。

    下面是一个简单的示例:
    @WebFilter(servletNames = {"SimpleServlet"},filterName="SimpleFilter")
    public class LessThanSixFilter implements Filter{...}
    如此配置之后,就可以不必在 web.xml 中配置相应的 <filter> 和 <filter-mapping> 元素了,容器会在部署时根据指定的属性将该类发布为过滤器。它等价的 web.xml 中的配置形式为:
    <filter>
        <filter-name>SimpleFilter</filter-name>
        <filter-class>xxx</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SimpleFilter</filter-name>
        <servlet-name>SimpleServlet</servlet-name>
    </filter-mapping>

    @WebListener

    该注解用于将类声明为监听器,被 @WebListener 标注的类必须实现以下至少一个接口:
    ServletContextListener
    ServletContextAttributeListener
    ServletRequestListener
    ServletRequestAttributeListener
    HttpSessionListener
    HttpSessionAttributeListener
    该注解使用非常简单,其属性如下:
    表 4. @WebListener 的常用属性

    属性名类型是否可选描述
    valueString该监听器的描述信息。

    一个简单示例如下:
    @WebListener("This is only a demo listener")
    public class SimpleListener implements ServletContextListener{...}
    如此,则不需要在 web.xml 中配置 <listener> 标签了。它等价的 web.xml 中的配置形式如下:
    <listener>
        <listener-class>footmark.servlet.SimpleListener</listener-class>
    </listener>

    @MultipartConfig

    该注解主要是为了辅助 Servlet 3.0 中 HttpServletRequest 提供的对上传文件的支持。该注解标注在 Servlet 上面,以表示该 Servlet 希望处理的请求的 MIME 类型是 multipart/form-data。另外,它还提供了若干属性用于简化对上传文件的处理。具体如下:
    表 5. @MultipartConfig 的常用属性

    属性名类型是否可选描述
    fileSizeThresholdint当数据量大于该值时,内容将被写入文件。
    locationString存放生成的文件地址。
    maxFileSizelong允许上传的文件最大值。默认值为 -1,表示没有限制。
    maxRequestSizelong针对该 multipart/form-data 请求的最大数量,默认值为 -1,表示没有限制。


    可插性支持:
    如果说 3.0 版本新增的注解支持是为了简化 Servlet/ 过滤器 / 监听器的声明,从而使得 web.xml 变为可选配置, 那么新增的可插性 (pluggability) 支持则将 Servlet 配置的灵活性提升到了新的高度。熟悉 Struts2 的开发者都知道,Struts2 通过插件的形式提供了对包括 Spring 在内的各种开发框架的支持,开发者甚至可以自己为 Struts2 开发插件,而 Servlet 的可插性支持正是基于这样的理念而产生的。使用该特性,现在我们可以在不修改已有 Web 应用的前提下,只需将按照一定格式打成的 JAR 包放到 WEB-INF/lib 目录下,即可实现新功能的扩充,不需要额外的配置。
    Servlet 3.0 引入了称之为“Web 模块部署描述符片段”的 web-fragment.xml 部署描述文件,该文件必须存放在 JAR 文件的 META-INF 目录下,该部署描述文件可以包含一切可以在 web.xml 中定义的内容。JAR 包通常放在 WEB-INF/lib 目录下,除此之外,所有该模块使用的资源,包括 class 文件、配置文件等,只需要能够被容器的类加载器链加载的路径上,比如 classes 目录等。
    现在,为一个 Web 应用增加一个 Servlet 配置有如下三种方式 ( 过滤器、监听器与 Servlet 三者的配置都是等价的,故在此以 Servlet 配置为例进行讲述,过滤器和监听器具有与之非常类似的特性 ):
    编写一个类继承自 HttpServlet,将该类放在 classes 目录下的对应包结构中,修改 web.xml,在其中增加一个 Servlet 声明。这是最原始的方式;
    编写一个类继承自 HttpServlet,并且在该类上使用 @WebServlet 注解将该类声明为 Servlet,将该类放在 classes 目录下的对应包结构中,无需修改 web.xml 文件。
    编写一个类继承自 HttpServlet,将该类打成 JAR 包,并且在 JAR 包的 META-INF 目录下放置一个 web-fragment.xml 文件,该文件中声明了相应的 Servlet 配置。web-fragment.xml 文件示例如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-fragment
        xmlns=http://java.sun.com/xml/ns/javaee
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
        metadata-complete="true">
        <servlet>
            <servlet-name>fragment</servlet-name>
            <servlet-class>footmark.servlet.FragmentServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>fragment</servlet-name>
            <url-pattern>/fragment</url-pattern>
        </servlet-mapping>
    </web-fragment>
    从上面的示例可以看出,web-fragment.xml 与 web.xml 除了在头部声明的 XSD 引用不同之外,其主体配置与 web.xml 是完全一致的。
    由于一个 Web 应用中可以出现多个 web-fragment.xml 声明文件,加上一个 web.xml 文件,加载顺序问题便成了不得不面对的问题。Servlet 规范的专家组在设计的时候已经考虑到了这个问题,并定义了加载顺序的规则。
    web-fragment.xml 包含了两个可选的顶层标签,<name> 和 <ordering>,如果希望为当前的文件指定明确的加载顺序,通常需要使用这两个标签,<name> 主要用于标识当前的文件,而 <ordering> 则用于指定先后顺序。一个简单的示例如下:
    <web-fragment...>
        <name>FragmentA</name>
        <ordering>
            <after>
                <name>FragmentB</name>
                <name>FragmentC</name>
            </after>
        <before>
            <others/>
        </before>
        </ordering>
        ...
    </web-fragment>
    如上所示, <name> 标签的取值通常是被其它 web-fragment.xml 文件在定义先后顺序时引用的,在当前文件中一般用不着,它起着标识当前文件的作用。
    在 <ordering> 标签内部,我们可以定义当前 web-fragment.xml 文件与其他文件的相对位置关系,这主要通过 <ordering> 的 <after> 和 <before> 子标签来实现的。在这两个子标签内部可以通过 <name> 标签来指定相对应的文件。比如:
    <after>
        <name>FragmentB</name>
        <name>FragmentC</name>
    </after>
    以上片段则表示当前文件必须在 FragmentB 和 FragmentC 之后解析。<before> 的使用于此相同,它所表示的是当前文件必须早于 <before> 标签里所列出的 web-fragment.xml 文件。
    除了将所比较的文件通过 <name> 在 <after> 和 <begin> 中列出之外,Servlet 还提供了一个简化的标签 <others/>。它表示除了当前文件之外的其他所有的 web-fragment.xml 文件。该标签的优先级要低于使用 <name> 明确指定的相对位置关系

    4.ServletContext对象的功能在新版本中也得到了增强,现在,该对象支持在运行时动态部署Servlet,过滤器,监听器,以及为Servlet和过滤器增加URL映射等。
    5.HttpServletRequest对文件上传的支持
        此前,对于处理上传文件的操作一直是让开发者头疼的问题,因为 Servlet 本身没有对此提供直接的支持,需要使用第三方框架来实现,而且使用起来也不够简单。如今这都成为了历史,Servlet 3.0 已经提供了这个功能,而且使用也非常简单。为此,HttpServletRequest 提供了两个方法用于从请求中解析出上传的文件:
    Part getPart(String name)
    Collection<Part> getParts()
    前者用于获取请求中给定 name 的文件,后者用于获取所有的文件。每一个文件用一个 javax.servlet.http.Part 对象来表示。该接口提供了处理文件的简易方法,比如 write()、delete() 等。至此,结合 HttpServletRequest 和 Part 来保存上传的文件变得非常简单,如下所示:
    Part photo = request.getPart("photo");
    photo.write("/tmp/photo.jpg");
    // 可以将两行代码简化为 request.getPart("photo").write("/tmp/photo.jpg") 一行。
    另外,开发者可以配合前面提到的 @MultipartConfig 注解来对上传操作进行一些自定义的配置,比如限制上传文件的大小,以及保存文件的路径等。其用法非常简单,故不在此赘述了。
    需要注意的是,如果请求的 MIME 类型不是 multipart/form-data,则不能使用上面的两个方法,否则将抛异常。
    servlet3.1:
        Non-blocking I/O,HTTP protocol upgrade mechanism

    servlet理解和Spring的DispatcherServlet理解及之间关系
    1.servlet是服务器端运行的一个程序,是一个被编译好的java类,它不是框架。
    2.web容器的启动,需要servlet,当web服务器开始执行时,servlet类就被初始化。
    3.当用户通过浏览器访问的时候,会输入URL,这个时候,web服务器就通过servlet来分发请求执行不同的内容。
    4.一般会使用tomcat运行java的web项目,通常在web项目的目录中可以看到WEB-INF这样的文件夹,这个文件夹是受保护的,外部是无法通过url访问的,文件夹里包含了web.xml以及classes和libs目录,要想将web项目运行起来,就得在web.xml中定义一个Servlet,因为定义了servlet,web才知道如何去分发请求进行业务处理。
    5.一个使用spring的servlet为:org.springframework.web.servlet.DispatcherServlet
    6.HttpServlet是一个抽象类,具体的实现自己需要的servlet需要通过继承该类来实现。HttpServlet中主要的几个方法:doGet(),doPost(),doPut(),doDelete()。Servlet最终调用的是service方法。


    展开全文
  • 在一些基于Spring/Spring MVC的Java Web项目中,总是会有一些xml...由于本文是基于Servlet 3,所以首先需要准备支持Servlet 3的容器,例如Tomcat 7.0及以上版本、Jetty 8及以上版本。1、去除web.xml下面是一个典型的

    在一些基于Spring/Spring MVC的Java Web项目中,总是会有一些xml配置文件,如web.xml、applicationContext.xml等,本文的目标即消灭这些xml配置文件,用代码和注解来代替。

    由于本文是基于Servlet 3,所以首先需要准备支持Servlet 3的容器,例如Tomcat 7.0及以上版本、Jetty 8及以上版本。

    1、去除web.xml

    下面是一个典型的web.xml,包含Spring/Spring MVC的配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app 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-app_3_0.xsd"
    	version="3.0">
    
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:applicationContext.xml</param-value>
    	</context-param>
    	<servlet>
    		<servlet-name>dispatcher</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:dispatcher-servlet.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>dispatcher</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    </web-app>

    下一步是去除web.xml文件,用Java代码代替它。

    Spring MVC提供了一个接口WebApplicationInitializer,用于替代web.xml配置文件。实现该接口的类会在Servlet容器启动时自动加载并运行。

    将以上xml文件转换成Java代码:

    public class MyWebAppInitializer implements WebApplicationInitializer {
    
    	/**
    	 * Servlet容器启动时会自动运行该方法
    	 */
    	@Override
    	public void onStartup(ServletContext servletContext) throws ServletException {
    
    		servletContext.setInitParameter("contextConfigLocation", "classpath:applicationContext.xml");
    
    		ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", new DispatcherServlet());
    		registration.setLoadOnStartup(1);
    		registration.addMapping("/");
    		registration.setInitParameter("contextConfigLocation", "classpath:dispatcher-servlet.xml");
    
    		servletContext.addListener(new ContextLoaderListener());
    	}
    }

    此时便可删除web.xml。


    2、去除Spring MVC配置文件dispatcher-servlet.xml

    一个典型的Spring MVC配置文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
     
        <mvc:annotation-driven />
         
        <context:component-scan base-package="com.xxg.controller" />
         
        <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
        </bean>
         
    </beans>

    Spring提供了@Configuration注解用于替代xml配置文件,@Bean注解可以替代xml中的<bean>来创建bean。

    将以上xml配置文件转换成Java代码:

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = "com.xxg.controller")
    public class WebConfig {
    	
    	@Bean
    	public InternalResourceViewResolver internalResourceViewResolver() {
    		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    		viewResolver.setPrefix("/WEB-INF/jsp/");
    		viewResolver.setSuffix(".jsp");
    		return viewResolver;
    	}
    }

    3、去除Spring配置文件applicationContext.xml

    Spring的配置文件中内容可能会比较多,并且不同的项目会有不同的配置,以下提供了一个简单的配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    	<context:component-scan base-package="com.xxg">
    		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    	</context:component-scan>
    	
    	<context:property-placeholder location="classpath:config.properties"/>
    	
    	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    	    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    	    <property name="url" value="${jdbc.url}"/>
    	    <property name="username" value="${jdbc.username}"/>
    	    <property name="password" value="${jdbc.password}"/>
    	</bean>
    
    </beans>
    其中数据库的相关配置从config.properties配置文件读取:

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mydb
    jdbc.username=root
    jdbc.password=123456

    将以上xml配置转换成Java代码:

    @Configuration
    @ComponentScan(basePackages = "com.xxg", excludeFilters = {@Filter(value = Controller.class)})
    public class AppConfig {
         
        @Value("${jdbc.driverClassName}")
        private String driverClassName;
         
        @Value("${jdbc.url}")
        private String url;
     
        @Value("${jdbc.username}")
        private String username;
     
        @Value("${jdbc.password}")
        private String password;
     
        @Bean(destroyMethod = "close")
        public DataSource dataSource() {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
        
        /**
         * 必须加上static
         */
        @Bean
        public static PropertyPlaceholderConfigurer loadProperties() {
            PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
            ClassPathResource resource = new ClassPathResource("config.properties");
            configurer.setLocations(resource);
            return configurer;
        }
    }

    除了上面的方法外,加载properties配置文件还可以使用@PropertySource注解,Java代码也可以这样写:

    @Configuration
    @ComponentScan(basePackages = "com.xxg", excludeFilters = {@Filter(value = Controller.class)})
    @PropertySource("classpath:config.properties")
    public class AppConfig {
    	
        @Value("${jdbc.driverClassName}")
        private String driverClassName;
    	
        @Value("${jdbc.url}")
        private String url;
    
        @Value("${jdbc.username}")
        private String username;
    
        @Value("${jdbc.password}")
        private String password;
    
        @Bean(destroyMethod = "close")
        public DataSource dataSource() {
        	BasicDataSource dataSource = new BasicDataSource();
        	dataSource.setDriverClassName(driverClassName);
        	dataSource.setUrl(url);
        	dataSource.setUsername(username);
        	dataSource.setPassword(password);
        	return dataSource;
        }
        
        /**
         * 必须加上static
         */
        @Bean
        public static PropertySourcesPlaceholderConfigurer loadProperties() {
        	PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            return configurer;
        }
    }

    以上两种Java编码方式选择其中一种即可。

    4、修改MyWebAppInitializer.java

    完成以上步骤后,就可以去掉dispatcher-servlet.xml和applicationContext.xml等Spring配置文件,用Java代码替代了。

    此时,第1步中的MyWebAppInitializer.java需要修改,不再读取xml配置文件,而是加载@Configuration注解的Java代码来配置Spring:

    public class MyWebAppInitializer implements WebApplicationInitializer {
    
        /**
         * Servlet容器启动时会自动运行该方法
         */
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
             
            AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            rootContext.register(AppConfig.class);
            servletContext.addListener(new ContextLoaderListener(rootContext));
             
            AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
            webContext.register(WebConfig.class);
            ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", new DispatcherServlet(webContext));
            registration.setLoadOnStartup(1);
            registration.addMapping("/");
        }
    }

    至此,便完成了Java程序替换xml配置文件。
    展开全文
  • Servlet3与Servlet4

    千次阅读 2019-03-11 09:38:28
    Servlet3 Servlet 3.0 新特性 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另...

    Servlet3

    Servlet 3.0 新特性

    • 异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。

    • 新增的注解支持:该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。

    • 可插性支持:熟悉 Struts2 的开发者一定会对其通过插件的方式与包括 Spring 在内的各种常用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。现在 Servlet 3.0 提供了类似的特性,开发者可以通过插件的方式很方便的扩充已有 Web 应用的功能,而不需要修改原有的应用

    消息异步

    Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:

    1. Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理
    2. 调用业务接口的某些方法,以完成业务处理;
    3. 最后,根据处理的结果提交响应,Servlet 线程结束。

    Servlet2.x详细说明:

    其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕。在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大的应用,这有可能造成性能的瓶颈。对此,在以前通常是采用私有解决方案来提前结束 Servlet 线程,并及时释放资源。

    Servlet3优化改进:

    1. Servlet 接收到请求之后,可能首先需要对请求携带的数据进行一些预处理
    2. 接着,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用),或者将请求继续转发给其它 Servlet。如此一来, Servlet 线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。

    web.xml
    servlet3为filter和servlet增加了异步支持标签,<async-supported>,默认是false,需要手动开启

    <servlet> 
        <servlet-name>DemoServlet</servlet-name> 
        <servlet-class>footmark.servlet.Demo Servlet</servlet-class> 
        <async-supported>true</async-supported> 
    </servlet>
    

    注解
    注解增加了属性asyncSupported支持异步

    @WebFilter(urlPatterns = "/demo",asyncSupported = true) 
    public class DemoFilter implements Filter{...}
    

    异步Demo如下:

    @WebServlet(urlPatterns = "/demo", asyncSupported = true)
    public class AsyncDemoServlet extends HttpServlet {
        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException, ServletException {
            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 {
                //等待十秒钟,以模拟业务方法的执行
                Thread.sleep(10000);
                PrintWriter out = ctx.getResponse().getWriter();
                out.println("业务处理完毕的时间:" + new Date() + ".");
                out.flush();
                ctx.complete();	//告诉context,这个子线程完毕
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    为了监听异步事件,Servlet3提供了AsyncListener事件监听器

    1. 异步线程开始时,调用 AsyncListener 的 onStartAsync(AsyncEvent event)方法;
    2. 异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event)方法;
    3. 异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event)方法;
    4. 异步执行完毕时,调用 AsyncListener 的 onComplete(AsyncEvent event) 方法;

    要注册一个 AsyncListener,只需将准备好的 AsyncListener 对象传递给 AsyncContext 对象的 addListener() 方法即可

    AsyncContext ctx = req.startAsync(); 
    ctx.addListener(new AsyncListener() { 
        public void onComplete(AsyncEvent asyncEvent) throws IOException { 
            // 做一些业务操作
        } 
        ... 
    });
    

    注解支持

    @WebServlet

    @WebServlet 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值):

    属性名 类型 描述
    name String 指定 Servlet 的 name 属性,等价于 <servlet-name>。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。
    value String[] 该属性等价于 urlPatterns 属性。两个属性不能同时使用。
    urlPatterns String[] 指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签。
    loadOnStartup int 指定 Servlet 的加载顺序,等价于 <load-on-startup> 标签。
    initParams WebInitParam[] 指定一组 Servlet 初始化参数,等价于 <init-param> 标签。
    asyncSupported boolean 声明 Servlet 是否支持异步操作模式,等价于 <async-supported> 标签。
    description String 该 Servlet 的描述信息,等价于 <description> 标签。
    displayName String 该 Servlet 的显示名,通常配合工具使用,等价于<display-name>标签。

    监听使用如下:

    @WebServlet(urlPatterns = {"/simple"}, asyncSupported = true, 
    loadOnStartup = -1, name = "SimpleServlet", displayName = "ss", 
    initParams = {@WebInitParam(name = "username", value = "tom")} 
    ) 
    public class SimpleServlet extends HttpServlet{}
    

    @WebInitParam

    该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数,这等价于 web.xml 中 和 的 子标签。@WebInitParam 具有下表给出的一些常用属性:

    属性名 类型 是否可选 描述
    name String 指定参数的名字,等价于<param-name>
    value String 指定参数的值,等价于<param-value>
    description String 关于参数的描述,等价于 <description>

    @WebFilter

    @WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 ):

    属性名 类型 描述
    filterName String 指定过滤器的 name 属性,等价于 <filter-name>
    value String[] 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
    urlPatterns String[] 指定一组过滤器的 URL 匹配模式。等价于<url-pattern>标签。
    servletNames String[] 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是web.xml 中<servlet-name> 的取值。
    dispatcherTypes DispatcherType 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
    initParams WebInitParam[] 指定一组过滤器初始化参数,等价于 <init-param>标签。
    asyncSupported boolean 声明过滤器是否支持异步操作模式,等价于<async-supported> 标签。
    description String 该过滤器的描述信息,等价于 <description>标签。
    displayName String 该过滤器的显示名,通常配合工具使用,等价于 <display-name>标签。

    @WebListener

    该注解用于将类声明为监听器,被 @WebListener 标注的类必须实现以下至少一个接口:

    • ServletContextListener
    • ServletContextAttributeListener
    • ServletRequestListener
    • ServletRequestAttributeListener
    • HttpSessionListener
    • HttpSessionAttributeListener

    这个接口只有一个默认value属性
    一个简单示例如下:

    @WebListener("This is only a demo listener") 
    public class SimpleListener implements ServletContextListener{...}
    

    如此,则不需要在 web.xml 中配置<listener> 标签了。它等价的 web.xml 中的配置形式如下:

    <listener> 
        <listener-class>footmark.servlet.SimpleListener</listener-class> 
    </listener>
    

    @MultipartConfig

    该注解主要是为了辅助 Servlet 3.0 中 HttpServletRequest 提供的对上传文件的支持。该注解标注在 Servlet 上面,以表示该 Servlet 希望处理的请求的 MIME 类型是 multipart/form-data。另外,它还提供了若干属性用于简化对上传文件的处理。具体如下:

    属性名 类型 是否可选 描述
    fileSizeThreshold int 当数据量大于该值时,内容将被写入文件。
    location String 存放生成的文件地址。
    maxFileSize long 允许上传的文件最大值。默认值为 -1,表示没有限制。
    maxRequestSize long 针对该 multipart/form-data 请求的最大数量,默认值为 -1,表示没有限制。

    可插性支持

    Servlet 3.0 引入了称之为“Web 模块部署描述符片段”的 web-fragment.xml 部署描述文件,该文件必须存放在 JAR 文件的 META-INF 目录下,该部署描述文件可以包含一切可以在 web.xml 中定义的内容。JAR 包通常放在 WEB-INF/lib 目录下,除此之外,所有该模块使用的资源,包括 class 文件、配置文件等,只需要能够被容器的类加载器链加载的路径上,比如 classes 目录等。

    • 编写一个类继承自 HttpServlet,将该类放在 classes 目录下的对应包结构中,修改 web.xml,在其中增加一个 Servlet 声明。这是最原始的方式;
    • 编写一个类继承自 HttpServlet,并且在该类上使用 @WebServlet 注解将该类声明为 Servlet,将该类放在 classes 目录下的对应包结构中,无需修改 web.xml 文件。
    • 编写一个类继承自 HttpServlet,将该类打成 JAR 包,并且在 JAR 包的 META-INF 目录下放置一个 web-fragment.xml 文件,该文件中声明了相应的 Servlet 配置。
    <?xml version="1.0" encoding="UTF-8"?>
    <web-fragment
        xmlns=http://java.sun.com/xml/ns/javaee
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
        metadata-complete="true">
        <servlet>
            <servlet-name>fragment</servlet-name>
            <servlet-class>footmark.servlet.FragmentServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>fragment</servlet-name>
            <url-pattern>/fragment</url-pattern>
        </servlet-mapping>
    </web-fragment>
    

    web-fragment.xml 包含了两个可选的顶层标签, 和 ,如果希望为当前的文件指定明确的加载顺序,通常需要使用这两个标签, 主要用于标识当前的文件,而 则用于指定先后顺序。

    <web-fragment...>
        <name>FragmentA</name>
        <ordering>
            <after>
                <name>FragmentB</name>
                <name>FragmentC</name>
            </after>
        <before>
            <others/>
        </before>
        </ordering>
        ...
    </web-fragment>
    

    ServletContext 的性能增强

    该对象支持在运行时动态部署 Servlet、过滤器、监听器,以及为 Servlet 和过滤器增加 URL 映射等。以 Servlet 为例,过滤器与监听器与之类似。ServletContext 为动态配置 Servlet 增加了如下方法:

    • ServletRegistration.Dynamic addServlet(String servletName,Class<? extends Servlet> servletClass)
    • ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
    • ServletRegistration.Dynamic addServlet(String servletName, String className)
    • <T extends Servlet> T createServlet(Class clazz)
    • ServletRegistration getServletRegistration(String servletName)
    • Map<String,? extends ServletRegistration> getServletRegistrations()

    其中前三个方法的作用是相同的,只是参数类型不同而已;通过 createServlet() 方法创建的 Servlet,通常需要做一些自定义的配置,然后使用 addServlet() 方法来将其动态注册为一个可以用于服务的 Servlet。两个 getServletRegistration() 方法主要用于动态为 Servlet 增加映射信息,这等价于在 web.xml( 抑或 web-fragment.xml) 中使用 <servlet-mapping> 标签为存在的 Servlet 增加映射信息。

    以上 ServletContext 新增的方法要么是在 ServletContextListener 的 contexInitialized 方法中调用,要么是在 ServletContainerInitializer 的 onStartup() 方法中调用。

    ServletContainerInitializer 也是 Servlet 3.0 新增的一个接口,容器在启动时使用 JAR 服务 API(JAR Service API) 来发现 ServletContainerInitializer 的实现类,并且容器将 WEB-INF/lib 目录下 JAR 包中的类都交给该类的 onStartup() 方法处理,我们通常需要在该实现类上使用 @HandlesTypes 注解来指定希望被处理的类,过滤掉不希望给 onStartup() 处理的类。

    HttpServletRequest 对文件上传的支持

    之前上次文件必须借助第三方jar来实现,比如Apache的IO包
    Servlet 3.0 已经提供了这个功能,而且使用也非常简单。

    • Part getPart(String name)
    • Collection getParts()

    前者用于获取请求中给定 name 的文件,后者用于获取所有的文件。每一个文件用一个 javax.servlet.http.Part 对象来表示。该接口提供了处理文件的简易方法,比如 write()、delete() 等。至此,结合 HttpServletRequest 和 Part 来保存上传的文件变得非常简单,如下所示:

    Part photo = request.getPart("photo"); 
    photo.write("/tmp/photo.jpg"); 
    // 可以将两行代码简化为 request.getPart("photo").write("/tmp/photo.jpg") 一行。
    

    开发者可以配合前面提到的 @MultipartConfig 注解来对上传操作进行一些自定义的配置,比如限制上传文件的大小,以及保存文件的路径等。

    Servlet4

    Servlet 4.0 的主要新功能为服务器推送和全新 API,该 API 可在运行时发现 servlet 的 URL 映射。

    服务器推送是最直观的 HTTP/2 强化功能,通过 PushBuilder 接口在 servlet 中公开。服务器推送功能还在 JavaServer Faces API 中实现,并在 RenderResponsePhase 生命周期内调用,以便 JSF 页面可以利用其增强性能。

    全新 servlet 映射发现接口 HttpServletMapping 使框架能够获取有关激活给定 servlet 请求的 URL 信息。这可能对框架尤为有用,这些框架需要这一信息来运行内部工作。

    在接下来的部分,我将概述服务器推送及其如何在 Java servlet 中运行,包括 JSF 2.3 中的服务器推送。我还将展示一个交换示例,重点介绍全新 servlet 映射发现功能。

    服务器推送

    服务器推送使服务器能预测客户端请求的资源需求。然后,在完成请求处理之前,它可以将这些资源发送到客户端。

    要了解服务器推送的好处,可以考虑一个包含图像和其他依赖项(比如 CSS 和 JavaScript 文件)的网页。客户端发出一个针对该网页的请求。服务器然后分析所请求的页面,确定呈现它所需的资源,并主动将这些资源发送到客户端的缓存。

    在执行所有这些操作的同时,服务器仍在处理原始网页请求。客户端收到响应时,它需要的资源已经位于缓存中。

    PushBuilder

    多数来自原始 HttpServletRequest 实例的请求标头,只添加到 PushBuilder 实例中。由于正确运行服务器推送并不需要某些标头,因此不包括以下标头:

    • 条件标头
    • Range 标头
    • Expect 标头
    • Authorization 标头
    • Referrer 标头
    @Override
    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) 
                         throws ServletException, IOException {
     
       PushBuilder pushBuilder = request.newPushBuilder();
     
    }
    

    设置推送资源并推送

    PushBuilder pushBuilder = request.newPushBuilder();
     
    if (pushBuilder != null) {
       pushBuilder.path("images/hero-banner.jpg").push();
       pushBuilder.path("css/menu.css").push();
       pushBuilder.path("js/marquee.js").push();
    }
    

    HttpServletMapping 接口

    Servlet 4.0 的全新 servlet 映射发现 API 使服务器能够对 URL(可调用 servlet)执行运行时检查。例如,对 file.ext, /path 和 /path/file.ext 的请求将通过 URL 模式 /path/* 和 *.ext 激活 servlet。

    • getMatchValue() 返回部分 URI 路径,该路径会导致请求匹配。
    • getPattern() 返回 URL 模式的 String 表示形式。
    • getServletName() 返回 servlet 名称的 String 表示形式。
    • getMappingMatch() 返回匹配的类型,表示为 MappingMatch 枚举值,该枚举值将为以下值之一CONTEXT_ROOTDEFAULT、EXACTEXTENSIONPATH

    运行时映射发现:

    @WebServlet({"/path/*", "*.ext"})
    public class ServletMapping extends HttpServlet {
     
        protected void doGet(HttpServletRequest request,
                             HttpServletResponse response) 
                             throws IOException {
     
            HttpServletMapping mapping = request.getHttpServletMapping();
            String mapping = mapping.getMappingMatch().name();
            String value = mapping.getMatchValue();
            String pattern = mapping.getPattern();
            String servletName = mapping.getServletName();
       }
     
    }
    

    细微重构变化

    • Trailer 响应标头支持发送方在分块消息的末尾包含额外字段。这用于提供在发送消息主体时可能会动态生成的元数据,例如,消息完整性检查、数字签名或后期处理状态。
    • Servlet 4.0 添加了 GenericFilter 和 HttpFilter 抽象类,这些抽象类通过最低限度地实现生命周期方法 init() 和 destroy(),简化了编写过滤器。
    • Servlet 4.0 还集成了全新的 HTTP Trailer,支持发送方在分块消息的末尾包含额外的字段。

    ServletContext 接口采用了一些新方法:
    addJspFile() 可将带有给定 JSP 文件的 servlet 添加到 servlet 上下文中。
    getSessionTimeout() 和 setSessionTimeout() 可提供对会话超时的访问权限。
    getRequestCharacterEncoding() 和 setRequestCharacterEncoding() 可为当前的 servlet 上下文提供访问权限,并改变默认的请求字符编码。

    • HttpServletRequest 接口上的 isRequestedSessionIdFromUrl() 方法已被弃用。
      由于升级到 Java SE 8,默认方法已被添加到侦听器接口中。
    展开全文
  • Servlet3使用总结

    千次阅读 2018-11-09 17:56:29
     关于这个Servlet3,我是从我邮箱里的垃圾邮件中看到一个在线测评网站,好奇的我点进去了所谓的链接,第一轮测评题目是采用Servlet3技术去简单实现一个在线的网页时间展示。  Servlet3? Servlet? 在大二学...

        很久没发博文了,五月也已经过了一大半,想写点东西记录下来,就现在吧,把我最近经历的遇到的都总结下。

        关于这个Servlet3,我是从我邮箱里的垃圾邮件中看到一个在线测评网站,好奇的我点进去了所谓的链接,第一轮测评题目是采用Servlet3技术去简单实现一个在线的网页时间展示。

        Servlet3? Servlet? 在大二学JavaWeb的时候了解过,Servlet不是web容器嘛,还有Servlet技术这等词汇?的确,自己见识的确短浅,框架的衍生发展离不开基础的一些东西,还是自己孤陋寡闻了。好了我们开始谈谈这个Servlet3技术吧。

     

         1.什么是Servlet3?

            Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。总结来说Servlet就是一群人来制定Java应用中使用web时的各种规范,统一接口。

            //小感想~~~

            谈到Web应用,自己就是偏向学习这方面的,SSM,SpringBoot ... ,管理端的技术发展虽然不如前端那样大红大紫,几天就一个新框架,新特性,新元素,新标签。但是,也是在稳步发展的,我很羡慕那些很懂原理的大牛,有些问题发生了,你不深入研究发生的原因,只是在意表象上的解决方案,看到许多前辈踩下的坑,你只是避开走了,为何不往坑里观望观望呢?有时候,解决问题固然重要,但是解决问题的背后所隐藏的,更值得我们去发现。

        2.那么Servlet的工作流程是怎样的?

            

            白话来讲就是:一个http请求来了,web容器将http请求封装成servlet中的request对象,在这个request对象中你可以得到所有的http请求信息,当然你也可以取出来进行一顿操作,最后你在把数据封装成servlet的response对象返还给web容器,web容器将接收到的response对象解析之后封装成http response响应给客户端。就像上图一样,Servlet也有生命周期吗,我们也来分了解一下:

            Servlet 通过调用 init () 方法进行初始化。
            Servlet 调用 service() 方法来处理客户端的请求。
            Servlet 通过调用 destroy() 方法终止(结束)。
            最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

            根据Servlet重要的声明周期中用到的方法进行详细介绍:

    public void init() throws ServletException {
      // 初始化代码...
    }

            init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化。Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,也可以指定 Servlet 在服务器第一次启动时被加载。当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

    public void service(ServletRequest request, 
                        ServletResponse response) 
          throws ServletException, IOException{
    }

            service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

            doGet() 和 doPost() 方法是每次服务请求中最常用的方法。

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws ServletException, IOException {
        // Servlet 代码
    }

            GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
        throws ServletException, IOException {
        // Servlet 代码
    }

            POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

     public void destroy() {
        // 终止化代码...
      }

            destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。

        

     

            第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。

            Servlet 容器在调用 service() 方法之前加载 Servlet。

            然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。

            3.Servlet3新特性?

                 //详情见博客:https://blog.csdn.net/w410589502/article/details/58168292

                (1)Servlet、Filter、Listener无需在web.xml中进行配置,可以通过Annotation进行配置; 
                (2)模块化编程,即将各个Servlet模块化,将配置文件也分开配置。 
                (3)Servlet异步处理,应对复杂业务处理; 
                (4)异步Listener,对于异步处理的创建、完成等进行监听; 

                (5)文件上传API简化;

            4.我的Servlet3工程测试:采用Servlet3技术实现网页端的当前时间展示这一功能。

                1.在IDEA环境下,建立基于Maven的web工程

                2.建立java,resources文件夹,并mark directory as 

                3.引入所需要的依赖

                pom.xml文件:

    <!-- servlet3 依赖-->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.0.1</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.1</version>
          <scope>provided</scope>
        </dependency>

            这里可能会遇到一个问题:

                解决maven中servlet-api.jar和容器自带的servlet-api.jar的依赖冲突

                https://blog.csdn.net/hi__study/article/details/51627403

            在这里我们要先说一下Java中的日期和时间处理方法:
                Date类(官方不再推荐使用,官方解释Date类不利于国际化,推荐使用Calendar类)
                Calendar类

                DateFormat类 使用此类来时间初始化

            这个小例子用的是Calender类,TimeServlet如下:

            

         有五个点需要注意:

         1. 刚才提到了Servlet3新特性中支持了注解方式,省去了web.xml的拦截器,请求格式的设定。这里用到了@WebServlet注解,是不是和@Controller注解很类似,name就是这个Servlet类,urLPatterns就是请求的URL格式。详细的@WebServlet注解的参数配置见博文:https://blog.csdn.net/mytt_10566/article/details/70173007

         2. 设置响应对象response:刷新页面请求,编码格式等。

         3.Servlet的内置输出对象:out,可以直接输出HTML,数据等。

         4.Calender时间类的使用:Calender是静态方法getInstence()方法可以初始化一个日历对象,调用其的get方法,根据参数的不同可以相应不同的日历日期信息。

     

            这里要注意:MONTH   月 因为西方文化的原因,一年的第一个月是从“0”开始算起的,一年中12个月份分别是:“0-11”,12指的是下一年的一月份。WEEK_OF_YEAR   一年中的第几周  由于西方的一周指的是:星期日-星期六,星期日是一周的第一天,星期六是一周的最后一天,所以,使用 calendar.get(Calendar.WEEK_OF_YEAR) 时应该注意一周的开始应该是哪一天。

        5.其余的部署Tomcat服务器运行就好了~~~

        

        //感叹时光

        最后,感叹时光下,匆匆三年,一晃就过了~~ 所以,人生的档口,努力变优秀吧!

     

     

            

     

     

    展开全文
  • Servlet3教程

    千次阅读 2017-03-17 20:27:55
    1. Servlet介绍Servlet是基于Java技术的web组件,容器托管的,用于生成动态内容。Servlet容器是web server或application server 的一部分,提供基于请求/响应发送模型的网络服务,解码基于 MIME 的请求,并且格式化...
  • NULL 博文链接:https://fanshuyao.iteye.com/blog/1688318
  • servlet3异步原理与实践

    千次阅读 2019-06-12 20:35:22
    一、什么是Servlet servlet 是基于 Java 的 Web 组件,由容器进行管理,来生成动态内容。像其他基于 Java 的组件技术一样,servlet 也是基于平台无关的 Java 类格式,被编译为平台无关的字节码,可以被基于 Java ...
  • servlet3与servlet4区别和实现

    千次阅读 2019-07-08 23:41:55
    一、servlet3 记得servlet3的特性有以下几点: 1、异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将...
  • Servlet 3中引入了一项新的技术可以让Servlet异步处理请求。有人可能会质疑,既然都有多线程了,还需要异步处理请求吗?答案是肯定的,因为如果一个任务处理时间相当长,那么Servlet或Filter会一直占用着请求处理...
  • Servlet 3特性:异步Servlet

    万次阅读 2014-01-28 16:23:58
    Servlet3是Tomcat7出现的新特性,所以需要先安装tomcat7 理解异步Servlet之前,让我们试着理解为什么需要它。假设我们有一个Servlet需要很多的时间来处理,类似下面的内容: LongRunningServlet.java package ...
  • Maven 配置Servlet 3版本

    千次阅读 2017-11-29 16:03:49
    老式配置 <groupId>javax.servlet <artifactId>servlet-api <version>2.2.0 注意artifactId的servlet-api是Servlet3版本之前的 而在3版本之后更改名字了 更改为
  • tomcat servlet3的异步化原理理解

    千次阅读 2017-07-28 10:12:49
    之所以想起来扒这个servlet 3的异化步原理,...所以想搞清楚tomcat是如何实现servlet3的异步化。tomcat如何处理请求从客户端发出一次请求至tomcat容器大致经过如下过程: 客户端发出http请求至tomcat的连接监听端口;
  • IDEA下maven新建servlet3.x/web3.x工程

    千次阅读 2018-07-30 17:29:41
    maven使我们常用的项目管理工具,但是使用maven创建web项目时,默认创建的为servlet2.x的webapp,我们想使用最新的功能更强大,性能更好的servlet3.x的webapp 2.解决方法 1. 手动修改相关配置(web.xml,引入...
  • TOMCAT7关于支持SERVLET3的新特性

    千次阅读 2010-08-11 10:24:00
    Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。其中...
  •  Servlet3.0是Java EE6规范的一部分,Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署描述,简化开发流程。 二、开发Servlet3.0程序的所需要的环境  开发
  • Servlet3的上传配置@MultipartConfig

    千次阅读 2016-01-20 23:17:48
    该注解标注在 Servlet 上面,以表示该 Servlet 希望处理的请求的 MIME 类型是 multipart/form-data。另外,它还提供了若干属性用于简化对上传文件的处理。具体如下: @MultipartConfig 的常用属
  • 1.配置文件 web.xml eduos 实例用的简单过滤器 示例过滤器 CharacterEncode dt.it.filter.CharacterEncode encoding UTF-8 CharacterEncode /* R
  • 1、打开Eclipse4.2,新建一个Maven项目  1)选择maven的archetype为maven-archetype-webapp ... 1)手工添加 src/main/java、src/test/java和src/test/resource 三个source folder,在项
  • Servlet3.0下@WebServlet注解配置Servlet

    万次阅读 多人点赞 2017-04-17 18:31:08
    @WebServlet注解配置Servlet
  • JavaWeb——Servlet         Tomcat工作机制动画演示(点击动图可全屏观看)   什么是Servlet    Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要...
1 2 3 4 5 ... 20
收藏数 858,100
精华内容 343,240
关键字:

servlet3