SpringBoot(五)-SringMVC

项目初始化

  1. 打开spring-boot-starter-web依赖,可以看到依赖的jar包有spring-webmvc,默认情况下,SpringBoot已经内置了很多SpringMVC的常用配置
  2. 在22_parent下新建Module项目为07_mvc
    1. 创建入口程序Application、创建TestController类com.zh.controller.TestController
     //com.zh.controller.TestController
     @RestController
     public class TestController {
         @Autowired
         private ProjectProperties properties;
        
         @GetMapping("/test")
         public String test(Date birthday) {
             return "哈哈哈哈 - " + birthday;
         }
     }
    

SringMVC的配置

  1. 默认情况下,SpringBoot已经内置了很多SpringMVC的常用配置(WebMvcConfigurer接口可以查看)
    1. 如果希望在此基础上,继续增加一些配置,可以新建类SpringMvcConfig,实现WebMvcConfigurer接口,该接口中包含了springVC很多配置
    2. 如果希望完全自定义SpringMVC的配置,那就使用@EnableWebMvc
     //com.zh.cfg.SpringMvcConfig
     @Configuration
     //@EnableWebMvc
     public class SpringMvcConfig implements WebMvcConfigurer {
         //实现WebMvcConfigurer的接口
     }
    
  2. 在application.yml配置文件的配置
    1. 具体配置那些内容,可以参考,maven依赖包目录spring-boot-autoconfigure.jar中的WebMvcProperties类
      1. 在jar包下打开spring.factories->搜索WebMvcAutoConfiguration->搜索WebMvcProperties,进入即可
    2. 在resources下新建application.yml
     spring:
       mvc:
         servlet:
           # servlet的创建时间
           load-on-startup: 0
         #日期格式转换
         format:
           date: yyyy-MM-dd
    

文件上传

  1. resources下新建templates文件夹,在下面新建index.xml

     //核心代码
     <form action="/upload" method="post" enctype="multipart/form-data">
         <input type="text" name="username">
         <input type="file" name="photo">
         <button type="submit">上传</button>
     </form>
    
  2. 07_mvc的pom.xml添加依赖

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
     </dependency>
      <!--第三方库,获取文件扩展名 -->
     <dependency>
         <groupId>commons-io</groupId>
         <artifactId>commons-io</artifactId>
         <version>2.7</version>
     </dependency>
    
  3. application.xml中配置上传文件的大小限制、文件上传的具体路径

     # 配置上传文件的大小
       servlet:
         multipart:
           max-file-size: 10MB
           max-request-size: 10MB
     # 指定好文件上传的具体路径
     project:
       upload:
         base-path: F:/upload/
         image-path: img/
         video-path: video/
    
  4. 封装读取application.xml中设置的数据类ProjectProperties

     //对应这application.xml中的project字段
     @ConfigurationProperties("project")
     @Component
     @Data
     public class ProjectProperties {
         //对应upload字段
         private Upload upload;
        
         //内部类
         @Data
         public static class Upload {
             //对应upload类
             private String basePath;
             private String imagePath;
             private String videoPath;
        
             public String getImageFullpath() {
                 return basePath + imagePath;
             }
        
             public String getVideoFullpath() {
                 return basePath + videoPath;
             }
         }
     }
    
    1. 注意: 这个功能是父类里面的这个第三方依赖包实现的

        <!-- 配置文件属性名提示 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-configuration-processor</artifactId>
       </dependency>
      
  5. TestController新增upload方法

     @PostMapping("/upload")
     public String upload(String username, MultipartFile photo, HttpServletRequest request) throws Exception {
         System.out.println(username);
         System.out.println(photo);
    
         // 使用第三方库commons-io,获取文件扩展名
         String extension = FilenameUtils.getExtension(photo.getOriginalFilename());
    
         // 目标文件
         //获取文件目录
         String dir = properties.getUpload().getImageFullpath();
         //文件名
         String filename = UUID.randomUUID() + "." + extension;
         File file = new File(dir + filename);
    
         // springboot如果文件路径不存在,默认不会创建,因此使用第三方commons-io,创建好目标文件所在的父目录
         FileUtils.forceMkdirParent(file);
    
         // 将文件数据写到目标文件
         photo.transferTo(file);
    
         return "上传成功!!!";
     }
    

资源映射(重点!!!!,理解)

  1. 在学习javaEE时上传文件直接在contextpath下建一个文件路径存储即可,原因是之前打包的项目都是war包,然后直接放到Tomcat的webapps文件夹下,路径固定可以直接访问

     //之前JavaEE获取项目的根路径通过这个方法
     request.getServletContext().getRealPath();
     //如果springboot项目仍然使用这个,会发现获取的是临时路径
    
  2. 而且war项目部署的方式是直接本地解压war包,然后上传的所有文件会放到war包的某个目录下,所以可以直接访问。
  3. springboot项目打包是jar,而且直接通过java-jar直接运行,此时运行的项目路径都是临时的虚拟路径,并不是在当前目录下解压运行,因此文件上传的路径不能是临时的,所以要配置一个绝对路径,这就是上面为什么要在application.xml中配置文件的具体路径的原因
  4. 通常情况接收到客户端上传的文件时,还需要将这个文件存储的路径返回给客户端进行访问,但是此时文件存储在磁盘固定位置上,并不在在这个服务器项目路径中,那该怎么办呢? —-资源映射
  5. 资源映射的原理
    1. 将指定存储文件的磁盘路径映射到项目的静态资源路径下,这样就可以直接访问固定磁盘路径下的资源了
    2. 在application.yml中配置

       #通过什么路径能够访问到静态资源,/**,无论静态资源下面几层目录,直接通过/就可以访问,比如:http://localhost:8080/img/xxx.png
       # 尽管图片的实际路径是:F:/upload/img/xxx.png,但是直接用一个/代表了F:/upload/路径
       spring:
         mvc:
           static-path-pattern: /**
              
       # 告诉springmvc有那些静态资源的路径 
       spring:
         resources:
           static-locations:
             # 项目根目录即resources下的static文件夹
             - classpath:/static/
             # 存储文件的具体磁盘路径,file://本机去查找,/根路径
             - file:///${project.upload.base-path}
      
    3. 这么配置,项目resources下的static、电脑的F:/upload/都变成了静态资源目录,浏览器直接可以访问了
  6. 也可以通过实现WebMvcConfigurer的方法进行静态资源的映射

     public class SpringMvcConfig implements WebMvcConfigurer {
         @Override
         public void addResourceHandlers(ResourceHandlerRegistry registry) {
             registry.addResourceHandler("/**")
                     .addResourceLocations("classpath:/static/");
        
             registry.addResourceHandler("/**")
                     .addResourceLocations("file:///F:/upload/");
         }
     }
    
  7. 总结
    1. 在SpringBoot中,静态资源需要进行映射才能直接访问
    2. SpringBoot默认的静态资源映射处理,看下面源码路径,就是如何设置静态资源的访问目录

       spring-boot-autoconfigure.jar->
       打开spring.factories->
       搜索WebMvcAutoConfiguration->
       WebMvcAutoConfigurationAdapter->
       addResourceHandlers
      
    3. 在application.yml中添加的值本质是如下:

       //1. 配置文件中的配置
       spring:
          mvc:
            static-path-pattern: /**
       spring:
          resources:
            static-locations:
                - classpath:/static/
                - file:///F:/upload/
              
       //2. 实际的代码转化如下:
       @Configuration
       public class SpringMvcConfig implements WebMvcConfigurer {
           @Override
           public void addResourceHandlers(ResourceHandlerRegistry registry) {
               registry.addResourceHandler("/**")
                       .addResourceLocations("classpath:/static/");
              
               registry.addResourceHandler("/**")
                       .addResourceLocations("file:///F:/upload/");
           }
       }
      

webjars

  1. SpringBoot支持使用webjars的方式访问静态资源
    1. 本质就是一个第三方库org.webjars,添加了依赖之后,会在maven下新建一个静态资源目录,然后将前端很多的框架导入进去
    2. 在项目中可以直接通过/webjars/路径去访问
  2. 举例:使用webjars方式访问jquery
    1. pom.xml添加依赖

       <dependency>
           <groupId>org.webjars</groupId>
           <artifactId>jquery</artifactId>
           <version>3.5.1</version>
       </dependency>
      
    2. index.html使用

       <button type="button" id="btn-add">添加</button>
       //直接可以引入jquery
       <script src="/webjars/jquery/3.5.1/jquery.min.js"></script>
       <script>
           $('#btn-add').click(() => {
               alert('点击了添加')
           })
       </script>
      

文件下载

  1. 在项目的static文件夹下新建一个txt文件夹,下面有个test.txt文件
  2. index.html

     <a href="/download">下载test.txt文件</a>
    
  3. TestController

     @GetMapping("/download")
     public void download(HttpServletResponse response) throws Exception {
         // 把文件以附件的形式返回
         // 设置响应头
         response.setHeader("Content-Disposition", "attachment; filename=test.txt");
    
         // 读取文件
         try (InputStream is = new ClassPathResource("static/txt/test.txt").getInputStream()) {
             // 将文件数据利用response写回到客户端
             //IOUtils使用commons-io第三方框架
             IOUtils.copy(is, response.getOutputStream());
         }
     }
    

SringMVC-API的参数格式

  1. 控制器api如下:

     @PostMapping("/test1")
     //本质等价于:public DataJsonVo<User> json(@RequestParam User user)
     //此时客户端传递到服务器的body参数格式为字段形式:id=0&name=jk
     public DataJsonVo<User> json(User user) {
         return new DataJsonVo<>(user);
     }
            
     @PostMapping("/test2")
     //此此时客户端传递到服务器的body参数格式为json数据,而不是一个字段一个字段的数据:{"id":10,"name":"jk"}
     // 客户端的Content-Type要设置为application/json,而且传递的格式必须是json格式
     public DataJsonVo<User> json(@RequestBody User user) {
         return new DataJsonVo<>(user);
     }
    
  2. 总结:

    1. @RequestParam: 普通的请求参数
      1. 前端不用做任何处理,客户端传递到服务器的body参数格式为字段形式:id=0&name=jk
    2. @RequestBody:请求体
      1. 客户端的Content-Type要设置为application/json
      2. 而且传递的格式必须是json格式{"id":10,"name":"jk"}
    3. @RequestHeader("header-name"): 请求头
      1. 获取客户端传递过来的请求头

SpringBoot知识点总结

  1. springboot项目没有webapp文件夹,web资源放在了static文件夹,就是静态资源文件夹中即可
  2. 通常使用前后端分离分别部署,但是也可以将前端项目整合到springboot项目目录下一起部署,采用(springboot+Thymeleaf);样例
Table of Contents