Spring Boot 探索之旅(五)——Web支持

 

目录

 

一、常规MVC配置

1.1 注册视图映射

1.2 注册拦截器

1.3 注册静态资源映射

1.4 注册对象格式器

1.5  注册对象转换器

二、注册Servlet、Filter、Listener

2.1 Servlet

扫描二维码关注公众号,回复: 3433568 查看本文章

2.2 Filter

2.3 Listener

三、全局通知

四、模板支持

4.1 环境搭建

4.2 常用标签和函数

4.3 实际使用

五、文件上传和下载


一、常规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纳入容器,自动注册

二、注册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、采用远程文件服务器

猜你喜欢

转载自blog.csdn.net/qq_35813653/article/details/82897779
今日推荐