4.5.1文件上传配置
文件上传是一个项目里经常要用的功能,Spring MVC通过配置一个MultipartResolver来上传文件。
在Spring的控制器中,通过MultipartFile file 来接收文件,通过MultipartFile[] files 接收多个文件上传。
示例
(1)添加文件上传依赖。
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.3
(2)上传页面。在 src/main/resources/views下载新建 upload.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
upload page
(3)添加转向到upload页面的ViewController。
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// TODO Auto-generated method stub
registry.addViewController("/index").setViewName("/index");
registry.addViewController("/toUpload").setViewName("/upload");
}
(4)MultipartResolver配置。
@Bean
public MultipartResolver multipartResolver(){
CommonsMultipartResolver multipartResolver =
new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
(5)控制器。
package com.wisely.highlight_springmvc4.web.ch4_5;
import java.io.File;
import java.io.IOException;
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;
@Controller
public class UploadController {
@RequestMapping(value ="/upload",method=RequestMethod.POST)
public @ResponseBody String upload(MultipartFile file){ //使用MultipartFile接受上传的文件
try {
FileUtils.writeByteArrayToFile(new File("d:/upload/"+file.getOriginalFilename()),
file.getBytes()); //使用FileUtils.writeByteArrayToFile快速写文件到磁盘。
return "ok";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "wrong";
}
}
}
(6)运行。访问http:localhost:8080/highlight_springmvc4/toUpload,如图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190116104431304.png
单击“上传”按钮后,查看d:\upload文件夹,如图
4.5.2 自定义HttpMessageConverter
HttpMessageConverter是用来处理request和response里的数据的。Spring为我们内置大量的HtpMessageConverter,例如,MappingJackson2HttpMessageConverter、StringHttpMessageConverter等。本节将演示自定义的HttpMessageConverter,并注册这个HttpMessageConverter到Spring MVC。
示例
(1)自定义HttpMessageConverter。
package com.wisely.highlight_springmvc4.messageconverter;
import java.io.IOException;
import java.nio.charset.Charset;
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 com.wisely.highlight_springmvc4.domain.DemoObj;
public class MyMessageConverter extends AbstractHttpMessageConverter {//继承AbstractHttpMessageConverter接口来实现自定义的HttpMessageConverter。
public MyMessageConverter(){
super(new MediaType("application","x-wisely",Charset.forName("UTF-8"))); //新建一个我们自定义的媒体类型application/x-wisely
}
/**
* 表明本HttpMessageConverter只处理DemoObj这个类。
*/
@Override
protected boolean supports(Class> clazz) {
return DemoObj.class.isAssignableFrom(clazz);
}
/**
* 重写readInternal方法,处理请求的数据。代码表明我们处理由“-”隔开的数据,并转成DemoObj的对象。
*/
@Override
protected DemoObj readInternal(Class extends DemoObj> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
String temp = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
String[] tempArr = temp.split("-");
return new DemoObj(new Long(tempArr[0]),tempArr[1]);
}
/**
* 重写writeInterNal,处理如何输出数据到response。此例中,我们在原样输出前面加上“hello:”。
*/
@Override
protected void writeInternal(DemoObj obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
String out = "hello:" +obj.getId() + "-" +obj.getName();
outputMessage.getBody().write(out.getBytes());
}
}
(2)配置。在addViewControllers中添加viewController映射页面访问演示页面,代码如下:
registry.addViewController("/converter").setViewName("/converter");
配置自定义的HttpMessageConverter的Bean,在Spring MVC里注册HttpMessageConverter有两个方法:
所以在此例中我们重写extendMessageConverters:
@Override
public void extendMessageConverters(List> converters) {
converters.add(converter());
}
@Bean
public MyMessageConverter converter(){
return new MyMessageConverter();
}
(3)演示控制器。
package com.wisely.highlight_springmvc4.web.ch4_5;
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;
import com.wisely.highlight_springmvc4.domain.DemoObj;
@Controller
public class ConverterController {
@RequestMapping(value = "/convert" , produces = { "application/x-wisely" }) //指定返回的媒体类型为我们自定义的媒体类型application/x-wisely。
public @ResponseBody DemoObj convert(@RequestBody DemoObj demoObj){
return demoObj;
}
}
(4)演示页面。 在src/main/resources下新建 conventer.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
upload page
(5)运行。访问http://localhost:8080/highlight_springmvc4/converter
单击“请求”按钮,做如下观察。
请求类型如图
后台获得我们自定义的数据格式,如图
页面效果如图
4.5.3服务器端推送技术
服务器端推送技术在我们日常开发中较为常用,可能早期很多人的解决方案是使用Ajax向服务器轮询消息,使浏览器尽可能第一时间获得服务端的消息,因为这种方式的轮询频率不好控制,所以大增加了服务端的压力。
本节的服务器端推送方案都是基于:当客户端向服务端发送请求,服务端会抓住这个请求不放,等有数据更新是时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求,周而复始。这种方式的好处是减少了服务器的请求数量,大大减少了服务器的压力。
除了服务器端推送技术以外,还有一个另外的双向通信的技术–WebSocket,我们将在后面章节。
本节将提供基于SSE(Server Send Event 服务端发送事件)的服务器端推送和基于Servlet3.0+的异步方法特性,其中第一种方式需要新式浏览器的支持,第二种方式是跨浏览器的。
1.SSE
(1)演示控制器。
package com.wisely.highlight_springmvc4.web.ch4_5;
import java.util.Random;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SseController {
@RequestMapping(value = "/push" , produces="text/event-stream") //注意,这里使用输出的媒体类型为 text/event-stream,这是服务器端SSE的支持,本例演示每5秒钟向浏览器推送随机消息。
public @ResponseBody String push(){
Random r = new Random();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "data:Testing 1,2,3"+r.nextInt() +"\n\n";
}
}
(2)演示页面。在 src/main/resources/views下新建 sse.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
SEE Demo
">
添加转向sse.jsp页面的映射:
registry.addViewController("/see").setViewName("/see");
(4)运行。访问http://localhost:8080/highlight_springmvc4/see,如图
2.Servlet 3.0+异步方法处理
(1)开启异步方法支持:
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));//注册Spring MVC的DispatcherServlet
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
servlet.setAsyncSupported(true); //此句开启异步方法支持。
(2)演示控制器。
package com.wisely.highlight_springmvc4.web.ch4_5;
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;
import com.wisely.highlight_springmvc4.service.PushService;
@Controller
public class AysncController {
@Autowired
PushService pushService;
@RequestMapping("/defer")
@ResponseBody
public DeferredResult deferredCall(){ //返回给客户端DeferredResult
return pushService.getAsyncUpdate();
}
}
(3)定时任务:
package com.wisely.highlight_springmvc4.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
@Service
public class PushService {
private DeferredResult deferredResult; //在PushService里产生DeferredResult给控制器使用,通过@Scheduled注解的方法定时更新DeferredReslt。
public DeferredResult getAsyncUpdate(){
deferredResult = new DeferredResult();
return deferredResult;
}
@Scheduled(fixedDelay = 5000)
public void refresh(){
if(deferredResult != null){
deferredResult.setResult(new Long(System.currentTimeMillis()).toString());
}
}
}
(4)演示页面
在 src/main/views下新建 async.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
servlet async support
(5)配置。
在MyMvcConfig上开始计划任务的支持,使用@EnableScheduling:
@Configuration
@EnableWebMvc //开启SpringMVC支持,若无此名,重写WebMvcConfigurerAdapter方法无效。
@EnableScheduling
@ComponentScan("com.wisely.highlight_springmvc4")
添加viewController:
registry.addViewController("/async").setViewName("/async");
(6)运行。访问http://localhost:8080/highlight_springmvc4/async,如图
控制台输出如图