Spring Boot 探索之旅(五)——Web支持
目录一、常规MVC配置1.1 注册视图映射1.2 注册拦截器1.3 注册静态资源映射1.4 注册对象格式器1.5 注册对象转换器1.6 实现自定义HttpMessageConvert二、注册Servlet、Filter、Listener2.1 Servlet2.2 Filter2.3 Listener三、全局通知四、模板支持4.1 环境搭建...
目录
一、常规MVC配置
/**
* 主要WebMvc配置
* @author sunyiran
* @date 2018-09-29
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 注册自定义拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
/**
* 注册视图映射
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
}
/**
* 注册资源映射
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
/**
*注册类型格式
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
}
/**
* 配置转化器
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
/**
* 配置异常处理器
* @param exceptionResolvers
*/
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
}
/**
* 配置跨域请求
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
}
}
1.1 注册视图映射
目标:输入localhost:8082时,访问非默认首页first.html
第一步、编写视图映射注册器(ViewController访问相对路径,ViewName视图名称)
/**
* 注册视图映射
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
/*访问相对路径为/时,映射至first,结合模版前后缀,跳转值/templates/first.html*/
registry.addViewController("/").setViewName("first");
}
第二步、运行项目测试
1.2 注册拦截器
目标:访问healthy方法是,返回“Bad”(正常为OK)
第一步、编写拦截器HealthyIntercepor
/**
* @author sunyiran
* @date 2018-09-29
*/
public class HealthyInterceptor implements HandlerInterceptor {
/**
* 调用前拦截
* @param request
* @param response
* @param handler
* @return false:直接返回,不进入目标方法
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setHeader("Content-Type","text/html");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("<html><body>Bad</body></html>".getBytes());
outputStream.close();
return false;
}
/**
* 调用后拦截
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
}
第二步、注册拦截器
/**
* 注册自定义拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册healthy拦截器,匹配路径为正则表达
registry.addInterceptor(new HealthyInterceptor()).addPathPatterns("/healthy");
}
第三步、运行测试
1.3 注册静态资源映射
目标:输入localhost:8082/file/test.jpg 能访问到file目录中的test.jpg
第一步、注册资源映射
/**
* 注册资源映射
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/file/**").addResourceLocations("classpath:/file/");
}
第二步、运行测试
1.4 注册对象格式器
目标:传入yyyy/MM-dd HH:ss:mm格式的字符串能自动解析为日期对象
第一步、编写格式器(实现对象文本与对象实体的相互转换)
/**
* @author sunyiran
* @date 2018-09-29
*/
public class DateFormatter implements Formatter<Date> {
private SimpleDateFormat format = new SimpleDateFormat("yyyy/MM-dd HH:ss:mm");
@Override
public Date parse(String s, Locale locale) throws ParseException {
return format.parse(s);
}
@Override
public String print(Date date, Locale locale) {
return format.format(date);
}
}
第二步、注册格式器
/**
*注册类型格式
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter());
}
第三步、运行测试
1.5 注册对象转换器
目标:传入yyyy/MM-dd HH:ss:mm格式的字符串能自动解析为日期对象
第一步、编写格式转换器
/**
* @author sunyiran
* @date 2018-09-29
*/
public class DateConvert implements Converter<String ,Date> {
private SimpleDateFormat format = new SimpleDateFormat("yyyy/MM-dd HH:ss:mm");
@Override
public Date convert(String source) {
try {
return format.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
第二步、注册转化器
/**
*注册类型格式转换
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
//registry.addFormatter(new DateFormatter());
registry.addConverter(new DateConvert());
}
第三步、运行测试
********formatter和convert都可以直接用@component纳入容器,自动注册
1.6 实现自定义HttpMessageConvert
package com.litb.business.tms.config;
import java.io.IOException;
import com.litb.core.EmptyParam;
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.stereotype.Component;
/**
* @author sunyiran
*/
@Component
public class EmptyConverter extends AbstractHttpMessageConverter<EmptyParam> {
public EmptyConverter() {
super(MediaType.APPLICATION_JSON);
}
/**
* 重写readInternal方法,处理请求的数据
*/
@Override
protected EmptyParam readInternal(Class<? extends EmptyParam> clazz, HttpInputMessage inputMessage) throws
HttpMessageNotReadableException {
return new EmptyParam();
}
/**
* 表明HttpMessageConvert只处理EmptyParam这个类
*/
@Override
protected boolean supports(Class<?> clazz) {
return EmptyParam.class.isAssignableFrom(clazz);
}
/**
* 重写writeInternal,处理如何输出数据到response。
*/
@Override
protected void writeInternal(EmptyParam obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
outputMessage.getBody().write("{}".getBytes());
}
}
二、注册Servlet、Filter、Listener
必要条件:在项目主类上添加@ServletComponentScan开启对@WebFilter等注解扫描
2.1 Servlet
目标:输入localhost:8082/ts ,输出this is a servlet
第一步、编写servlet
/**
* @author sunyiran
* @date 2018-09-29
*/
@WebServlet(urlPatterns = "/ts")
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.getOutputStream().write("this is a servlet".getBytes());
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
第二步、运行测试
2.2 Filter
目标:访问localhost:8082/test ,打印 healthyFilter执行
第一步、编写filter
/**
* @author sunyiran
* @date 2018-09-29
*/
@WebFilter(urlPatterns = "/test")
public class HealthFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("healthyFilter执行");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
第二步、运行测试
2.3 Listener
目标:访问任意资源,打印监听开始
第一步、编写监听器
/**
* @author sunyiran
* @date 2018-09-29
*/
@WebListener
public class MyListner implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("监听开始");
}
}
第二步、运行测试
三、全局通知
@ControllerAdvice:标识为通知类
@InitBinder:定制参数处理器
@ExceptionHander:异常处理
@ModelAttribute:添加键值对参数
目标:1、通过InitBinder正确转化yyyy/MM-dd HH:ss:mm格式的日期对象
2、通过ExceptionHander向页面返回错误信息
3、通过ModelAttribute添加全局参数t
第一步、编写全局通知类
/**
* @author sunyiran
* @date 2018-09-30
*/
@RestControllerAdvice
public class WebAdvice {
/**
* 对参数参数初始化处理
* @param webDataBinder 数据处理器
*/
@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
//转换日期
DateFormat dateFormat=new SimpleDateFormat("yyyy/MM-dd HH:ss:mm");
// CustomDateEditor为自定义日期编辑器
webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
/**
* 异常处理(value指定要处理的异常对象)
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
public String exceptionHander(Exception e){
return e.getMessage();
}
/**
* 添加键值对参数
* @param model
*/
@ModelAttribute
public void modelAttri(Model model) {
model.addAttribute("t","存在");
}
}
第二步、运行测试
四、模板支持
4.1 环境搭建
引入maven依赖:
<!--默认配置:前缀(/templates),后缀(.html),字符集(UTF-8)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
添加页面标签支持:
<html xmlns:th="http://www.thymeleaf.org">
4.2 常用标签和函数
${}:动态解析值;@{}:动态引入链接内容
th:text,显示文本内容;th:utext,显示保留文本内容
th:attr,设置标签属性;th:if 和th:unless:条件判断
th:switch,th:case,选择语句;th:each循环语句
#data,日期处理;#calendars:日历处理
#numbers,数字处理;#strings,字符串处理
#objects,对象处理;#bools,逻辑处理
#arrays,数组处理;#lists,列表处理
4.3 实际使用
第一步、编写测试用java代码
@RequestMapping("/test1")
public String test1(Model model) throws Exception {
model.addAttribute("today",new Date());
model.addAttribute("ts","我的模板");
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
model.addAttribute("list",list);
String[] str = {"a","b","c","d"};
model.addAttribute("arr",str);
return "first";
}
第二步、编写测试用html
<!--
* @author sunyiran
* @date 2018-09-29
* @purpose
*-->
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<hr>
<div th:text="${ts}"></div>
<img th:src="@{test.jpg}" width="100px" height="100px">
<div th:text="${today} ? ${#dates.format(today,'yyyy-MM-dd HH:ss:mm')} : ''"></div>
<div th:each="i : ${list}">
<span th:text="${i}"></span>
</div>
<div th:if="${#arrays.contains(arr,'d')}">
存在d
</div>
</body>
</html>
第二步、运行测试
五、文件上传和下载
5.1 文件上传
目标:上传大小超过1M的名为test.jpg的图片至file目录下
第一步、修改默认文件上传最大限制
spring.servlet.multipart.max-file-size=10MB
第二步、编写文件上传代码
@RequestMapping("/upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
//防止空传
if (file == null) {
return null;
}
//获取文件存储路径目录
String rootFilePath = this.getClass().getResource("/file").getPath() + "/";
//获取文件名,用uuid做前缀,防止相同文件名覆盖
String fileName = UUID.randomUUID().toString() + "-" + file.getOriginalFilename();
//jar运行时无法正确获取路径
file.transferTo(new File(rootFilePath+ fileName));
//返回新的文件名
return fileName;
}
第三步、运行测试(postman模拟文件上传)
5.2 文件下载
目标:下载刚才上传成功的图片
第一步、编写下载代码
@RequestMapping("/download/{fileName}")
@ResponseBody
public ResponseEntity<byte[]> download(@PathVariable String fileName) throws IOException {
//获取文件二进制
File file = ResourceUtils.getFile("classpath:file/" + fileName);
byte[] bytes = StreamUtils.copyToByteArray(new FileInputStream(file));
//获取文件名
String[] split = fileName.split("-");
String realName = split[split.length - 1];
//设置响应头信息
HttpHeaders headers = new HttpHeaders();
headers.setContentDispositionFormData("attachment", realName);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
}
第二步、运行测试
如何解决jar运行时存储路径无法获取的问题?
1、指定文件存储目录在项目外部
2、采用远程文件服务器
更多推荐
所有评论(0)