【SpringMVC】10—其他概念

news2024/11/14 11:31:05

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

在这里插入图片描述

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";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年Web3的五大趋势

Web3 这个词有时被称为 "去中心化的互联网"&#xff0c;涵盖了一些重要的互联网发展趋势。Web3 的愿景是创造一个不受大公司控制的互联网&#xff0c;如Alibaba、baidu、Google和Facebook&#xff0c;这些公司制定了互联网的大部分规则&#xff0c;掌控着我们今天可以…

HyperWorks2021软件安装教程

下载软件 https://www.xsoftnet.com/share/a0004MWyQAg9r.html产品介绍&#xff1a; HyperWorks一款功能强大的开放式架构仿真软件。拥有先进的技术以及高性能、高效和创新的产品&#xff0c;为用户提供了设计、仿真和制造等服务。支持电磁分析设计、材料建模制造、多物理场分…

学校的地下网站(学校的地下网站1080P高清)

这个问题本身就提得有问题&#xff0c;为什么这么说&#xff0c;这是因为YouTube本身就不是一个视频网站或者说YouTube不是一个传统的视频网站&#xff01;&#xff01;&#xff01; YouTube能够一家独大&#xff0c;可不仅仅是因为有了Google 这个亲爹&#xff0c;还有一点&am…

Flutter Web 开发实践与优化

一,Flutter Web架构 目前,除了可以支持Android、iOS移动跨平台开发之外,Flutter还支持macOS、Windows、Linux和Web等多个跨平台的开发。可以说,作为一款先进的跨平台开发框架,Flutter已经真正意义上实现了“一次编写,处处运行”的美好愿景。 众所周知,Dart 语言存在之…

【建议收藏】数据库 SQL 入门——事务(内附演示)

文章目录&#x1f4da;引言&#x1f4d6;事务&#x1f4d1;事务的概念&#x1f4d1;事务操作&#x1f516;查看与设置事务提交方式&#x1f516;提交事务与回滚事务&#x1f4d1;事务的特性&#x1f4d1;并发事务问题&#x1f4d1;事务隔离级别&#x1f4cd;总结&#x1f4da;引…

8.基于拉丁超立方法的风光场景生成与削减

matlab代码&#xff1a;基于拉丁超立方法的风光场景生成与削减 摘要&#xff1a;与蒙特卡洛法不同&#xff0c;拉丁超立方采样改进了采样策略能够做到较小采样规模中获得较高的采样精度&#xff0c;属于分层抽样技术&#xff0c;设定风光出力遵从正态分布normrnd&#xff0c;从…

字节面试体验值拉满~

今天分享一位读者春招的字节二面面经&#xff0c;岗位是后端开发。 一个编程语言都没问&#xff0c;都是问网络项目mysqlredis。 问题记录 使用消息中间件降低消息持久化的压力是怎么做的&#xff0c;为什么可以降低&#xff1f; 读者答&#xff1a;在突发大量消息的情况下…

水塘抽样解决随机选择问题

1.简介 水塘抽样是一系列的随机算法&#xff0c;其目的在于从包含n个项目的集合S中选取k个样本&#xff0c;其中n为一很大或未知的数量&#xff0c;尤其适用于不能把所有n个项目都存放到内存的情况。最常见例子为Jeffrey Vitter在其论文中所提及的算法R。 2.算法步骤&#xff1…

AD823AARZ-RL-ASEMI代理亚德诺AD823AARZ-RL车规级芯片

编辑-Z AD823AARZ-RL芯片参数&#xff1a; 型号&#xff1a;AD823AARZ-RL −3dB带宽&#xff1a;17 MHz 全功率响应&#xff1a;4.8 MHz 斜率&#xff1a;30 V/s 输入电压噪声&#xff1a;14 nV/√Hz 输入电流噪声&#xff1a;1 fA/√Hz 初始偏移量&#xff1a;0.12mV …

nacos集群配置高可用数据库

1.架构 nacos集群配置高可用数据库的架构其实和nacos集群的架构差不多&#xff0c;只是在数据库方面做了主从跟keepalive实现数据库的高可用&#xff0c;当mysql的master节点挂掉时&#xff0c;keepalive的vip自动漂移到slave节点&#xff0c;并通过脚本使slave节点提升为mast…

Leetcode.1992 找到所有的农场组

题目链接 Leetcode.1992 找到所有的农场组 Rating &#xff1a; 1539 题目描述 给你一个下标从 0 开始&#xff0c;大小为 m x n 的二进制矩阵 land &#xff0c;其中 0 表示一单位的森林土地&#xff0c;1 表示一单位的农场土地。 为了让农场保持有序&#xff0c;农场土地之…

QT程序退出还占进程

问题情况 程序运行时的样子&#xff1a; 程序退出时的样子&#xff1a; 其跑到了后台进程里面&#xff1a; 程序退出了&#xff0c;但在任务管理器里查看&#xff0c;其从进程里面转移到后台进程了。 这种问题&#xff0c;怎么办&#xff0c;代码里&#xff0c;应该释放的也都…

微信小程序引入广告位功能,详细步骤!!!

大家碰到过首页加载时一开始出现的广告页面&#xff0c;这种微信官方提供了一个api进行设置&#xff0c;下面我们来详细解释一下。 首先第一步需要小程序累计用户数达到1000即可开通流量主&#xff0c;成功开通流量主之后就可以创建相应的广告位了&#xff0c;包括banner广告、…

【设计模式】如何在业务开发中使用适配器模式?

文章目录前言适配器模式定义通用代码实现适用场景案例场景分析一坨坨代码实现适配器模式重构总结前言 适配器模式&#xff08;Adapter Pattern&#xff09;&#xff1a;将一个类的接口变换成客户端所期待的另一种接口&#xff0c;从而使原本因接口不匹配而无法在一起工作的两个…

Can‘‘t connect to MySQL server on localhost (10061)解决方法

首先检查MySQL 服务没有启动》如果没有启动&#xff0c;则要启动这个服务。 有时候安装mysql后使用mysql命令时报错 Cant connect to MySQL server on localhost (10061)&#xff0c;或者用net start mysql 时报服务名无效&#xff0c;一般是因为mysql服务没有启动。 打开 powe…

itop-3568开发板驱动学习笔记(18)tasklet 机制

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录tasklet 简介tasklet 结构体tasklet 初始化使能 tasklet失能 tasklettasklet 调度函数tasklet 取消调度函数tasklet 实验tasklet 简介 Tasklets 机制是linux中断处理机制中的软中断延迟机制。在linux中存在着…

【ES】搜索结果处理RestClient查询文档

【ES】搜索结果处理&RestClient查询文档2.搜索结果处理2.1.排序2.1.1.普通字段排序2.1.2.地理坐标排序2.2.分页2.2.1.基本的分页2.2.2.深度分页问题2.2.3.小结2.3.高亮2.3.1.高亮原理2.3.2.实现高亮2.4.总结3.RestClient查询文档3.1.快速入门3.1.1.发起查询请求3.1.2.解析响…

【计算机图形学】图形变换(平移变换、比例变换、旋转变换、对称变换、错切变换、复合变换)

一 实验目的 编写图形各种变换的算法二 实验内容 1&#xff1a;自行设计基本图案&#xff0c;完成1-5种简单变换 实验结果如下图所示&#xff1a; 图形初始化&#xff1a; 第一次点击左键&#xff0c;实现平移变换&#xff1a; 第二次点击左键&#xff0c;实现比例变换&…

Android 性能优化——APP启动优化详解

1.1 为什么要启动优化&#xff1f; 用户希望应用能够及时响应并快速加载&#xff0c;启动时间过长的应用不能满足这个期望&#xff0c;并且可能使用户失望。 启动太慢的结果&#xff1a; 体验效果差用户放弃使用你的应用时间越长用户流失越高产品死掉 1.2 启动优化流程及分…

HDLBits-Modules 题解【Verilog模块例化】(中文翻译+英文原文,可顺带学习英文)

Moudule 概念介绍 到目前为止&#xff0c;你已经熟悉了一个模块&#xff0c;它是一个通过输入和输出端口与其外部交互的电路。更大、更复杂的电路是通过将较小的模块和其他连接在一起的部分&#xff08;例如赋值语句和always块&#xff09;组合而成的更大模块来构建的。因为模…