最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring MVC 更靈活的控制 json 返回問題(自定義過濾字段)

 更新時間:2017年02月15日 09:53:38   作者:DiamondFsd  
本篇文章主要介紹了Spring MVC 更靈活的控制 json 返回問題(自定義過濾字段),具有一定的參考價值,感興趣的小伙伴們可以參考一下。

這篇文章主要講 Spring MVC 如何動態(tài)的去返回 Json 數(shù)據(jù) 在我們做 Web 接口開發(fā)的時候, 經(jīng)常會遇到這種場景。

兩個請求,返回同一個對象,但是需要的返回字段并不相同。如以下場景

/**
* 返回所有名稱以及Id
*/
@RequestMapping("list")
@ResponseBody
public List<Article> findAllNameAndId() {
 return articleService.findAll();
}

/**
* 返回所有目錄詳情
*/
@RequestMapping("list-detail")
@ResponseBody
public List<Article> findAllDetail() {
 return articleService.findAll();
}

Spring MVC 默認(rèn)使用轉(zhuǎn)json框架是 jackson。 大家也知道, jackson 可以在實(shí)體類內(nèi)加注解,來指定序列化規(guī)則,但是那樣比較不靈活,不能實(shí)現(xiàn)我們目前想要達(dá)到的這種情況。

這篇文章主要講的就是通過自定義注解,來更加靈活,細(xì)粒化控制 json 格式的轉(zhuǎn)換。

最終我們需要實(shí)現(xiàn)如下的效果:

@RequestMapping(value = "{id}", method = RequestMethod.GET)
// 返回時候不包含 filter 內(nèi)的 createTime, updateTime 字段
@JSON(type = Article.class, filter="createTime,updateTime") 
public Article get(@PathVariable String id) {
  return articleService.get(id);
}
@RequestMapping(value="list", method = RequestMethod.GET)
// 返回時只包含 include 內(nèi)的 id, name 字段 
@JSON(type = Article.class , include="id,name")
public List<Article> findAll() {
  return articleService.findAll();
}

jackson 編程式過濾字段

jackson 中, 我們可以在實(shí)體類上加上 @JsonFilter 注解,并且通過 ObjectMapper.setFilterProvider 來進(jìn)行過濾規(guī)則的設(shè)置。 這里簡單介紹一下 setFilterProvider 的使用

@JsonFilter("ID-TITLE")
class Article {
 private String id;
 private String title;
 private String content;
 // ... getter/setter
}

// Demo
class Demo {
 public void main(String args[]) {
  ObjectMapper mapper = new ObjectMapper();
  // SimpleBeanPropertyFilter.filterOutAllExcept("id,title")
  // 過濾除了 id,title 以外的所有字段,也就是序列化的時候,只包含 id 和 title
  mapper.setFilterProvider(new SimpleFilterProvider().addFilter("ID-TITLE",
          SimpleBeanPropertyFilter.filterOutAllExcept("id,title"))); 

  String filterOut = mapper.writeValueAsString(new Article());

  mapper = new ObjectMapper();
  // SimpleBeanPropertyFilter.serializeAllExcept("id,title")
  // 序列化所有字段,但是排除 id 和 title,也就是除了 id 和 title之外,其他字段都包含進(jìn) json
  mapper.setFilterProvider(new SimpleFilterProvider().addFilter("ID-TITLE",
      SimpleBeanPropertyFilter.serializeAllExcept(filter.split("id,title"))));

  String serializeAll = mapper.writeValueAsString(new Article());

  System.out.println("filterOut:" + filterOut);
  System.out.println("serializeAll :" + serializeAll);  
 }
}

輸出結(jié)果

filterOut:{id: "", title: ""}
serializeAll:{content:""}

封裝json轉(zhuǎn)換

通過上面的代碼,我們發(fā)現(xiàn),可以使用 setFilterProvider 來靈活的處理需要過濾的字段。不過上面的方法還有一些缺陷就是,還是要在 原來的 model 上加注解,這里我們使用 ObjectMapper.addMixIn(Class<?> type, Class<?> mixinType) 方法,這個方法就是講兩個類的注解混合,讓第一個參數(shù)的類能夠擁有第二個參數(shù)類的注解。讓需要過濾的 model 和 @JsonFilter 注解解除耦合

package diamond.cms.server.json;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

/**
 * depend on jackson
 * @author Diamond
 */
public class CustomerJsonSerializer {

  static final String DYNC_INCLUDE = "DYNC_INCLUDE";
  static final String DYNC_FILTER = "DYNC_FILTER";
  ObjectMapper mapper = new ObjectMapper();

  @JsonFilter(DYNC_FILTER)
  interface DynamicFilter {
  }

  @JsonFilter(DYNC_INCLUDE)
  interface DynamicInclude {
  }

  /**
   * @param clazz 需要設(shè)置規(guī)則的Class
   * @param include 轉(zhuǎn)換時包含哪些字段
   * @param filter 轉(zhuǎn)換時過濾哪些字段
   */
  public void filter(Class<?> clazz, String include, String filter) {
    if (clazz == null) return;
    if (include != null && include.length() > 0) {
      mapper.setFilterProvider(new SimpleFilterProvider().addFilter(DYNC_INCLUDE,
          SimpleBeanPropertyFilter.filterOutAllExcept(include.split(","))));
      mapper.addMixIn(clazz, DynamicInclude.class);
    } else if (filter !=null && filter.length() > 0) {
      mapper.setFilterProvider(new SimpleFilterProvider().addFilter(DYNC_FILTER,
          SimpleBeanPropertyFilter.serializeAllExcept(filter.split(","))));
      mapper.addMixIn(clazz, DynamicFilter.class);
    }
  }

  public String toJson(Object object) throws JsonProcessingException {
    return mapper.writeValueAsString(object);
  }
}

我們之前的 Demo 可以變成:

// Demo
class Demo {
 public void main(String args[]) {
  CustomerJsonSerializer cjs= new CustomerJsonSerializer();
  // 設(shè)置轉(zhuǎn)換 Article 類時,只包含 id, name
  cjs.filter(Article.class, "id,name", null); 

  String include = cjs.toJson(new Article()); 

  cjs = new CustomerJsonSerializer();
  // 設(shè)置轉(zhuǎn)換 Article 類時,過濾掉 id, name
  cjs.filter(Article.class, null, "id,name"); 

  String filter = cjs.toJson(new Article());

  System.out.println("include: " + include);
  System.out.println("filter: " + filter);  
 }
}

輸出結(jié)果

include: {id: "", title: ""}
filter: {content:""}

自定義 @JSON 注解

我們需要實(shí)現(xiàn)文章開頭的那種效果。這里我自定義了一個注解,可以加在方法上,這個注解是用來攜帶參數(shù)給 CustomerJsonSerializer.filter 方法的,就是某個類的某些字段需要過濾或者包含。

package diamond.cms.server.json;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JSON {
  Class<?> type();
  String include() default "";
  String filter() default "";
}

實(shí)現(xiàn) Spring MVC 的 HandlerMethodReturnValueHandler

HandlerMethodReturnValueHandler 接口 Spring MVC 用于處理請求返回值 。 看一下這個接口的定義和描述,接口有兩個方法supportsReturnType 用來判斷 處理類 是否支持當(dāng)前請求, handleReturnValue 就是具體返回邏輯的實(shí)現(xiàn)。

 // Spring MVC 源碼
package org.springframework.web.method.support;

import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;

public interface HandlerMethodReturnValueHandler {

  boolean supportsReturnType(MethodParameter returnType);

  void handleReturnValue(Object returnValue, MethodParameter returnType,
      ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

我們平時使用 @ResponseBody 就是交給 RequestResponseBodyMethodProcessor 這個類處理的

還有我們返回 ModelAndView 的時候, 是由 ModelAndViewMethodReturnValueHandler 類處理的

要實(shí)現(xiàn)文章開頭的效果,我實(shí)現(xiàn)了一個 JsonReturnHandler類,當(dāng)方法有 @JSON 注解的時候,使用該類來處理返回值。

package diamond.cms.server.json.spring;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import diamond.cms.server.json.CustomerJsonSerializer;
import diamond.cms.server.json.JSON;

public class JsonReturnHandler implements HandlerMethodReturnValueHandler{

  @Override
  public boolean supportsReturnType(MethodParameter returnType) { 
    // 如果有我們自定義的 JSON 注解 就用我們這個Handler 來處理
    boolean hasJsonAnno= returnType.getMethodAnnotation(JSON.class) != null;
    return hasJsonAnno;
  }

  @Override
  public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest) throws Exception {
    // 設(shè)置這個就是最終的處理類了,處理完不再去找下一個類進(jìn)行處理
    mavContainer.setRequestHandled(true);

    // 獲得注解并執(zhí)行filter方法 最后返回
    HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
    Annotation[] annos = returnType.getMethodAnnotations();
    CustomerJsonSerializer jsonSerializer = new CustomerJsonSerializer();
    Arrays.asList(annos).forEach(a -> {
      if (a instanceof JSON) {
        JSON json = (JSON) a;
        jsonSerializer.filter(json.type(), json.include(), json.filter());
      }
    });

    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    String json = jsonSerializer.toJson(returnValue);
    response.getWriter().write(json);
  }
}

通過這些,我們就可以最終實(shí)現(xiàn)以下效果。

class Article {
 private String id;
 private String title;
 private String content;
 private Long createTime;
 // ... getter/setter
}

@Controller
@RequestMapping("article")
class ArticleController {
 @RequestMapping(value = "{id}", method = RequestMethod.GET)
 @JSON(type = Article.class, filter="createTime") 
 public Article get(@PathVariable String id) {
   return articleService.get(id);
 }

 @RequestMapping(value="list", method = RequestMethod.GET)
 @JSON(type = Article.class , include="id,title")
 public List<Article> findAll() {
   return articleService.findAll();
 }
}

請求 /article/{articleId}

{
  id: "xxxx",
  title: "xxxx",
  content: "xxxx"
}

請求 article/list

[ {id: "xx", title: ""}, {id: "xx", title: ""}, {id: "xx", title: ""} ... ]

下載地址:cms-admin-end_jb51.rar

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java Hibernate save()與persist()區(qū)別

    java Hibernate save()與persist()區(qū)別

    本文章來給各位同學(xué)介紹一下Hibernate save()與persist()區(qū)別,希望此文章能對各位同學(xué)對于Hibernate save()與persist()有所理解
    2016-01-01
  • 淺談web項(xiàng)目讀取classpath路徑下面的文件

    淺談web項(xiàng)目讀取classpath路徑下面的文件

    這篇文章主要介紹了淺談web項(xiàng)目讀取classpath路徑下面的文件,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • idea版本控制忽略.idea文件和.iml文件的問題

    idea版本控制忽略.idea文件和.iml文件的問題

    這篇文章主要介紹了idea版本控制忽略.idea文件和.iml文件,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • 實(shí)例講解Java中random.nextInt()與Math.random()的基礎(chǔ)用法

    實(shí)例講解Java中random.nextInt()與Math.random()的基礎(chǔ)用法

    今天小編就為大家分享一篇關(guān)于實(shí)例講解Java中random.nextInt()與Math.random()的基礎(chǔ)用法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • kotlin java 混合代碼 maven 打包實(shí)現(xiàn)

    kotlin java 混合代碼 maven 打包實(shí)現(xiàn)

    這篇文章主要介紹了kotlin java 混合代碼 maven 打包實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot Actuator未授權(quán)訪問漏洞修復(fù)詳解

    SpringBoot Actuator未授權(quán)訪問漏洞修復(fù)詳解

    這篇文章主要介紹了SpringBoot Actuator未授權(quán)訪問漏洞修復(fù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • java實(shí)現(xiàn)簡單銀行管理系統(tǒng)

    java實(shí)現(xiàn)簡單銀行管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • java幾種排序算法的實(shí)現(xiàn)及簡單分析

    java幾種排序算法的實(shí)現(xiàn)及簡單分析

    這篇文章主要介紹了java幾種排序算法的實(shí)現(xiàn)及簡單分析,實(shí)例分析了插入排序、希爾排序、選擇排序等常用排序算法,并分析了各個算法的優(yōu)劣,需要的朋友可以參考下
    2015-05-05
  • Java集合案例之斗地主游戲

    Java集合案例之斗地主游戲

    這篇文章主要為大家詳細(xì)介紹了Java集合案例之斗地主游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 解析JDK14中的java tools簡介

    解析JDK14中的java tools簡介

    這篇文章主要介紹了JDK14中的java tools簡介,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04

最新評論

蒲江县| 河西区| 寿阳县| 铜梁县| 阜新市| 大悟县| 亚东县| 洛扎县| 香港 | 平塘县| 林芝县| 札达县| 琼海市| 绍兴市| 定兴县| 达日县| 金沙县| 高青县| 奈曼旗| 册亨县| 诸暨市| 江口县| 平阳县| 旬邑县| 沂源县| 依安县| 南川市| 河北区| 井冈山市| 嵊泗县| 九龙城区| 永安市| 乐都县| 平湖市| 电白县| 临泽县| 定兴县| 宝应县| 大足县| 西乡县| 怀仁县|