成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

借一古老技術考察你對SpringBoot掌握程度

開發 前端
我們的服務端又該實現呢?直接在對應的接口中進行修改嗎?如果直接修改接口,那么當我又希望返回的是數據又該如何,重新再來一個接口嗎?

環境:Spring3.2.5

本篇文章將通過一個古老的技術JSONP來考察在座的對SpringBoot中某些技術的掌握程度。

1. 簡介

JSONP(JSON with Padding)是一種非官方的協議,主要用于解決瀏覽器跨域數據訪問的問題。它利用HTML的<script>標簽可以跨域加載資源的特性,通過服務器端生成包含JSON數據的JavaScript函數調用,并返回給客戶端執行??蛻舳诵枰A先定義好回調函數,以便在數據加載完畢后接收并處理數據。JSONP簡單易用,但僅支持GET請求,且存在安全風險,如XSS攻擊和CSRF攻擊。隨著技術的發展,CORS等更安全的跨域解決方案逐漸取代了JSONP。

關于JSONP的應用示例

現有如下接口地址:http://localhost:9100/jsonps,返回數據如下:

[{"id":1,"name":"張三"},{"id":2,"name":"李四"},{"id":3,"name":"王五"}]

JSONP需要我們傳遞一個類似回調的參數,服務端拿到值后會將最終的響應數據拼接成javascript函數調用的形式,如下:

<script src="http://localhost:9100/jsonps?callback=getUsers"></script>

通過<script>標簽引用上面的即可地址,同時傳遞了callback參數,當請求到達服務端后會拿到callback參數對應的getUsers值,與真正的數據做拼接,如下:

getUsers([{"id":1,"name":"張三"},{"id":2,"name":"李四"},{"id":3,"name":"王五"}]);

上面將是服務端響應的最終結果。這就是javascript函數的調用,我們只要保證前端頁面中有getUsers函數即可,它會自動的執行該函數。

以上就是JSONP實現的基本原理。

思考:我們的服務端又該實現呢?直接在對應的接口中進行修改嗎?如果直接修改接口,那么當我又希望返回的是數據又該如何,重新再來一個接口嗎?

接下來我們通過HttpMessageConverter和ResponseBodyAdvice來實現即支持原始數據又支持JSONP格式的數據響應。

2. 實戰案例

2.1 Rest接口定義

@RestController
@RequestMapping(("/jsonps"))
public class JsonpController {
  
  static List<User> DATAS = List.of(new User(1L, "張三"), new User(2L, "李四"), new User(3L, "王五")) ;
  
  @GetMapping("")
  public List<User> queryUsers() {
    return DATAS ;
  }
}

接口非常簡單直接返回List集合。

2.2 自定義JSON包裝器

public class JsonpMappingJacksonValue extends MappingJacksonValue {


  private String jsonpFunction ;
  
  public JsonpMappingJacksonValue(Object value) {
    super(value);
  }
  // getters, setters
}

該類繼承了MappingJacksonValue,同時增加了jsonpFunction的屬性,后面會根據該屬性是否有值對結果進行處理,如果沒有值則原始返回。而MappingJacksonValue類的作用就是一個POJO序列化到JSON時提供額外的序列號指令。

SpringBoot默認響應JSON數據是通過MappingJackson2HttpMessageConverter類,在該類中的writeInternal方法中會判斷當前輸出的值是否是MappingJacksonValue,如果是最終也會獲取其中的Value進行輸出客戶端的。

2.3 自定義ResponseBodyAdvice

@ControllerAdvice
public class JsonpControllerAdvice implements ResponseBodyAdvice<Object> {


  // 參數值必須滿足該正則
  private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
  // 參數名稱默認callback,你也可以通過配置方式設置
  private String jsonpQueryParamName = "callback" ;
  
  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    // 只要轉換器是jackson(json數據輸出)
    // 當然你也可以自定義實現,比如:方法上有具體的某個注解等
    return AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converterType);
  }
  @Override
  public Object beforeBodyWrite(
      Object body, MethodParameter returnType, 
      MediaType selectedContentType,
      Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
      ServerHttpResponse response) {
    // 創建MappingJacksonValue對象(包裝原始的數據)
    JsonpMappingJacksonValue container = this.getOrCreateContainer(body) ;
    // 取得請求的callback參數值
    HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest() ;
    String value = servletRequest.getParameter(jsonpQueryParamName) ;
    // 如果不存在直接返回,不做任何處理
    if (value != null) {
      // 不滿足條件也直接返回
      if (!CALLBACK_PARAM_PATTERN.matcher(value).matches()) {
        return container ;
      }
      // 設置響應頭為:application/javascript;charset=utf-8
      MediaType contentTypeToUse = new MediaType("application", "javascript", StandardCharsets.UTF_8) ;
      response.getHeaders().setContentType(contentTypeToUse) ;
      // 設置jsonp函數名,后面就會根據該值判斷是否要進行處理
      container.setJsonpFunction(value) ;
    }
    return container ;
  }
  // ...
}

自定義ResponseBodyAdvice的作用是將返回客戶端的數據包裝為MappingJacksonValue對象,然后設置jsonp會調用函數名。

接下來就是最重要的,如何在寫入客戶端時,將數據改造成JSONP所需要的格式。

2.4 重寫HttpMessageConverter

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
  MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter() {
    protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
      // 我們上面設置的值在這里用上了,關鍵就在該值是否有
      // 只有有值的情況下我們才會進行JSONP的處理
      String jsonpFunction =
          (object instanceof JsonpMappingJacksonValue ? ((JsonpMappingJacksonValue) object).getJsonpFunction() : null);
      if (jsonpFunction != null) {
        generator.writeRaw("/**/");
        generator.writeRaw(jsonpFunction + "(");
      }
    }
    protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
      String jsonpFunction =
          (object instanceof JsonpMappingJacksonValue ? ((JsonpMappingJacksonValue) object).getJsonpFunction() : null);
      if (jsonpFunction != null) {
        generator.writeRaw(");") ;
      }
    }
  } ;
  return converter ;
}

在這里我們自定義了MappingJackson2HttpMessageConverter 的writePrefix和writeSuffix方法,這兩個方法都進行判斷,如果期望輸出的是JSONP格式才會進行數據處理。

到此就完成了所有處理過程,每一步你都懂嗎?

說明:本篇文章不是教你實現JSONP這個技術并使用它,JSONP本就是用來解決跨域的問題,我用CORS技術不比它簡單,安全。這里只是借用這個JSONP來檢驗你對其它知識的掌握程度。

驗證上面的代碼

不使用callback參數請求

圖片圖片

使用callback參數請求

圖片圖片

成功,當你的頁面中有getUsers方法時,會自動調用getUsers方法。

通過HTML頁面進行測試

<html>
  <head>
    <script>
      function getUsers(users) {
        alert(JSON.stringify(users))
      }
    </script>
    <script src="http://localhost:9100/jsonps?callback=getUsers"></script>
  </head>
</html>

訪問上面的頁面,輸出結果:

圖片 圖片

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2024-11-01 08:34:18

Spring配置@Bean

2015-09-15 09:50:12

2020-11-09 07:25:20

函數 JavaScript數據

2021-10-21 08:13:11

Springboot

2020-12-10 11:00:37

JavaJVM命令

2018-02-08 10:47:19

存儲技術列存儲

2025-05-21 09:32:28

2015-09-29 09:24:22

Node.js面試題

2023-03-23 08:11:59

2018-02-02 16:41:01

程序員編程Web

2020-05-06 14:54:59

技術人工智能大數據

2024-04-12 09:01:08

2023-10-24 11:44:21

2022-02-18 07:32:13

Linux項目代碼

2019-09-29 15:30:58

JavaScript框架V8

2010-08-04 15:01:00

2016-12-26 16:34:41

技術

2019-04-03 15:07:11

便利店物聯網傳感器

2020-02-03 13:55:49

技術研發指標

2022-07-24 09:56:40

大數據技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲视频三区 | 蜜桃av鲁一鲁一鲁一鲁 | 亚洲网在线 | 日韩图区 | 亚洲国产一 | 久久精品无码一区二区三区 | 欧美黄色一区 | 日韩在线免费播放 | 欧美人成在线视频 | 中文字幕欧美一区二区 | 亚洲国产成人精品久久久国产成人一区 | 精品国产欧美日韩不卡在线观看 | 久久久精 | 日韩视频一区在线观看 | 日韩欧美精品 | 涩涩操 | 成年人黄色一级毛片 | 亚洲精品福利在线 | 日韩精品二区 | 国产91在线视频 | 成人久久网 | 精品国产一区二区三区性色 | 国产二区在线播放 | www四虎com | 国产www在线 | 久久国产欧美日韩精品 | 啪啪综合网 | 狠狠色综合网站久久久久久久 | 91最新视频 | 欧美日韩亚洲国产 | 欧美乱码精品一区二区三区 | 一区二区三区播放 | 欧美一级毛片在线播放 | 黄网站免费在线 | 国产极品粉嫩美女呻吟在线看人 | 91九色在线观看 | 国产在线97 | 国产传媒在线播放 | 国产福利在线看 | 国产精品久久久久久久久久久久久久 | 在线免费观看毛片 |