【SpringMVC】10—其他概念

⭐⭐⭐⭐⭐⭐
Github主页https://github.com/A-BigTree
笔记链接https://github.com/A-BigTree/Code_Learning
⭐⭐⭐⭐⭐⭐

如果可以,麻烦各位看官顺手点个star~

如果文章对你有所帮助,可以点赞收藏⭐支持一下博主~


文章目录

  • 10 其他概念
    • 10.1 类型转换
      • 10.1.1 自动类型转换
      • 10.1.2 日期和数值类型
        • 注解设定数据格式
        • 表单
        • 处理方法
      • 10.1.3 转换失败处理方式
        • `BindingResult`接口
        • 重构处理方法
        • 页面显示错误信息
      • 10.1.4 自定义类型转换器
        • 创建实体类
        • 创建自定义类型转换器类
        • Spring-MVC中注册
        • 表单
        • 处理方法
    • 10.2 数据校验
      • 10.2.1 校验概述
      • 10.2.2 操作
        • 导入依赖
        • 应用校验规则
    • 10.3 请求映射的其他方式
      • 10.3.1 根据请求参数情况映射
      • 10.3.2 根据请求消息头内容映射
      • 10.3.3 Ant风格通配符
    • 10.4 `@ModelAttribute`注解
    • 10.5 `@RequestHeader`注解

10 其他概念

10.1 类型转换

SpringMVC 将『把请求参数注入到POJO对象』这个操作称为『数据绑定』,英文单词是 binding。数据类型的转换和格式化就发生在数据绑定的过程中。 类型转换和格式化是密不可分的两个过程,很多带格式的数据必须明确指定格式之后才可以进行类型转换。最典型的就是日期类型。

10.1.1 自动类型转换

HTTP 协议是一个无类型的协议,我们在服务器端接收到请求参数等形式的数据时,本质上都是字符串类型。请看 javax.servlet.ServletRequest 接口中获取全部请求参数的方法:

public Map<String, String[]> getParameterMap();

而我们在实体类当中需要的类型是非常丰富的。对此,SpringMVC对基本数据类型提供了自动的类型转换。例如:请求参数传入“100”字符串,我们实体类中需要的是 Integer 类型,那么 SpringMVC 会自动将字符串转换为 Integer 类型注入实体类。

10.1.2 日期和数值类型

注解设定数据格式

public class Product {
 
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date productDate;
 
    @NumberFormat(pattern = "###,###,###.###")
    private Double productPrice;

表单

<form th:action="@{/save/product}" method="post">
    生产日期:<input type="text" name="productDate" value="1992-10-15 17:15:06" /><br/>
    产品价格:<input type="text" name="productPrice" value="111,222,333.444" /><br/>
    <button type="submit">保存button>
form>

处理方法

@RequestMapping("/save/product")
public String saveProduct(Product product) {
 
    logger.debug(product.toString());
 
    return "target";
}

10.1.3 转换失败处理方式

BindingResult接口

【SpringMVC】10—其他概念_第1张图片

BindingResult接口和它的父接口Errors中定义了很多和数据绑定相关的方法,如果在数据绑定过程中发生了错误,那么通过这个接口类型的对象就可以获取到相关错误信息。

重构处理方法

@RequestMapping("/save/product")
public String saveProduct(
        Product product,
 
      // 在实体类参数和 BindingResult 之间不能有任何其他参数
        // 封装数据绑定结果的对象
        BindingResult bindingResult) {
 
    // 判断数据绑定过程中是否发生了错误
    if (bindingResult.hasErrors()) {
        // 如果发生了错误,则跳转到专门显示错误信息的页面
        // 相关错误信息会自动被放到请求域
        return "error";
    }
 
    logger.debug(product.toString());
 
    return "target";
}

页面显示错误信息






<p th:errors="${product.productDate}">这里显示具体错误信息p>

10.1.4 自定义类型转换器

在实际开发过程中,难免会有某些情况需要使用自定义类型转换器。因为我们自己自定义的类型在 SpringMVC 中没有对应的内置类型转换器。此时需要我们提供自定义类型来执行转换。

创建实体类

public class Address {
 
    private String province;
    private String city;
    private String street;
    ……
public class Student {
 
    private Address address;
    ……

创建自定义类型转换器类

实现接口:org.springframework.core.convert.converter.Converter

泛型S:源类型(本例中是String类型)

泛型T:目标类型(本例中是Address类型)

public class AddressConverter implements Converter<String, Address> {
    @Override
    public Address convert(String source) {
  
        // 1.按照约定的规则拆分源字符串
        String[] split = source.split(",");
         
        String province = split[0];
        String city = split[1];
        String street = split[2];
 
        // 2.根据拆分结果创建 Address 对象
        Address address = new Address(province, city, street);
         
        // 3.返回转换得到的对象
        return address;
    }
}

Spring-MVC中注册


<mvc:annotation-driven conversion-service="formattingConversionService"/>
 

<bean id="formattingConversionService"
      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

    
    <property name="converters">
        <set>
            <bean class="com.atguigu.mvc.converter.AddressConverter"/>
        set>
    property>
 
bean>

表单

<h3>自定义类型转换器h3>
<form th:action="@{/save/student}" method="post">
    地址:<input type="text" name="address" value="aaa,bbb,ccc" /><br/>
form>

处理方法

@RequestMapping("/save/student")
public String saveStudent(Student student) {
 
    logger.debug(student.getAddress().toString());
 
    return "target";
}

10.2 数据校验

在 Web 应用三层架构体系中,表述层负责接收浏览器提交的数据,业务逻辑层负责数据的处理。为了能够让业务逻辑层基于正确的数据进行处理,我们需要在表述层对数据进行检查,将错误的数据隔绝在业务逻辑层之外。

10.2.1 校验概述

JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0标准中。JSR 303通过在Bean属性上标注类似于 @NotNull@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。

注解 规则
@Null 标注值必须为 null
@NotNull 标注值不可为 null
@AssertTrue 标注值必须为 true
@AssertFalse 标注值必须为 false
@Min(value) 标注值必须大于或等于 value
@Max(value) 标注值必须小于或等于 value
@DecimalMin(value) 标注值必须大于或等于 value
@DecimalMax(value) 标注值必须小于或等于 value
@Size(max,min) 标注值大小必须在 max 和 min 限定的范围内
@Digits(integer,fratction) 标注值值必须是一个数字,且必须在可接受的范围内
@Past 标注值只能用于日期型,且必须是过去的日期
@Future 标注值只能用于日期型,且必须是将来的日期
@Pattern(value) 标注值必须符合指定的正则表达式

JSR 303 只是一套标准,需要提供其实现才可以使用。Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:

注解 规则
@Email 标注值必须是格式正确的 Email 地址
@Length 标注值字符串大小必须在指定的范围内
@NotEmpty 标注值字符串不能是空字符串
@Range 标注值必须在指定的范围内

Spring 4.0 版本已经拥有自己独立的数据校验框架,同时支持 JSR 303 标准的校验框架。Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。在SpringMVC 中,可直接通过注解驱动 mvc:annotation-driven 的方式进行数据校验。Spring 的 LocalValidatorFactoryBean 既实现了 Spring 的 Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在Spring容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。Spring本身并没有提供JSR 303的实现,所以必须将JSR 303的实现者的jar包放到类路径下。

配置 mvc:annotation-driven 后,SpringMVC 会默认装配好一个 LocalValidatorFactoryBean,通过在处理方法的入参上标注 @Validated 注解即可让 SpringMVC 在完成数据绑定后执行数据校验的工作。

10.2.2 操作

导入依赖


<dependency>
    <groupId>org.hibernate.validatorgroupId>
    <artifactId>hibernate-validatorartifactId>
    <version>6.2.0.Finalversion>
dependency>

<dependency>
    <groupId>org.hibernate.validatorgroupId>
    <artifactId>hibernate-validator-annotation-processorartifactId>
    <version>6.2.0.Finalversion>
dependency>

应用校验规则

标记规则注解:

// 字符串长度:[3,6]
@Size(min = 3, max = 6)

// 字符串必须满足Email格式
@Email
private String email;

在处理方法形参注解:

@RequestMapping("/save/person")
public String saveperson(@Validated Person person) {
 
    logger.debug(person.getEmail());
 
    return "target";
}

10.3 请求映射的其他方式

10.3.1 根据请求参数情况映射

使用 @RequestMapping 注解的 params 参数实现,表达式语法参见下面的例子:

需求 映射方式
请求参数中必须包含userName @RequestMapping(value = “/xxx”, params=“userName”)
请求参数中不能包含userName @RequestMapping(value = “/xxx”, params=“!userName”)
请求参数中必须包含userName且值必须为Tom2015 @RequestMapping(value = “/xxx”, params=“userName=Tom2015”)
请求参数中必须包含userName但值不能为Tom2015 @RequestMapping(value = “/xxx”, params=“userName=!Tom2015”)
请求参数中必须包含userName且值为Tom2015,同时必须包含userPwd但值不限 @RequestMapping(value = “/xxx”, params={“userName=Tom2015”,“userPwd”} )

10.3.2 根据请求消息头内容映射

使用 @RequestMapping 注解的 headers 参数实现,表达式语法参见下面的例子:

需求 映射方式
根据 Accept-Language:zh-CN,zh;q=0.8 映射 @RequestMapping (value=“/xxx”,headers= “Accept-Language=zh-CN,en;q=0.8” )

10.3.3 Ant风格通配符

  • 英文问号:匹配一个字符
  • 一个星号:匹配路径中的一层
  • 两个连续星号:匹配路径中的多层

10.4 @ModelAttribute注解

handler 类中,选定一个方法标记 @ModelAttribute 注解。

  • 效果1:在每个 handler 方法前执行
  • 效果2:可以将某些数据提前存入请求域
@Controller
public class ModelAttrHandler {
 
    @ModelAttribute
    public void doSthBefore(Model model) {
        model.addAttribute("initAttr", "initValue");
    }
 
    @RequestMapping("/test/model/attr/one")
    public String testModelAttrOne(Model model) {
 
        Object modelAttribute = model.getAttribute("initAttr");
        System.out.println("modelAttribute = " + modelAttribute);
 
        return "target";
    }
 
    @RequestMapping("/test/model/attr/two")
    public String testModelAttrTwo(Model model) {
 
        Object modelAttribute = model.getAttribute("initAttr");
        System.out.println("modelAttribute = " + modelAttribute);
 
        return "target";
    }
 
    @RequestMapping("/test/model/attr/three")
    public String testModelAttrThree(Model model) {
 
        Object modelAttribute = model.getAttribute("initAttr");
        System.out.println("modelAttribute = " + modelAttribute);
 
        return "target";
    }
 
}

10.5 @RequestHeader注解

通过这个注解获取请求消息头中的具体数据。

@RequestMapping("/request/header")
public String getRequestHeader(
    
        // 使用 @RequestHeader 注解获取请求消息头信息
        // name 或 value 属性:指定请求消息头名称
        // defaultValue 属性:设置默认值
        @RequestHeader(name = "Accept", defaultValue = "missing") String accept
) {
    
    logger.debug("accept = " +accept);
    
    return "target";
}

你可能感兴趣的:(微服务,#SpringMVC,servlet,java,前端)