1.请求参数为下划线
下划线方式参数请求,使用对象接收,则需要进行下划线转驼峰处理:
注意:请求接口不可使用@ModelAttribute接收对象,其原理和@RequestParam(“userId”)相同,请求参数根据后台所定义的接收参数名一致,不会进行驼峰转换处理。
1.自定义参数转换类,重写ServletRequestDataBinder中addBindValues方法,对参数进行处理
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.web.bind.ServletRequestDataBinder;
import javax.servlet.ServletRequest;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- 自定义CustomServletRequestDataBinder类,继承ServletRequestDataBinder,
- 重写addBindValues方法,将入参通过underLineToCamel方法进行转换处理
* - @author Tom
- @date 2021-07-23
*/
public class CustomServletRequestDataBinder extends ServletRequestDataBinder { private final Pattern underLinePattern = Pattern.compile(“_(\w)”); public CustomServletRequestDataBinder(final Object target) {
super(target);
} /**- 遍历请求参数对象 把请求参数的名转换成驼峰体,重写addBindValues绑定数值的方法
- @param mpvs 请求参数列表
- @param request 请求
*/
@Override
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
List pvs = mpvs.getPropertyValueList();
List adds = new LinkedList<>();
for (PropertyValue pv : pvs) {
String name = pv.getName();
String camel = this.underLineToCamel(name);
if (!name.equals(camel)) {
adds.add(new PropertyValue(camel, pv.getValue()));
}
}
pvs.addAll(adds);
}
/**
- 下划线转驼峰方法(如: 把app_id转换成appId)
- @param value 要转换的下划线字符串
- @return 驼峰体字符串
*/
private String underLineToCamel(final String value) {
final StringBuffer sb = new StringBuffer();
Matcher m = this.underLinePattern.matcher(value);
while (m.find()){
m.appendReplacement(sb, m.group(1).toUpperCase());
}
m.appendTail(sb);
return sb.toString();
}
}
2.自定义属性处理器CustomServletModelAttributeMethodProcessor,继承ServletModelAttributeMethodProcessor重写bindRequestParameters方法,将bind方法替换为我们自定义的CustomServletRequestDataBinder
import org.springframework.util.Assert;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;
import javax.servlet.ServletRequest;
/**
- 自定义属性处理器: CustomServletModelAttributeMethodProcessor
- 继承ServletModelAttributeMethodProcessor类,重写bindRequestParameters方法,
- 将bind方法替换为我们自定义的CustomServletRequestDataBinder
* - @author Tom
- @date 2021-07-23
*/
public class CustomServletModelAttributeMethodProcessor extends ServletModelAttributeMethodProcessor { public CustomServletModelAttributeMethodProcessor(final boolean annotationNotRequired) {
super(annotationNotRequired);
} @Override
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
Assert.state(servletRequest != null, “No ServletRequest”);
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
/**
* ServletModelAttributeMethodProcessor此处使用的servletBinder.bind(servletRequest)
* 修改的目的是为了将ServletRequestDataBinder换成自定的CustomServletRequestDataBinder
*/
new CustomServletRequestDataBinder(servletBinder.getTarget()).bind(servletRequest);
}
}
3.实现WebMvcConfigurer类,重写addArgumentResolvers方法,引入CustomServletModelAttributeMethodProcessor
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.xiaomi.config.request.CustomServletModelAttributeMethodProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
- 添加自定义拦截器,消息转换器等
* - @Author Tom
- @Date 2021-07-22
- @Description 实现WebMvcConfigurer接口
*/
@Configuration
public class WebConfig implements WebMvcConfigurer { /**- 配置入参转换器 – 重写HTTP请求参数转换规则(前端请求参数为下划线类型,自动转换为驼峰形式进行对象参数封装)
- @param resolvers
*/
@Override
public void addArgumentResolvers(List resolvers) {
resolvers.add(new CustomServletModelAttributeMethodProcessor(true));
}
}2.返回参数将驼峰转换为下划线
使用Jackson方式处理:
方式一:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
- 解决前端和后台交互过程中时间格式问题,比如LocalDateTime中带”T的问题”
* - @author Tom
- @date 2021-07-22
*/
@Configuration
@ConditionalOnClass({ObjectMapper.class})
@AutoConfigureBefore({JacksonAutoConfiguration.class})
public class JacksonConfig { public JacksonConfig() {
} @Bean
public ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(“yyyy-MM-dd”)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(“HH:mm:ss”)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(“yyyy-MM-dd”)));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(“HH:mm:ss”)));
objectMapper.registerModule(javaTimeModule);
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);//对于fastjson缺省使用SnakeCase策略(统一对象参数下划线形式)
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return objectMapper;
}
}
上面代码中,为我本地配置的JacksonConfig,其中将对象参数驼峰形式转换为下划线的代码仅一句:
PS:由于Jackson本身已经封装好,所以需要情况下直接配置即可
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);//对于fastjson缺省使用SnakeCase策略(统一对象参数下划线形式)
方式二:
在配置文件中修改:
spring:
application:
name:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
property-naming-strategy: SNAKE_CASE #对于fastjson缺省使用SnakeCase策略(统一对象参数下划线形式)
property-naming-strategy: SNAKE_CASE
fastjson缺省使用四种策略:
属性名策略说明:
CamelCase策略,Java对象属性:personId,序列化后属性:persionId
PascalCase策略,Java对象属性:personId,序列化后属性:PersonId
SnakeCase策略,Java对象属性:personId,序列化后属性:person_id
KebabCase策略,Java对象属性:personId,序列化后属性:person-id