【Spring MVC】 ---- 数据转换和格式化

目录

1.1 HttpMessageConverter和JSON消息转换器
1.2 一对一转换器(Converter)
1.3 数组和集合转换器GenericConverter
1.4 使用格式化器(Formatter)

数据转换和格式化

Spring MVC通过处理器,在HTTP请求到达控制器(Controller)之前对HTTP的各类消息进行处理。

各类注解能够得到类型参数的原因:
当一个请求到达DispatcherServlet时,需要找到对应的HandlerMapping,然后根据HandlerMapping去找到对应的HandlerApater执行处理器。处理器在要调用的控制器之前,先获取HTTP发送过来的信息,然后将其转变为控制器的各种不同类型参数

Spring MVC消息转化流程
在这里插入图片描述

对于Spring MVC,在XML配置了 < mvc:annotation-driven>.SpringIoC容器会自定义生成一个关于转换器和格式化器的类实例----FormattingConversionServiceFactoryBean工厂类,该工厂主要生成DefaultFormattingConversionService类对象

在这里插入图片描述

DefaultFormattingConversionService实现了转换器的注册机(ConverterRegistry)和格式转化器(FormatterRegistry)两个接口

对于转换器而言,在Spring中分为两大类,一种是由Converter接口所定义的,另外一种是GenericConverter,它们都可以使用注册机注册。它们都是来自于Spring Core 项目,而非Spring MVC项目,它的作用范围是Java内部各种类型之间的转换。

1.1 HttpMessageConverter和JSON消息转换器

  • HttpMessageConverter是定义从HTTP接受请求信息和应答给用户的

    HttpMessageConverter接口定义:

    public interface HttpMessageConverter<T> {
    	// 判断类型是否可读,var1是类别,var2是HTTP类型
        boolean canRead(Class<?> var1, @Nullable MediaType var2);
    	// 判断类型是否可写,var1是类别,var2是HTTP类型
        boolean canWrite(Class<?> var1, @Nullable MediaType var2);
    	// 对于mediaType 是 HTTP的类型
        List<MediaType> getSupportedMediaTypes();
    	// 读取数据类型,进行转换,var1是类,var2是HTTP请求消息
        T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
     	// 消息写, 进行转换,var2是HTTP类型,var3是HTTP应答消息
        void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
    }
    
  • JSON消息转换类 -> MappingJackson2HttpMessageConverter

    它能够把控制器返回的结果在处理器内转换为JSON数据

  • 使用XML配置MappingJackson2HttpMessageConverter

    <!--配置MappingJackson2HttpMessageConverter-->
        <!--创建RequestMappingHandlerApater适配器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <!--往适配器加入JSON转换器-->
            <property name="messageConverters">
                <list>
                    <ref bean="jsonConverter"/>
                </list>
            </property>
        </bean>
    
        <!--HTTP JSON转换器-->
        <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <!--http类型支持为JSON类型-->
            <property name="supportedMediaTypes">
                <list>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    

    注解@ResponseBody将标记Spring MVC,将响应结果转变为JSON,这样在控制器返回结果后,它会通过类型判断找到MappingJackson2HttpMessageConverter实例,进而在处理器内转变为JSON,从而满足JSON的转换的要求

1.2 一对一转换器(Converter)

接口Conveter

/**
* S 源类型
* T 目标类型
**/
@FunctionalInterface
public interface Converter<S, T> {
    @Nullable
    T convert(S var1);
}

Spring Core项目的部分转换器

转换器说明
CharacterToNumber将字符转换为数字
IntegerToEnum将整数转换为枚举类型
ObjectToStringConverter将对象转换为字符串
SerializingConverter序列化转换器
DeserializingConverter反序列转换器
StringToBooleanConverter将字符串转换为布尔值
StringToEnum将字符串转换为枚举
EnumToStringConverter将枚举转化为字符串

通过HttpMessageConverter把HTTP消息读出后,Spring MVC就开始使用这些转换器将HTTP的信息,转化为控制器的参数。

自定义转换器案例
需求: url中按照格式{id}-{role_name}-{note}传递,传递一串字符串,控制器参数为Role类型,以-作为分隔符,所以我们自定义一个字符串角色转换器,将字符串转换为pojo类型

  • 字符串角色转换器

    public class StringToRoleConverter implements Converter<String, Role> {
    
        @Override
        public Role convert(String str) {
            // 空串
            if(StringUtils.isEmpty(str)) {
                return null;
            }
    
            // 不包含指定字符
            if(str.indexOf("-") == -1) {
                return null;
            }
    
            String[] arr = str.split("-");
            // 字符串长度不对
            if(arr.length != 3) {
                return null;
            }
    
            Role role = new Role();
            role.setId(Long.parseLong(arr[0]));
            role.setRoleName(arr[1]);
            role.setNote(arr[2]);
            return role;
        }
    }
    
  • 使用XML注册自定义转换器

    <!--使用注解驱动Spring MVC, 指定转换服务类-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--注册自定义转换器-->
        <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
                <list>
                    <!--转换服务类注册转换器-->
                    <bean class="cn.whc.converter.StringToRoleConverter"/>
                </list>
            </property>
        </bean>
    

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

1.3 数组和集合转换器GenericConverter

上述转换器是一对一的转换,只能从一种类型转换成另一种类型,不能进行一对多转换,比如把String转换为List < String >或者 String[]

Spring Core其它类型转换器GenericConverter,ConditionalConverter,ConditionalGenericConverter 满足数组和集合转换的要求。
在这里插入图片描述
案例演示
接受角色List对象

@RequestMapping(value = "/updateRole")
    @ResponseBody
    public Map<String, Object> updateRole(List<Role> roleList) {
        Map<String, Object> result = new HashMap<>();
        // 更新角色
        boolean updateFlag = (roleService.updateRoleArr(roleList) == 1);
        result.put("success", updateFlag);
        if(updateFlag) {
            result.put("msg", "更新成功");
        } else {
            result.put("msg", "更新失败");
        }
        return result;
    }

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

1.4 使用格式化器(Formatter)

有些数据需要格式化,比如说金额、日期等。

传递的日期格式为yyyy-MM-dd 或者 yyyy-MM-dd hh:ss:mm
对于金额,比如一万元人名币,正式场合往往写成 ¥ 10 000.00
通过注解@DateTimeFormat和注解@NumberFormat对数据进行格式化

案例
form.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form id="form" action="${pageContext.request.contextPath}/converter/formatPojo.do">
        <table>
            <tr>
                <td>日期</td>
                <td>
                    <input id="date" name="date" type="text" value="2020-4-24"/>
                </td>
            </tr>
            <tr>
                <td>数字</td>
                <td>
                    <input id="amount" name="amount" type="text" value="123,000.00"/>
                </td>
            </tr>
            <tr>
                <td></td>
                <td align="center"><input id="commit" type="submit" value="提交"></td>
            </tr>
        </table>
    </form>
</body>
</html>

FormatPojo

public class FormatPojo {

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private Date date;

    @NumberFormat(pattern = "##,###.00")
    private BigDecimal amount;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}
@Controller
@RequestMapping("/converter")
public class ConverterController {

    @RequestMapping("/formatPojo")
    public ModelAndView formatPojo(FormatPojo pojo){
        ModelAndView mv = new ModelAndView("index");
        mv.addObject("date", pojo.getDate());
        mv.addObject("amount", pojo.getAmount());
        return mv;
    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值