目录

一、常规MVC配置

1.1 注册视图映射

1.2 注册拦截器

1.3 注册静态资源映射

1.4 注册对象格式器

1.5  注册对象转换器

1.6 实现自定义HttpMessageConvert

二、注册Servlet、Filter、Listener

2.1 Servlet

2.2 Filter

2.3 Listener

三、全局通知

四、模板支持

4.1 环境搭建

4.2 常用标签和函数

4.3 实际使用

五、文件上传和下载

5.1 文件上传

5.2 文件下载


一、常规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、采用远程文件服务器

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐