springboot项目配置参数请求及返回均为下划线方式

450次阅读
没有评论

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

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 
评论(没有评论)