Spring boot之WEB 开发-静态资源访问--自定义转换器--处理JSON--内容协商

Spring boot之WEB 开发-静态资源访问

官方文档

在线文档:
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.develo\ping-web-applications

基本介绍

1. 只要静态资源放在类路径下: /static 、/public 、/resources 、/META-INF/resources可以被直接访问- 对应文件WebProperties.java

private static final String[] CLASSPATH_RESOURCE_LOCATIONS =
{
    
     "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };

2. 常见静态资源:JS、CSS 、图片(.jpg .png .gif .bmp .svg)、字体文件(Fonts)等

3. 访问方式:默认: 项目根路径/ + 静态资源名比如http://localhost:8080/hi.jpg . - 设置WebMvcProperties.java

private String staticPathPattern = “/**”;

快速入门

1. 创建SpringBoot 项目springbootweb , 使用灵活配置方式来创建项目

2. 创建相关静态资源目录, 并放入测试图片, 没有目录,自己创建即可, 完成测试

静态资源访问注意事项和细节

1. 静态资源访问原理:静态映射是/**, 也就是对所有请求拦截,请求进来,先看Controller
能不能处理,不能处理的请求交给静态资源处理器,如果静态资源找不到则响应404 页面

2. 改变静态资源访问前缀,比如我们希望http://localhost:8080/hellores/* 去请求静态资源,

应用场景:静态资源访问前缀和控制器请求路径冲突

1) 创建application.yml

spring:
mvc:
static-path-pattern: /hellores/**

2) 重启应用,完成测试, 浏览器输入: http://localhost:8080/hellores/1.jpg

3.改变默认的静态资源路径,比如希望在类路径下增加ninhaoimg 目录作为静态资源路径,
并完成测试.

spring:
  mvc:
    static-path-pattern: /hellores/** #修改静态资源访问的路径/前缀

  web:
    resources:
      #修改/指定 静态资源的访问路径/位置
      #
      static-locations: ["classpath:/ninhaoimg/","classpath:/META-INF/resources/",
                         "classpath:/resources/", "classpath:/static/", "classpath:/public/"]      #String[] staticLocations

3) 测试, 浏览器输入http://localhost:8080/hellores/pen.jpg

[提示: 没错就是这样访问pen.jpg, 不是/ninhaoimg /pen.jpg 形式, 另外因为pen.jpg 还是拷贝来的, 一定要保证工作目录target 有pen.jpg ,如果没有, 请rebulid 下项目, 再重启项目]

4) 如果你配置static-locations, 原来的访问路径就被覆盖,如果需要保留,你再指定一下即可


spring:
  mvc:
    static-path-pattern: /hellores/** #修改静态资源访问的路径/前缀
  web:
    resources:
    #修改/指定静态资源的访问路径/位置

    static-locations: ["classpath:/ninhaoimg /","classpath:/META-INF/resources/",
                   "classpath:/resources/", "classpath:/static/", "classpath:/public/"]
#String[] staticLocations

这之所以不需要http://localhost:8080/hellores/ninhaoimg/12.jpg

是因为修改的默认访问路劲 容器在其他目录找不到的时候就会默认去找ninhaoimg目录下的12.jap


自定义转换器

基本介绍

1. SpringBoot 在响应客户端请求时,将提交的数据封装成对象时,使用了内置的转换器

2. SpringBoot 也支持自定义转换器, 这个内置转换器在debug 的时候, 可以看到, 后面给演示, 提供了124 个内置转换器. 看下源码GenericConverter-ConvertiblePair

自定义转换器-应用实例

需求说明: 演示自定义转换器使用

代码实现

修改save.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加妖怪</title>
</head>
<body>
<h1>添加妖怪-坐骑[测试封装POJO;]</h1>
<form action="/savemonster" method="post">
    编号: <input name="id" value="100"><br/>
    姓名: <input name="name" value="牛魔王"/> <br/>
    年龄: <input name="age" value="500"/> <br/>
    婚否: <input name="isMarried" value="true"/> <br/>
    生日: <input name="birth" value="2000/11/11"/> <br/>
    <!-- 使用自定义转换器关联car, 字符串整体提交, 使用,号间隔  -->
    坐骑:<input name="car" value="避水金晶兽,666.6"><br/>
    <input type="submit" value="保存"/>
</form>
</body>
</html>

创建WebConfig.java,增加自定义转换器


/**
 * @Configuration(proxyBeanMethods = false)
 * 1. 表示 WebConfig 是一个配置类
 * 2. proxyBeanMethods = false 使用Lite模式
 */
@Configuration(proxyBeanMethods = false)
public class WebConfig  {
    
    



    //注入bean WebMvcConfigurer
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
    
    

        return new WebMvcConfigurer() {
    
    
            @Override
            public void addFormatters(FormatterRegistry registry) {
    
    
                /**
                 * 解读
                 * 1. 在addFormatters 方法中,增加一个自定义的转换器
                 * 2. 增加自定义转换器 String -> Car
                 * 3. 增加的自定义转换器会注册到 converters 容器中
                 * 4. converters 底层结构是 ConcurrentHashMap 内置有124转换器
                 * 5. 一会会使用debug来看到这些转换器
                 */

                registry.addConverter(new Converter<String, Car>() {
    
    
                    @Override
                    public Car convert(String source) {
    
    //source就是 传入的字符串 避水金晶兽,666.6
                        //这里就加入你的自定义的转换业务代码
                        if (!ObjectUtils.isEmpty(source)) {
    
    

                            Car car = new Car();
                            String[] split = source.split(",");
                            car.setName(split[0]);
                            car.setPrice(Double.parseDouble(split[1]));
                            return car;
                        }
                        return null;
                    }
                });



                //转种写法来注册自定义转换器-方便理解

                1.先创建自定义的转换器
                //Converter<String,Car> hspConverter = new Converter<String, Car>() {
    
    
                //    @Override
                //    public Car convert(String source) {//source就是 传入的字符串 避水金晶兽,666.6
                //        //这里就加入你的自定义的转换业务代码
                //        if (!ObjectUtils.isEmpty(source)) {
    
    
                //
                //            Car car = new Car();
                //            String[] split = source.split(",");
                //            car.setName(split[0]);
                //            car.setPrice(Double.parseDouble(split[1]));
                //            return car;
                //        }
                //        return null;
                //    }
                //};
                //
                还可以增加更多的转换器
                //2个自定义转换器
                //Converter<String,Monster> hspConverter2 = new Converter<String, Monster>() {
    
    
                //    @Override
                //    public Monster convert(String source) {//source就是 传入的字符串 避水金晶兽,666.6
                //        return null;
                //    }
                //};
                //3个自定义转换器
                //Converter<String,Car> hspConverter3 = new Converter<String, Car>() {
    
    
                //    @Override
                //    public Car convert(String source) {//source就是 传入的字符串 避水金晶兽,666.6
                //        System.out.println("source-" + source);
                //        return null;
                //    }
                //};
                //
                2添加转换器到converters key-[源类型->目标类型]
                //registry.addConverter(hspConverter);
                //registry.addConverter(hspConverter2);
                //registry.addConverter(hspConverter3);
            }
        };
    }
}

3. 完成测试, 浏览器http://localhost:8080/save.html

4. Debug 可以看到我们新增的Converter

------注意看, 多了一个我们自定义的转换器String->com.wyxedu.web.bean.Car


处理JSON

需求说明:

演示返回JSON 格式数据

应用实例

1. SpringBoot 支持返回JSON 格式数据,在启用WEB 开发场景时,已经引入了相关依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

创建ResponseController.java

@Controller
public class ResponseController {
    
    

    //返回Monster数据-要求以json格式返回

    @GetMapping("/get/monster")
    @ResponseBody
    public Monster getMonster() {
    
    
        //说明
        //开发中, monster对象是从DB获取-这里模拟一个monster对象
        Monster monster = new Monster();
        monster.setId(100);
        monster.setName("奔波霸");
        monster.setAge(200);
        monster.setIsMarried(false);
        monster.setBirth(new Date());
        Car car = new Car();
        car.setName("奔驰");
        car.setPrice(222.2);
        monster.setCar(car);
        return monster;
    }
}

Postman 完成测试

Debug 一下monster 对象以Json 格式返回


内容协商

基本介绍

1. 根据客户端接收能力不同,SpringBoot 返回不同媒体类型的数据

2. 比如: 客户端Http 请求Accept: application/xml 则返回xml 数据,客户端Http 请求Accept: application/json 则返回json 数据

比如下面的示意图

内容协商-应用实例

● 需求说明: 使用Postman 发送Http 请求,根据请求头不同,返回对应的json 数据或者xml
数据, 如图

在pom.xml 增加处理xml 的依赖

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

2. 使用Postman 发出不同的Http Header , 可以看到返回对应的数据格式(说明: 测试前请重启一把项目)

3. 切换Postman 不同的Accept 类型, 来Debug 源码, 看看对应的JsonGenerator 类型

4. 使用浏览器请求,为什么会返回xml 数据分析,而不是json?

注意事项和使用细节

1. Postman 可以通过修改Accept 的值,来返回不同的数据格式

2. 对于浏览器,我们无法修改其Accept 的值,怎么办? 解决方案: 开启支持基于请求参数的内容协商功能

1) 修改application.yml, 开启基于请求参数的内容协商功能

spring:
  mvc:
    #static-path-pattern: /hellores/** #修改静态资源访问的路径/前缀
    hiddenmethod:
      filter:
        enabled: true #启用了HiddenHttpMethodFilter,开启页面表单的Rest功能
    view:       #配置视图解析器
      suffix: .html
      prefix: /        #这里是需要注意 prefix需要和当前的static-path-pattern一致
    contentnegotiation:
      favor-parameter: true #开启基于请求参数的内容协商功能
  web:
    resources:
      #修改/指定 静态资源的访问路径/位置
      #
      static-locations: ["classpath:/ninhaoimg/","classpath:/META-INF/resources/",
                         "classpath:/resources/", "classpath:/static/", "classpath:/public/"]      #String[] staticLocations

2)完成测试

  1. 注意,参数format 是规定好的, 在开启请求参数的内容协商功能后,SpringBoot 底层ParameterContentNegotiationStrategy 会通过format 来接收参数,然后返回对应的媒体类型/
    数据格式, 当然format=xx 这个xx 媒体类型/数据格式是SpringBoot 可以处理的才行,不能乱写.

如果需要自定义format 在配置文件加一个

parameter-name: wwwformat #指定一个内容协商的参数名 就好了然后要指定上面格式就不是format=json 而是 wwwformat=json

spring:
  mvc:
    #static-path-pattern: /hellores/** #修改静态资源访问的路径/前缀
    hiddenmethod:
      filter:
        enabled: true #启用了HiddenHttpMethodFilter,开启页面表单的Rest功能
    view:       #配置视图解析器
      suffix: .html
      prefix: /        #这里是需要注意 prefix需要和当前的static-path-pattern一致
    contentnegotiation:
      favor-parameter: true #开启基于请求参数的内容协商功能
      parameter-name: wwwformat #指定一个内容协商的参数名
  web:
    resources:
      #修改/指定 静态资源的访问路径/位置
      #
      static-locations: ["classpath:/ninhaoimg/","classpath:/META-INF/resources/",
                         "classpath:/resources/", "classpath:/static/", "classpath:/public/"]      #String[] staticLocations

.l…

猜你喜欢

转载自blog.csdn.net/apple_67445472/article/details/131114023