一:文件上传
文件上传是一个项目里经常要用的功能,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.
* 文件上传控制器
*/
@Controller
public 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.
*/
@Controller
public 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" οnclick="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.
*/
@Controller
public 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.
*/
@Controller
public 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.
*/
@Service
public 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查看,如下图所示: