SpringBoot9-Spring MVC-Spring MVC高级配置

来源:互联网 发布:redis可视化工具 知乎 编辑:程序博客网 时间:2024/05/29 15:43

一:文件上传

      文件上传是一个项目里经常要用的功能,Spring MVC通过配置一个MultipartResolver来上传文件。

      在Spring的控制器中通过MultipartFile file来接收文件,通过MultipartFile[] files接收多个文件上传。

     下面是示例:

1,添加文件上传依赖:

<!--文件上传依赖-->        <dependency>            <groupId>commons-fileupload</groupId>            <artifactId>commons-fileupload</artifactId>            <version>1.3.3</version>        </dependency>        <!--非必须,可简化I/O操作-->        <dependency>            <groupId>commons-io</groupId>            <artifactId>commons-io</artifactId>            <version>2.5</version>        </dependency>

目前完整的pom.xml代码如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.jack</groupId>    <artifactId>springmvc1</artifactId>    <version>1.0-SNAPSHOT</version>    <packaging>war</packaging>    <properties>        <!--基本属性配置-->        <java.version>1.8</java.version>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <!--WEB的属性配置-->        <jsp.version>2.2</jsp.version>        <jstl.version>1.2</jstl.version>        <servlet.version>3.1.0</servlet.version>        <!--spring基本属性的配置-->        <spring-framework.version>4.3.9</spring-framework.version>        <!--Logging日志的基本属性配置-->        <logback.version>1.2.3</logback.version>        <slf4j.version>1.7.25</slf4j.version>    </properties>    <!--依赖配置-->    <dependencies>        <dependency>            <groupId>javax</groupId>            <artifactId>javaee-web-api</artifactId>            <version>7.0</version>            <scope>provided</scope>        </dependency>        <!--spring mvc的依赖-->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>${spring-framework.version}.RELEASE</version>        </dependency>        <!--其他web依赖-->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jstl</artifactId>            <version>${jstl.version}</version>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>javax.servlet-api</artifactId>            <version>${servlet.version}</version>        </dependency>        <dependency>            <groupId>javax.servlet.jsp</groupId>            <artifactId>jsp-api</artifactId>            <version>${jsp.version}</version>            <scope>provided</scope>        </dependency>        <!--spring and transactions-->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-tx</artifactId>            <version>${spring-framework.version}.RELEASE</version>        </dependency>        <!--使用SLF4J和LogBack作为日志-->        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>slf4j-api</artifactId>            <version>${slf4j.version}</version>        </dependency>        <dependency>            <groupId>log4j</groupId>            <artifactId>log4j</artifactId>            <version>1.2.17</version>        </dependency>        <dependency>            <groupId>org.slf4j</groupId>            <artifactId>jcl-over-slf4j</artifactId>            <version>${slf4j.version}</version>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-classic</artifactId>            <version>${logback.version}</version>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-core</artifactId>            <version>${logback.version}</version>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-access</artifactId>            <version>${logback.version}</version>        </dependency>        <!--添加jackson依赖,获得对象和josn或xml之间的转换-->        <dependency>            <groupId>com.fasterxml.jackson.dataformat</groupId>            <artifactId>jackson-dataformat-xml</artifactId>            <version>2.8.9</version>        </dependency>        <!--文件上传依赖-->        <dependency>            <groupId>commons-fileupload</groupId>            <artifactId>commons-fileupload</artifactId>            <version>1.3.3</version>        </dependency>        <!--非必须,可简化I/O操作-->        <dependency>            <groupId>commons-io</groupId>            <artifactId>commons-io</artifactId>            <version>2.5</version>        </dependency>    </dependencies>    <build>        <!--插件-->        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.6.0</version>                <configuration>                    <source>${java.version}</source>                    <target>${java.version}</target>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-war-plugin</artifactId>                <version>3.1.0</version>                <configuration>                    <failOnMissingWebXml>false</failOnMissingWebXml>                </configuration>            </plugin>        </plugins>    </build></project>


2,上传页面

    在src/main/resources/views下新建upload.jsp,页面代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %><html><head>    <meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8" >    <title>upload page</title></head><body><div class="upload">    <form action="upload" enctype="multipart/form-data" method="post">        <input type="file" name="file"/><br/>        <input type="submit" value="上传"/>    </form></div></body></html>


3,添加转向到upload页面的ViewController

/**     * 统一处理没啥业务逻辑处理的controller请求,实现代码的简洁     * @param registry     */    @Override    public void addViewControllers(ViewControllerRegistry registry) {        //super.addViewControllers(registry);        registry.addViewController("/index").setViewName("/index");        registry.addViewController("/toUpload").setViewName("upload");    }


4,MultipartResolver配置

/**     * 配置文件上传Bean     * @return     */    @Bean    public MultipartResolver multipartResolver(){        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();        multipartResolver.setMaxUploadSize(1000000);        return multipartResolver;    }


目前spring mvc配置类的代码如下:

package jack.springmvc.config;import jack.springmvc.interceptor.DemoInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.multipart.MultipartResolver;import org.springframework.web.multipart.commons.CommonsMultipartResolver;import org.springframework.web.servlet.config.annotation.*;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView;/** * Created by jack on 2017/7/16. */@Configuration@EnableWebMvc   //开启Spring MVC支持,若无此句,重写WebMvcConfigurerAdapter方法无效@ComponentScan("jack.springmvc")//继承WebMvcConfigurerAdapter类,重写其方法可对Spring MVC进行配置public class MyMvcConfig extends WebMvcConfigurerAdapter{    /**     * 配置拦截器的Bean     * @return     */    @Bean    public DemoInterceptor demoInterceptor(){        return new DemoInterceptor();    }    /**     * 配置文件上传Bean     * @return     */    @Bean    public MultipartResolver multipartResolver(){        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();        multipartResolver.setMaxUploadSize(1000000);        return multipartResolver;    }    /**     * c重写addInterceptors方法,注册拦截器     * @param registry     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        //super.addInterceptors(registry);        registry.addInterceptor(demoInterceptor());    }    @Bean    public InternalResourceViewResolver viewResolver(){        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        //viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setSuffix(".jsp");        viewResolver.setViewClass(JstlView.class);        return  viewResolver;    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        //super.addResourceHandlers(registry);        //addResourceLocations指的是文件放置的目录,addResourceHandler指的是对外暴露的访问路径        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");    }    /**     * 统一处理没啥业务逻辑处理的controller请求,实现代码的简洁     * @param registry     */    @Override    public void addViewControllers(ViewControllerRegistry registry) {        //super.addViewControllers(registry);        registry.addViewController("/index").setViewName("/index");        registry.addViewController("/toUpload").setViewName("upload");    }    @Override    public void configurePathMatch(PathMatchConfigurer configurer) {        //super.configurePathMatch(configurer);        configurer.setUseSuffixPatternMatch(false);    }}


5,控制器



package jack.springmvc.controller;import org.apache.commons.io.FileUtils;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.multipart.MultipartFile;import java.io.File;/** * Created by jack on 2017/7/25. * 文件上传控制器 */@Controllerpublic class UploadController {    @RequestMapping(value = "/upload",method = RequestMethod.POST)    @ResponseBody    public String upload(MultipartFile file){//使用MultipartFile接受上传的文件        try {            //使用FileUtils.writeByteArrayToFile快速写文件到磁盘            FileUtils.writeByteArrayToFile(new File("F:\\yhcrm/"+file.getOriginalFilename()),file.getBytes());            return "ok";        }catch (Exception e){            e.printStackTrace();            return "wrong";        }    }}


6,运行程序,在浏览器输入:http://localhost:8080/toUpload,如图:



单击上传,可以在指定的目录下看到上传的文件。



二:自定义HttpMessageConverter

      HttpMessageConverter是用来处理request和response里的数据的。Spring为我们内置了大量的HttpMessageConverter,例如,MappingJackson2HttpMessageConverter,StringHttpMessageConvert等。下面演示自定义的HttpMessageConverter,并主持这个HttpMessageConverter到Spring MVC。

       示例:

1,自定义HttpMessageConverter

package jack.springmvc.messageconverter;import jack.springmvc.domain.DemoObj;import org.springframework.http.HttpInputMessage;import org.springframework.http.HttpOutputMessage;import org.springframework.http.MediaType;import org.springframework.http.converter.AbstractHttpMessageConverter;import org.springframework.http.converter.HttpMessageNotReadableException;import org.springframework.http.converter.HttpMessageNotWritableException;import org.springframework.util.StreamUtils;import java.io.IOException;import java.nio.charset.Charset;/** * Created by jack on 2017/7/25. *///继承AbstractHttpMessageConverter实现自定义接口public class MyMessageConverter extends AbstractHttpMessageConverter<DemoObj>{    public MyMessageConverter() {        //新建一个我们自定义的媒体类型application/x-wisely        super(new MediaType("application", "x-wisely", Charset.forName("UTF-8")));    }    /**     * 表明本HttpMessageConverter只处理DemoObj这个类     * @param aClass     * @return     */    @Override    protected boolean supports(Class<?> aClass) {        return DemoObj.class.isAssignableFrom(aClass);    }    /**     * 重写readInternal方法,处理请求的数据,代码表明处理由"-"隔开的数据,并转成DemoObj的对象     * @param aClass     * @param httpInputMessage     * @return     * @throws IOException     * @throws HttpMessageNotReadableException     */    @Override    protected DemoObj readInternal(Class<? extends DemoObj> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {        String temp = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("UTF-8"));        String[] tempArr = temp.split("-");        return new DemoObj(new Long(tempArr[0]),tempArr[1]);    }    /**     * 重写writeInternal,处理如何输出数据到response,代码中在原样输出前面加上hello:     * @param obj     * @param httpOutputMessage     * @throws IOException     * @throws HttpMessageNotWritableException     */    @Override    protected void writeInternal(DemoObj obj, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {        String out = "hello :" + obj.getId() + "-" + obj.getName();        httpOutputMessage.getBody().write(out.getBytes());    }}


2,配置。在addViewControllers中添加ViewController映射页面访问演示页面,代码如下:

registry.addViewController("/converter").setViewName("/converter");


addViewControllers方法中目前所有的代码如下:

/**     * 统一处理没啥业务逻辑处理的controller请求,实现代码的简洁     * @param registry     */    @Override    public void addViewControllers(ViewControllerRegistry registry) {        //super.addViewControllers(registry);        registry.addViewController("/index").setViewName("/index");        registry.addViewController("/toUpload").setViewName("upload");        registry.addViewController("/converter").setViewName("/converter");    }


    重写extendMessageConverters方法:

@Override    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {        //super.extendMessageConverters(converters);        converters.add(converter());    }    @Bean    public MyMessageConverter converter(){        return new MyMessageConverter();    }


spring mvc目前所有的配置如下:

package jack.springmvc.config;import jack.springmvc.interceptor.DemoInterceptor;import jack.springmvc.messageconverter.MyMessageConverter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.web.multipart.MultipartResolver;import org.springframework.web.multipart.commons.CommonsMultipartResolver;import org.springframework.web.servlet.config.annotation.*;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView;import java.util.List;/** * Created by jack on 2017/7/16. */@Configuration@EnableWebMvc   //开启Spring MVC支持,若无此句,重写WebMvcConfigurerAdapter方法无效@ComponentScan("jack.springmvc")//继承WebMvcConfigurerAdapter类,重写其方法可对Spring MVC进行配置public class MyMvcConfig extends WebMvcConfigurerAdapter{    /**     * 配置拦截器的Bean     * @return     */    @Bean    public DemoInterceptor demoInterceptor(){        return new DemoInterceptor();    }    /**     * 配置文件上传Bean     * @return     */    @Bean    public MultipartResolver multipartResolver(){        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();        multipartResolver.setMaxUploadSize(1000000);        return multipartResolver;    }    /**     * c重写addInterceptors方法,注册拦截器     * @param registry     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        //super.addInterceptors(registry);        registry.addInterceptor(demoInterceptor());    }    @Bean    public InternalResourceViewResolver viewResolver(){        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        //viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setSuffix(".jsp");        viewResolver.setViewClass(JstlView.class);        return  viewResolver;    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        //super.addResourceHandlers(registry);        //addResourceLocations指的是文件放置的目录,addResourceHandler指的是对外暴露的访问路径        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");    }    /**     * 统一处理没啥业务逻辑处理的controller请求,实现代码的简洁     * @param registry     */    @Override    public void addViewControllers(ViewControllerRegistry registry) {        //super.addViewControllers(registry);        registry.addViewController("/index").setViewName("/index");        registry.addViewController("/toUpload").setViewName("upload");        registry.addViewController("/converter").setViewName("/converter");    }    @Override    public void configurePathMatch(PathMatchConfigurer configurer) {        //super.configurePathMatch(configurer);        configurer.setUseSuffixPatternMatch(false);    }    /**     * 配置自定义的HttpMessageConverter的bean,在spring mvc里注册HttpMessageConverter有两个方法:     * configureMessageConverters:重载会覆盖掉Spring MVC默认注册的多个HttpMessageConverter     * extendMessageConverters:仅添加一个自定义的HttpMessageConverter,不覆盖默认注册的HttpMessageConverter     * @param converters     */    @Override    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {        //super.extendMessageConverters(converters);        converters.add(converter());    }    @Bean    public MyMessageConverter converter(){        return new MyMessageConverter();    }}


3,编写控制器:

package jack.springmvc.controller;import jack.springmvc.domain.DemoObj;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;/** * Created by jack on 2017/7/26. */@Controllerpublic class ConverterController {    //指定返回的媒体类型为我们自定义的媒体类型application/x-wisely    @RequestMapping(value = "/convert",produces = {"application/x-wisely"})    @ResponseBody    public DemoObj convert(@RequestBody DemoObj demoObj){        return demoObj;    }}



4,演示页面。在src/main/resources下新建converter.jsp,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %><html><head>    <meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8" >    <title>HttpMessageConverter Demo</title>    <script src="../assets/js/jquery-3.2.1.js"></script></head><body><div id="resp"></div><input type="button" onclick="req();" value="请求"/><script>    function req() {        $.ajax({            url: "convert",            data: "1-jack",//主要这里的数据格式,后台处理按此格式处理,用"-"隔开            type: "POST",            contentType:"application/x-wisely",//contentType设置的媒体类型是我们自定义的application/w-wisely            success: function (data) {                $("#resp").html(data);            }        });    }</script></body></html>



5,运行

        在浏览器输入:http://localhost:8080/converter,如下图:




点击请求按钮,做如下规则:




页面效果如下:




三:服务器端推送技术

       服务端推送技术在日常开发中较为常用,早期很多人采用ajax向服务器轮询消息,使浏览器尽可能第一时间获得服务端的消息,因为这种方式的轮询频率不好控制,所以大大增加了服务端的压力。

      下面的服务器端推送方案都是基于:当客户端向服务端发送请求,服务端会抓住这个请求不放,等有数据更新的时候才返回给客户端,当客户端接收到消息后,在向服务端发送请求,周而复使。这种方式的好处是减少了服务端的请求数量,大大减少了服务器的压力。

       除了服务器推送技术以外,还有另外一个双向通信的技术一WebSocket。

       下面基于SSE(Server Send Event服务端发送事件)的服务器端推送和基于Servlet3.0+的异步方法特性,其中第一种方式需要新式浏览器的支持,第二种是跨浏览器的。

     1,SSE

   1)演示控制器

package jack.springmvc.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import java.util.Random;/** * Created by jack on 2017/7/26. */@Controllerpublic class SseController {    /**     * 这里使用输出媒体类型为text/event-stream,这是服务器端SSE的支持     * @return     */    @RequestMapping(value = "/push",produces="text/event-stream;charset=UTF-8")    public @ResponseBody String push(){        Random r = new Random();        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        return "data:Testing 1,2,3->"+r.nextInt()+"\n\n";    }}



2)演示页面,在src/main/resources/views下新建sse.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <title>SSE Demo</title></head><body><div id="msgFromPush"></div><script type="text/javascript"        src="<c:url value="../assets/js/jquery-3.2.1.js" />"></script><script type="text/javascript">    if (!!window.EventSource) { //EventSource是SSE的客户端.此时说明浏览器支持EventSource对象        var source = new EventSource('push');//发送消息        s = '';        source.addEventListener('message', function(e) {            s += e.data + "<br/>";            $("#msgFromPush").html(s);        });//添加客户端的监听        source.addEventListener('open', function(e) {            console.log("连接打开");        }, false);        source.addEventListener('error',function(e){            if(e.readyState==EventSource.CLOSED){                console.log("连接关闭");            }else{                console.log(e.readyState);            }        });    }else{        console.log("您的浏览器不支持SSE");    }</script></body></html>


3)配置

添加转向sse.jsp页面的映射:

registry.addViewController("/sse").setViewName("/sse");

4)运行

      在浏览器输入:http://localhost:8080/sse,如下图所示:





2,Servlet3.0+异步方法处理


1),开启异步方法支持:

package jack.springmvc.config;import org.springframework.web.WebApplicationInitializer;import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import org.springframework.web.servlet.DispatcherServlet;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRegistration;/** * Created by jack on 2017/7/16. * web配置 *//*WebApplicationInitializer是spring提供用来配置Servlet3.0+配置的接口,从而实现了替代web.xml的位置。实现此接口将会自动被SpringServletContainerInitializer(用来启动Servlet3.0容器)获取到 */public class WebInitializer implements WebApplicationInitializer{    public void onStartup(ServletContext servletContext) throws ServletException {        //新建WebApplicaitonContext,注册配置类,并将其和当前的servletContext关联        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();        ctx.register(MyMvcConfig.class);        ctx.setServletContext(servletContext);        //注册Spring MVC的DispatcherServlet        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher",new DispatcherServlet(ctx));        servlet.addMapping("/");        servlet.setLoadOnStartup(1);        servlet.setAsyncSupported(true);//开启异步方法支持    }}

2)演示控制器

package jack.springmvc.controller;import jack.springmvc.service.PushService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.context.request.async.DeferredResult;/** * Created by jack on 2017/7/27. */@Controllerpublic class AsyncController {    /**     * 异步任务的实现是通过控制器从另外一个线程返回一个DeferredResult,这里的DeferredResult     * 是从pushService中获得的     */    @Autowired    PushService pushService;    @RequestMapping(value = "/defer")    @ResponseBody    public DeferredResult<String> deferredCall(){        //返回给客户端的DeferredResult        return pushService.getAsyncUpdate();    }}


3)定时任务

package jack.springmvc.service;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Service;import org.springframework.web.context.request.async.DeferredResult;/** * Created by jack on 2017/7/27. */@Servicepublic class PushService {    //PushService里产生DeferredResult给控制器使用    private DeferredResult<String> deferredResult;    public DeferredResult<String> getAsyncUpdate(){        deferredResult = new DeferredResult<String>();        return deferredResult;    }    //通过@Scheduled注解定时更新DeferredResult    @Scheduled(fixedDelay = 5000)    public void refresh(){        if (deferredResult != null) {            deferredResult.setResult(new Long(System.currentTimeMillis()).toString());        }    }}


4)演示页面

  在src/main/resources/views下新建async.jsp,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <title>servlet async support</title></head><body><div id="msgFromPush"></div><script type="text/javascript"        src="<c:url value="../assets/js/jquery-3.2.1.js" />"></script><script type="text/javascript">    deferred();//页面打开就向后台发送请求    function deferred() {        $.get('defer',function (data) {            console.log(data);//在浏览器控制台输出服务端推送的数据            deferred();//一次请求完成以后在向后台发送请求        });    }</script></body></html>


5)配置

    在MyMvcConfig上开始计划任务的支持,使用@EnableScheduling:

package jack.springmvc.config;import jack.springmvc.interceptor.DemoInterceptor;import jack.springmvc.messageconverter.MyMessageConverter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.web.multipart.MultipartResolver;import org.springframework.web.multipart.commons.CommonsMultipartResolver;import org.springframework.web.servlet.config.annotation.*;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView;import java.util.List;/** * Created by jack on 2017/7/16. */@Configuration@EnableWebMvc   //开启Spring MVC支持,若无此句,重写WebMvcConfigurerAdapter方法无效@ComponentScan("jack.springmvc")@EnableScheduling   //开启计划任务的支持//继承WebMvcConfigurerAdapter类,重写其方法可对Spring MVC进行配置public class MyMvcConfig extends WebMvcConfigurerAdapter{    /**     * 配置拦截器的Bean     * @return     */    @Bean    public DemoInterceptor demoInterceptor(){        return new DemoInterceptor();    }    /**     * 配置文件上传Bean     * @return     */    @Bean    public MultipartResolver multipartResolver(){        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();        multipartResolver.setMaxUploadSize(1000000);        return multipartResolver;    }    /**     * c重写addInterceptors方法,注册拦截器     * @param registry     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        //super.addInterceptors(registry);        registry.addInterceptor(demoInterceptor());    }    @Bean    public InternalResourceViewResolver viewResolver(){        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        //viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setPrefix("/WEB-INF/classes/views/");        viewResolver.setSuffix(".jsp");        viewResolver.setViewClass(JstlView.class);        return  viewResolver;    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        //super.addResourceHandlers(registry);        //addResourceLocations指的是文件放置的目录,addResourceHandler指的是对外暴露的访问路径        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");    }    /**     * 统一处理没啥业务逻辑处理的controller请求,实现代码的简洁     * @param registry     */    @Override    public void addViewControllers(ViewControllerRegistry registry) {        //super.addViewControllers(registry);        registry.addViewController("/index").setViewName("/index");        registry.addViewController("/toUpload").setViewName("upload");        registry.addViewController("/converter").setViewName("/converter");        registry.addViewController("/sse").setViewName("/sse");        registry.addViewController("/async").setViewName("/async");    }    @Override    public void configurePathMatch(PathMatchConfigurer configurer) {        //super.configurePathMatch(configurer);        configurer.setUseSuffixPatternMatch(false);    }    /**     * 配置自定义的HttpMessageConverter的bean,在spring mvc里注册HttpMessageConverter有两个方法:     * configureMessageConverters:重载会覆盖掉Spring MVC默认注册的多个HttpMessageConverter     * extendMessageConverters:仅添加一个自定义的HttpMessageConverter,不覆盖默认注册的HttpMessageConverter     * @param converters     */    @Override    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {        //super.extendMessageConverters(converters);        converters.add(converter());    }    @Bean    public MyMessageConverter converter(){        return new MyMessageConverter();    }}

     上面了添加viewController:

registry.addViewController("/async").setViewName("/async");


6)运行

在浏览器输入:http://localhost:8080/async,打开f12查看,如下图所示: