fastjson free: Specifies the active profile on the controller, so that what field you want to serialize serialize what field fastjson free: Specifies the active profile on the controller, so that what field you want to serialize what field you serialize

Excerpt: https://www.cnblogs.com/grey-wolf/p/11828582.html

fastjson free: Specifies the active profile on the controller, what makes you think what field to field serialization serialization

 

 

I. Introduction

Recently, a demand, in fact, this demand there before, such as the definition of a vo, contains 10 fields,

A interface where you want to return all of the fields;

However, the interface B in it, we need to reuse this vo, but only to return eight fields.

Could it be that some students will choose to redefine a new vo, but this will lead to a particularly large number of vo class; you said, if all the fields have returned it, it will give the students a front end causing distress.

For the need to exclude part of the field, hoping to achieve such results the following:

1, specifies a profile on the controller

2, the profile to be applied to the type of class, add annotations in the field

3, request interface, the returned results, as follows:

4, comment out the comment that if two lines, the effect is as follows:

For effect need only include part of the field, hoping to achieve the following:

1, designated profile on the controller

/**
     * 测试include类型的profile,这里指定了:
     * 激活profile为 includeProfile
     * User中,对应的field将会被序列化,其他字段都不会被序列化
     */
    @GetMapping("/test.do")
    @ActiveFastJsonProfileInController(profile = "includeProfile",clazz = User.class) public CommonMessage<User> test() { User user = new User(); user.setId(111L); user.setAge(8); user.setUserName("kkk"); user.setHeight(165); CommonMessage<User> message = new CommonMessage<>(); message.setCode("0000"); message.setDesc("成功"); message.setData(user); return message; }

2, in ActiveFastJsonProfileInControllerclazz annotation of the specified class, need be annotated sequence of fields:

@Data
public class User { @FastJsonFieldProfile(profiles = {"includeProfile"},profileType = FastJsonFieldProfileType.INCLUDE) private Long id; private String userName; private Integer age; @FastJsonFieldProfile(profiles = {"includeProfile"},profileType = FastJsonFieldProfileType.INCLUDE) private Integer height; }

3, the request results are as follows:

{
   code: "0000",
   data: {
       id: 111,
       height: 165
   },
   desc: "成功"
}

Second, the realization of ideas

Ideas are as follows:

  1. Custom annotations, the method is applied to the controller, to activate the specified Profile, and corresponding class
  2. During startup, the above analytical annotation information, construct the following map:
  3. Add controllerAdviceto realize org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvicethe interface, to return responseBodyprocessing
  4. In controllerAdvicethe acquisition request path, then the path according to a request, to map the second step, the query active profile and class information
  5. Acquired according to the fourth step: the active profile and class information set corresponding to the calculated field, for example, according to a profile field set to get: {name, age}, and exclude these two types of fields are so can not be serialized in front of two fields
  6. The field set in the fifth step, for responseBodythe object is processed, the field does not exclude the set of sequences

So speak up, it is quite abstract, concrete can see the effect of the first chapter of the screenshot.

Third, the implementation details

Use fastjson serialized

spring boot version 2.1.10, there are many online articles, said methods are time 1.x version, version 2.1 does not apply. Because the default is jackson, so order HttpMessageConverter of us will advance the fastjson:

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport { @Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { super.extendMessageConverters(converters); FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); Charset defaultCharset = Charset.forName("utf-8"); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setCharset(defaultCharset); converter.setFastJsonConfig(fastJsonConfig); converter.setDefaultCharset(defaultCharset); //将fastjson的消息转换器提到第一位 converters.add(0, converter); } }

Annotative information on the reading process controller, and configured to map

Here, the point is acquired RequestMappingurl the annotations, and custom annotations on the corresponding method:

RequestMappingHandlerMapping handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
//获取handlerMapping的map
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
for (HandlerMethod handlerMethod : handlerMethods.values()) {
    Class<?> beanType = handlerMethod.getBeanType();//获取所在类
    //获取方法上注解
    RequestMapping requestMapping = handlerMethod.getMethodAnnotation(RequestMapping.class);
}

Dynamic registration bean

After the map is constructed above, a per se can be saved directly to the public static field, but not very elegant feel, thus constructed a bean (containing the above-described map), registered to the spring:

//bean的类定义
@Data
public class VoProfileRegistry { private ConcurrentHashMap<String,ActiveFastJsonProfileInController> hashmap = new ConcurrentHashMap<String,ActiveFastJsonProfileInController>(); } //动态注册到spring applicationContext.registerBean(VoProfileRegistry.class); VoProfileRegistry registry = myapplicationContext.getBean(VoProfileRegistry.class); registry.setHashmap(hashmap);

In controllerAdvice in responseBody returned when processed according to the request url, from the above map, the acquired profile information:

org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#beforeBodyWrite

@Override
public CommonMessage<Object> beforeBodyWrite(CommonMessage<Object> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { String requestPath = request.getURI().getPath(); log.info("path:{}",requestPath); VoProfileRegistry voProfileRegistry = applicationContext.getBean(VoProfileRegistry.class); ConcurrentHashMap<String, ActiveFastJsonProfileInController> hashmap = voProfileRegistry.getHashmap(); //从map中获取该url,激活的profile等信息 ActiveFastJsonProfileInController activeFastJsonProfileInControllerAnnotation = hashmap.get(requestPath); if (activeFastJsonProfileInControllerAnnotation == null) { log.info("no matched json profile,skip"); return body; } ......//进行具体的对responseBody进行过滤 }

Fourth, the summary and source code

If you use fastjsonit, it is supported propertyFilterin particular can understand, but also on fields include and exclude, but the feeling is not particularly convenient, especially to support the size of the interface level.

Further, originally, I also have another scheme: In controllerAdvice where, after obtaining the set of fields to be excluded, provided to the ThreadLocal variable and modify fastjson source, (when fastjson to serialize it, to get the class field set be in that place, on the field collection process), but it, like a lot of trouble, even if the thought.

You have any comments and suggestions can be put are also welcome to add a group discussion.

Source code in the cloud (github too slow):

https://gitee.com/ckl111/json-profile

 

 

 

I. Introduction

Recently, a demand, in fact, this demand there before, such as the definition of a vo, contains 10 fields,

A interface where you want to return all of the fields;

However, the interface B in it, we need to reuse this vo, but only to return eight fields.

Could it be that some students will choose to redefine a new vo, but this will lead to a particularly large number of vo class; you said, if all the fields have returned it, it will give the students a front end causing distress.

For the need to exclude part of the field, hoping to achieve such results the following:

1, specifies a profile on the controller

2, the profile to be applied to the type of class, add annotations in the field

3, request interface, the returned results, as follows:

4, comment out the comment that if two lines, the effect is as follows:

For effect need only include part of the field, hoping to achieve the following:

1, designated profile on the controller

/**
     * 测试include类型的profile,这里指定了:
     * 激活profile为 includeProfile
     * User中,对应的field将会被序列化,其他字段都不会被序列化
     */
    @GetMapping("/test.do")
    @ActiveFastJsonProfileInController(profile = "includeProfile",clazz = User.class) public CommonMessage<User> test() { User user = new User(); user.setId(111L); user.setAge(8); user.setUserName("kkk"); user.setHeight(165); CommonMessage<User> message = new CommonMessage<>(); message.setCode("0000"); message.setDesc("成功"); message.setData(user); return message; }

2, in ActiveFastJsonProfileInControllerclazz annotation of the specified class, need be annotated sequence of fields:

@Data
public class User { @FastJsonFieldProfile(profiles = {"includeProfile"},profileType = FastJsonFieldProfileType.INCLUDE) private Long id; private String userName; private Integer age; @FastJsonFieldProfile(profiles = {"includeProfile"},profileType = FastJsonFieldProfileType.INCLUDE) private Integer height; }

3, the request results are as follows:

{
   code: "0000",
   data: {
       id: 111,
       height: 165
   },
   desc: "成功"
}

Second, the realization of ideas

Ideas are as follows:

  1. Custom annotations, the method is applied to the controller, to activate the specified Profile, and corresponding class
  2. During startup, the above analytical annotation information, construct the following map:
  3. Add controllerAdviceto realize org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvicethe interface, to return responseBodyprocessing
  4. In controllerAdvicethe acquisition request path, then the path according to a request, to map the second step, the query active profile and class information
  5. Acquired according to the fourth step: the active profile and class information set corresponding to the calculated field, for example, according to a profile field set to get: {name, age}, and exclude these two types of fields are so can not be serialized in front of two fields
  6. The field set in the fifth step, for responseBodythe object is processed, the field does not exclude the set of sequences

So speak up, it is quite abstract, concrete can see the effect of the first chapter of the screenshot.

Third, the implementation details

Use fastjson serialized

spring boot version 2.1.10, there are many online articles, said methods are time 1.x version, version 2.1 does not apply. Because the default is jackson, so order HttpMessageConverter of us will advance the fastjson:

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport { @Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { super.extendMessageConverters(converters); FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); Charset defaultCharset = Charset.forName("utf-8"); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setCharset(defaultCharset); converter.setFastJsonConfig(fastJsonConfig); converter.setDefaultCharset(defaultCharset); //将fastjson的消息转换器提到第一位 converters.add(0, converter); } }

Annotative information on the reading process controller, and configured to map

Here, the point is acquired RequestMappingurl the annotations, and custom annotations on the corresponding method:

RequestMappingHandlerMapping handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
//获取handlerMapping的map
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
for (HandlerMethod handlerMethod : handlerMethods.values()) {
    Class<?> beanType = handlerMethod.getBeanType();//获取所在类
    //获取方法上注解
    RequestMapping requestMapping = handlerMethod.getMethodAnnotation(RequestMapping.class);
}

Dynamic registration bean

After the map is constructed above, a per se can be saved directly to the public static field, but not very elegant feel, thus constructed a bean (containing the above-described map), registered to the spring:

//bean的类定义
@Data
public class VoProfileRegistry { private ConcurrentHashMap<String,ActiveFastJsonProfileInController> hashmap = new ConcurrentHashMap<String,ActiveFastJsonProfileInController>(); } //动态注册到spring applicationContext.registerBean(VoProfileRegistry.class); VoProfileRegistry registry = myapplicationContext.getBean(VoProfileRegistry.class); registry.setHashmap(hashmap);

In controllerAdvice in responseBody returned when processed according to the request url, from the above map, the acquired profile information:

org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#beforeBodyWrite

@Override
public CommonMessage<Object> beforeBodyWrite(CommonMessage<Object> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { String requestPath = request.getURI().getPath(); log.info("path:{}",requestPath); VoProfileRegistry voProfileRegistry = applicationContext.getBean(VoProfileRegistry.class); ConcurrentHashMap<String, ActiveFastJsonProfileInController> hashmap = voProfileRegistry.getHashmap(); //从map中获取该url,激活的profile等信息 ActiveFastJsonProfileInController activeFastJsonProfileInControllerAnnotation = hashmap.get(requestPath); if (activeFastJsonProfileInControllerAnnotation == null) { log.info("no matched json profile,skip"); return body; } ......//进行具体的对responseBody进行过滤 }

Fourth, the summary and source code

If you use fastjsonit, it is supported propertyFilterin particular can understand, but also on fields include and exclude, but the feeling is not particularly convenient, especially to support the size of the interface level.

Further, originally, I also have another scheme: In controllerAdvice where, after obtaining the set of fields to be excluded, provided to the ThreadLocal variable and modify fastjson source, (when fastjson to serialize it, to get the class field set be in that place, on the field collection process), but it, like a lot of trouble, even if the thought.

You have any comments and suggestions can be put are also welcome to add a group discussion.

Source code in the cloud (github too slow):

https://gitee.com/ckl111/json-profile

 

Guess you like

Origin www.cnblogs.com/xichji/p/11835753.html