springMVC笔记2

在这里插入图片描述

数据绑定:

1.数据绑定概念

将HTTP请求中的参数一定的方式转换并绑定到控制器类的方法参数中,这个过程就是Spring MVC中的数据绑定

在数据绑定过程中,Spring MVC框架会通过数据绑定组件(DataBinder)将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数。

2.数据绑定的原理:

前后台交互遇到的3个问题:

1…数据绑定前的数据类型转换:前端页面请求带来的参数默认都是字符串,而我们后台需要的java对象有各种类型数据,所以要涉及到各种数据类型的转换,比如前台的年龄(String类型)需要在后台转换成int类型的年龄。当此类参数特别多的时候springmvc怎么帮我们进行转化呢?

2.数据绑定前的数据格式化: 前台表单我们经常会输入 日期和数字,但是系统默认的格式有时候不符合我们的要求,例如我们希望日期是(2019-11-15)格式输入的。这时候就可以用到 数据格式化的内容了。

3.数据合法性校验:虽然我们有前端的数据校验,但是前端字段的校验可以被越过,而后台的校验对于重要数据是必须的。

在这里插入图片描述

在这里插入图片描述
浏览器这样做可以禁用前台的js脚本,以此来越过前台的校验。

在这里插入图片描述

对象封装的过程:

第一步:想创建一个java对象,各项属性都是空的默认值。
第二步:将请求中所有与java对象对应的属性一一设置进来。(相同的属性名才设置)


数据绑定的源码:

getMethodArgumentValues()方法获取调用的处理器方法的参数,通过参数解析器argumentResolvers逐一解析方法的参数,ModelAttributeMethodProcessor类的resolveArgument()方法部分源码如下:
在这里插入图片描述

底层代码this.bindRequestParameters(binder, webRequest);代码主要负责数据的绑定工作。
断点调试的时候我们在实体类的setXXX方法上打一个断点。明显看出来setter方法被调用了。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


3.数据绑定流程:

在这里插入图片描述

数据绑定流程原理★
① Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
② DataBinder 调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet 中的请求信息填充到入参对象中

③ 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象

④ Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参

Spring MVC 通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是 DataBinder,运行机制如下:

在这里插入图片描述

4.自定义数据绑定的转换器:

将下图所示的表单信息提交并绑定到一个实体类对象中。(多个属性参数写成了一个字符串,中间用-分割。)
ngyi

在这里插入图片描述

1.Converter:

spring框架提供了一个Converter用于将一种类型的对象转换为另一种类型的对象。
而Converter是一个接口,我们自定义的Converter需要实现Converter接口。
转换器要实现的接口:

在这里插入图片描述
实现自定义数据转换器的第一步
自定义类实现Converter接口(org.springframework.core.convert.converter.Converter):

在这里插入图片描述

代码如下:

package com.fan.converter;

import com.fan.pojo.User;
import org.springframework.core.convert.converter.Converter;

//Converter<String,User>:将String转为User对象,泛型需要指明
public class MyStringToUserConverter implements Converter<String,User> {

    @Override//参数是字符串,返回值是转成的对象
    public User convert(String source) {
        System.out.println("这是我的自定义转换器在工作-------");
        System.out.println("页面提交的需要转换的字符串:"+source);
        User user = new User();

        if(source.contains("-")){
            //分割字符串
            String[] split = source.split("-");
            //给对象赋值,即给创建的对象赋前端的参数值
            user.setName(split[0]);
            user.setAge(Integer.parseInt(split[1]));
        }
        return user;
    }
}

在convert方法中编写自定义的转换规则:

在这里插入图片描述

上面的代码中,Converter<String,User>:将String转为User对象,泛型需要指明。该接口中的第一个类型String表示需要被转换的数据类型,第二个类型User表示需要转成的目标类型。第二个类型也可以是其他类型,如Date等;

自定义数据转换器的第二步
显示的配置自定义类型转换器:

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="com.fan"></context:component-scan>
    <!--mvc驱动注解,显示的装配自定义类型转换器-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    <!--自定义类型转换器配置-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.fan.converter.MyStringToUserConverter"></bean>
            </set>
        </property>
    </bean>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结:自定义类型的转换器,三步曲:**在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

自定义数据转换器的第三步

index.jsp中的表单

<%--
  Created by IntelliJ IDEA.
  User: fan
  Date: 2021/3/25
  Time: 9:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <form action="${pageContext.request.contextPath}/quickaddUser" method="post">
  <%--将用户的所有信息都写上,自动封装对象--%>
    <input type="text" name="userinfo" value="admin-30">
    <input type="submit" value="快速添加">
  </form>
  </body>
</html>

controller中的代码测试:

package com.fan.controller;

import com.fan.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserConverterController {
    @RequestMapping("/quickaddUser")
    public String quickAdd(@RequestParam("userinfo")User user){
        System.out.println("封装:"+user);
        System.out.println(user.getClass());
        return "success";
    }
}

mvc:annotation-driven的作用:

在这里插入图片描述

系统中有一个接口下面有好多专门解析各种标签的类:

在这里插入图片描述
在解析这个mvc注解驱动的时候,系统帮我们添加了好多东西。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

两个注解都加上,则静态资源和动态资源都能正常运行:

在这里插入图片描述
在这里插入图片描述

数据格式化:

1.对属性对象输入输出的数据进行格式化,本质上还是属于数据类型的转换。
2.Spring 在格式化模块中定义了一个实现 ConversionService 接口的 FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能。
3.支持对数值类型的属性使用 @NumberFormat 注解,对日期属性@DateTimeFormat注解
4.mvc:annotation-driven/ 默认创建的 ConversionService 实例即为
DefaultFormattingConversionService,也就是说,只要在配置文件中注册了 mvc:annotation-driven/就可以在SpringMVC入参绑定和输出时使用注解驱动。

之前在java类里面我们对于日期的格式化都是使用SimpleDateFormat 来格式化数据

用法:要使用数据的格式化,即规定页面提交的日期格式或者数字格式。比如按照2020-12-18这种格式的日期可以被解析并数据绑定。就必须要使用两个常用的注解:

@DateTimeFormat(pattern = “yyyy-MM-dd”):规定页面提交的日期格式
@NumberFormat(pattern = “”):规定页面提交的数据格式

要使用这两个注解,先要在web.xml中有annotation-driven注解驱动。
然后要导入一个maven坐标:这里使用第三方的框架hibernate-validator验证,比较全。

<dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.6.Final</version>
        </dependency>

然后就可以使用上面的两个注解。

注意:当使用了注解驱动后,但是实体类中没有@DateTimeFormat(pattern = “yyyy-MM-dd”):规定页面提交的日期格式,此时发送请求,可能会报错。框架默认支持的格式为斜线方式。2001/04/08

当我们在后台需要对前端的参数封装的javabean进行校验的时候,还需要用到一个方法中参数的注解:
public String addUser(@Valid User user){}//表示校验user对象,按照其校验规格来。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
自定义格式化转换:

当我们既要用我们自定义的类型转换器,又要用格式化的功能,怎么办?
按照如下操作即可:
只需要改这里:

bean id=“conversionService” class=“org.springframework.format.support.FormattingConversionServiceFactoryBean”>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

后台数据校验:

所谓的数据校验,就是检验输入的数据和输出的数据是否为指定的格式,跟数据格式化类似,但是比格式化更加强大。

通过在处理方法的入参上标注 @Valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作。

在这里插入图片描述
JSR 303:

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

在这里插入图片描述

在这里插入图片描述
Hibernate Validator 扩展注解:

Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解
在这里插入图片描述

如何校验?在SpringMVC中分为以下几步骤:

①使用JSR 303验证标准
②加入hibernate validator验证框架
③在SpringMVC配置文件中增加 mvc:annotation-driven/
④需要在bean的属性上增加对应验证的注解
⑤在目标方法bean类型的前面增加@Valid注解

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

前端页面:使用springmvc的form表单标签,更方便数据的回显:

在页面上检验错误信息:
将验证错误的信息显示在可以用表单标签,Spring MVC 除了会将表单/命令对象的校验结果保存到对应的 BindingResult 或 Errors 对象中外,还会将所有校验结果保存到 “隐含模型”
在 JSP 页面上可通过 <form:errors path=“userName”> 显示错误消息。

在这里插入图片描述

在这里插入图片描述

代码演示:
index.jsp页面:

<%--
  Created by IntelliJ IDEA.
  User: fan
  Date: 2021/3/26
  Time: 9:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="hello">测试hello</a><br>
  <a href="toForm1">利用view-controller去到toForm1</a>
  </body>
</html>

springmvcform1.jsp页面(此页面在WEB-INF/pages下):

<%--
  Created by IntelliJ IDEA.
  User: fan
  Date: 2021/3/26
  Time: 9:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>
<head>
    <title>这里是springmvc的表单标签</title>
</head>
<body>

<h1>这里是springmvc的表单标签</h1>
<%--使用自带form标签是,必须先通过model对象,传递了一个空的user对象到页面.--%>
<form:form action="${pageContext.request.contextPath}/addUser" modelAttribute="user" method="post">
    <%--<form:errors path="birth">用于显示错误消息,从后台的隐含模型中拿错误消息--%>
    用户名:<form:input  path="name"></form:input><form:errors path="name"></form:errors><br>
   年龄:<form:input  path="age"></form:input><form:errors path="age"></form:errors><br>
    生日:<form:input path="birth"></form:input> <form:errors path="birth"></form:errors><br>
    <input type="submit" value="提交">
</form:form>
</body>
</html>

实体类代码(带数据格式化和JSR303校验:)User:

package com.fan.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;

import javax.validation.constraints.Max;
import javax.validation.constraints.Past;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Length(min = 3)//最小长度3位
    private String name;
    @Max(150)//最大年龄150岁
    private Integer age;
    /*前端请求参数封装的时候要经过这里的set方法*/
    @Past//必须是一个过去的时间,比如生日
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birth;
}

Controller代码:

package com.fan.controller;

import com.fan.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;

@Controller
public class UserController {

    @RequestMapping(value = "/hello")
    public String hello(){
        return "success";
    }

    @RequestMapping(value = "/toForm1")
    public String toForm1(Model model){
        model.addAttribute("user",new User());
        return "springmvcform1";
    }



    @RequestMapping("/addUser")
    public String addUser(@Valid User user, BindingResult result){
        System.out.println("前端封装的数据:"+user);

        return "springmvcform1";//必须转发返回到添加页面才能看到错误消息提示;
    }
}

验证显示:
在这里插入图片描述
原生表单怎么获取错误消息:

在这里插入图片描述

在这里插入图片描述

国际化定制自己的错误消息显示:

在这里插入图片描述

准备国际化文件:
在这里插入图片描述

国际化文件的错误消息的key遵循的规则:有以下四种:
在这里插入图片描述

第一步:编写国际化文件内容:在这里插入图片描述

在这里插入图片描述

第二步:让springmvc管理国际化文件:使用一个类:ResourceBundleMessageSource

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

springmvc.xml中的配置(让spring管理消息资源):

<!--加载国际化的资源文件-->
    <bean class="org.springframework.context.support.ResourceBundleMessageSource">
        <!--资源文件的前缀名字-->
        <property name="basename" value="com.fan.conf.error"></property>
    </bean>

最终效果:
在这里插入图片描述

还可以这样进行消息提示,但是此种方式不能国际化:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值