springboot mybatis自定义枚举enum转换

摘要:
BaseEnum接口定义如下:清单3:枚举packageorg所需的实现接口。fhp。springbootdemo实体;publicinterfaceBaseEnum{intgetValue();}3、 Converter接口的好处是Spring为我们提供了一个自动类型转换接口Converter,它可以将一个对象转换为另一个对象。应该注意的是,在SpringMVC和SpringBoot中,由于从客户端接收的请求被视为String类型,因此只能使用String转换为枚举转换器。清单5:字符串到性别的转换器实现是packageorg。fhp。springbootdemo。转换器;importorg.springframework.core.covert.converter。转换器;publicclassStringToGenderConverterimplementsConverter<String,性别>{@OverridepublicGenderconvert{returnGender.getByValue;}}4、 ConverterFactory接口ConverterFactory的出现允许我们统一管理一些相关的Converter。现在,您可以为所有已实现BaseEnum枚举的ConverterFactory定义一个字符串,然后根据转换的目标类型生成相应的Converter。

原文链接:https://blog.csdn.net/u014527058/article/details/62883573

一、概述

在利用Spring进行Web后台开发时,经常会遇到枚举类型的绑定问题。一般情况下,如果Spring接收到的参数值为字符串类型,Spring会根据枚举的值与传入的字符串进行对应。假设有如下枚举

清单1:枚举定义

public enum Gender {
MALE, FEMALE;
}

那么,只要客户端在发送请求时,将参数的值设为MALE或FEMALE即可。请求类似如下形式:
http://localhost:8080/handle/enum?gender=MALE

但是,假如客户端传来的参数值不是枚举值对应的字符串,而是诸如整数值之类的值,Spring就没法做自动对应了。这种情况下该如何处理呢?

二、枚举与接口定义

好了,从现在开始,我们将使用如下枚举进行参数绑定。

清单2:需要进行转换的枚举定义

package org.fhp.springbootdemo.entity;

import java.util.HashMap;
import java.util.Map;

public enum Gender implements BaseEnum {
MALE(1), FEMALE(2);

private int value;
private static Map<Integer, Gender> valueMap = new HashMap<>();

static {
for(Gender gender : Gender.values()) {
valueMap.put(gender.value, gender);
}
}

Gender(int value) {
this.value = value;
}

@Override
public int getValue() {
return value;
}

public static Gender getByValue(int value) {
Gender result = valueMap.get(value);
if(result == null) {
throw new IllegalArgumentException("No element matches " + value);
}
return result;
}
}

在这里,我们令所有的枚举都实现BaseEnum接口,以便转换时使用。BaseEnum接口定义如下:
清单3:枚举所需的实现接口

package org.fhp.springbootdemo.entity;

public interface BaseEnum {
int getValue();
}

三、Converter接口

好在Spring为我们提供了一个类型自动转换接口Converter<S, T>,可以实现从一个Object转为另一个Object的功能。除了Converter接口之外,实现ConverterFactory接口和GenericConverter接口也可以实现我们自己的类型转换逻辑。

我们先来看一下Converter接口的定义:

清单4:Converter接口定义

public interface Converter<S, T> { 

T convert(S source); 

}

我们可以看到这个接口是使用了泛型的,第一个类型表示原类型,第二个类型表示目标类型,然后里面定义了一个convert方法,将原类型对象作为参数传入进行转换之后返回目标类型对象。当我们需要建立自己的converter的时候就可以实现该接口。
下面给出一个字符串转换为Gender枚举的converter实现。需要注意的是,在Spring MVC和Spring Boot中,由于从客户端接收到的请求都被视为String类型,所以只能用String转枚举的converter。

清单5:String转Gender的Converter实现

package org.fhp.springbootdemo.converter;


import org.springframework.core.convert.converter.Converter;


public class StringToGenderConverter implements Converter<String, Gender> {

    @Override
    public Gender convert(String source) {
        return Gender.getByValue(Integer.parseInt(source));
    }
}

四、ConverterFactory接口

ConverterFactory的出现可以让我们统一管理一些相关联的Converter。顾名思义,ConverterFactory就是产生Converter的一个工厂,确实ConverterFactory就是用来产生Converter的。我们先来看一下ConverterFactory接口的定义:

清单6:ConverterFactory的接口定义

public interface ConverterFactory<S, R> { 

<T extends R> Converter<S, T> getConverter(Class<T> targetType); 

}

我们可以看到ConverterFactory接口里面就定义了一个产生Converter的getConverter方法,参数是目标类型的class。我们可以看到ConverterFactory中一共用到了三个泛型,S、R、T,其中S表示原类型,R表示目标类型,T是类型R的一个子类。
可以看出,ConverterFactory相比ConvertFactory的好处在于,ConverterFactory可以将原类型转换成一组实现了相同接口类型的对象,而Converter则只能转换成一种类型。这样做的坏处在于,假如我们又定义了其他枚举,那么对于每一个枚举,我们都需要实现一个对应的Converter,十分的不方便。而有了ConverterFactory之后,事情就变得简单了不少。现在可以定义一个String到所有实现了BaseEnum的枚举的ConverterFactory,然后根据目标类型生成对应的Converter来进行转换操作。如清单7所示。有了ConverterFactory,就可以取代清单5中的Converter了。

清单7:ConverterFactory转换

package org.fhp.springbootdemo.converter;

import org.fhp.springbootdemo.entity.BaseEnum;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class UniversalEnumConverterFactory implements ConverterFactory<String, BaseEnum> {

private static final Map<Class, Converter> converterMap = new WeakHashMap<>();

@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
Converter result = converterMap.get(targetType);
if(result == null) {
result = new IntegerStrToEnum<T>(targetType);
converterMap.put(targetType, result);
}
return result;
}

class IntegerStrToEnum<T extends BaseEnum> implements Converter<String, T> {
private final Class<T> enumType;
private Map<String, T> enumMap = new HashMap<>();

public IntegerStrToEnum(Class<T> enumType) {
this.enumType = enumType;
T[] enums = enumType.getEnumConstants();
for(T e : enums) {
enumMap.put(e.getValue() + "", e);
}
}


@Override
public T convert(String source) {
T result = enumMap.get(source);
if(result == null) {
throw new IllegalArgumentException("No element matches " + source);
}
return result;
}
}
}

五、集成至Spring Boot

在Spring Boot中,可以通过覆盖addFormatter方法来实现对Converter和ConverterFactory的绑定。

清单8:在配置中绑定ConverterFactory

package org.fhp.springbootdemo;

import org.fhp.springbootdemo.converter.UniversalEnumConverterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {

@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new UniversalEnumConverterFactory());
}
}

当然,也可以通过registry.addConverter()方法来绑定Converter。
在Controller中,采用如下方式来进行接收,和平常接收参数是一样的用法。

清单9:在Controller中的用法

package org.fhp.springbootdemo.controller;

import org.fhp.springbootdemo.entity.Gender;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HandleEnumController {

@RequestMapping("/handle/enum")
public Object handleEnum(@RequestParam("gender") Gender gender) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("data", gender.name());
return dataMap;
}
}

免责声明:文章转载自《springboot mybatis自定义枚举enum转换》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇freeswitch官网最新版安装1.10.3Qt Meta Object System-元对象系统下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.NET MVC JSON JavaScriptSerializer 字符串的长度超过 maxJsonLength 值问题的解决

1 [ArgumentException: 使用 JSON JavaScriptSerializer 序列化或还原序列化期间发生错误。字符串的长度超过在 maxJsonLength 属性上设定的值。 2 参数名称: input] 3 System.Web.Script.Serialization.JavaScriptSerializer.Dese...

1.golang数据类型,转换,变量类型检查,生命周期、闭包,打印方法,指针简介

golang是强类型,静态语言 1.golang 数据类型 布尔类型 true/false var b bool ,在golang底层bool不是1/0表示的 数值类型 :var i int =3 / var i:=3 数字在计算机内部是以二进制的方式存储的,二进制位就是一系列布尔值,取值要么为1,要么为0. 1位表示1或0,对于4位整数可以表示16个不同...

Spring 框架的事务管理

1. Spring 框架的事务管理相关的类和API PlateformTransactionManager 接口: 平台事务管理器(真正管理事务的类); TransactionDefinition 接口: 事务定义信息(事务的隔离级别,传播行为,超时,只读等); TransactionStatus 接口: 事务的状态; 平台事务管理器真正管理事务对...

java生成解析xml的另外两种方法JAXB

   JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示...

Java之MyBatis

MyBatis中文文档:https://mybatis.org/mybatis-3/zh/index.htmlMyBatis是一款优秀的持久化框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动配置参数以及结果集。MyBatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO(Plain...

java中读取资源文件的方法

展开全部 1.使用java.util.Properties类的load()方法 示例: //文件在项目下。不是在包下!! InputStream in = new BufferedInputStream(new FileInputStream("demo.properties")) ;   Properties p = new Properties...