【SpringMVC】10—其他概念

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

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

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


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接口

在这里插入图片描述

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

重构处理方法
@RequestMapping("/save/product")
public String saveProduct(
        Product product,
 
      // 在实体类参数和 BindingResult 之间不能有任何其他参数
        // 封装数据绑定结果的对象
        BindingResult bindingResult) {
 
    // 判断数据绑定过程中是否发生了错误
    if (bindingResult.hasErrors()) {
        // 如果发生了错误,则跳转到专门显示错误信息的页面
        // 相关错误信息会自动被放到请求域
        return "error";
    }
 
    logger.debug(product.toString());
 
    return "target";
}
页面显示错误信息
<!-- th:errors 属性:用来显示请求处理过程中发生的错误 -->
<!-- th:errors 属性值:访问错误信息的表达式 -->
<!-- 访问错误信息的表达式:访问请求域,需要使用 ${} 格式 -->
<!-- 访问请求域使用的属性名:执行数据绑定的实体类的简单类名首字母小写 -->
<!-- 具体错误信息:找到实体类之后进一步访问出问题的属性名 -->
<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,T>

泛型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 中注册 FormattingConversionServiceFactoryBean -->
<mvc:annotation-driven conversion-service="formattingConversionService"/>
 
<!-- 在 FormattingConversionServiceFactoryBean 中注册自定义类型转换器 -->
<bean id="formattingConversionService"
      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

    <!-- 在 converters 属性中指定自定义类型转换器 -->
    <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 操作

导入依赖
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-annotation-processor</artifactId>
    <version>6.2.0.Final</version>
</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";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一棵___大树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值