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

springboot HandlerIntercepter攔截器修改request body數據的操作

 更新時間:2021年06月29日 09:07:05   作者:Skyler  
這篇文章主要介紹了springboot HandlerIntercepter攔截器修改request body數據的操作,具有很好的參考價值,希望對大家有所幫助。

實際工作中學習技術是最快、最深刻的。當然,自身的持續(xù)學習意識是必須的

技術棧版本:

spring boot 2.0.2

遇到事兒了

近來做業(yè)務需求,前端同學fe將userIduserName放到request header中了。

后端api接口要想使用userIduserName,每個接口都要從header中獲取。

試想一下,如果你有十個接口,那么每個接口都要寫一遍

Object.setUserId(request.getHeader("userId"))

正如下面代碼段

@RestController
@Validated
@RequestMapping("/template")
public class TemplateController {
    // 一個feign client
    @Autowired 
    TemplateClient templateClient
    @PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultVO create(@RequestBody @Valid TemplateParam param, HttpServletRequest request) {
        // 每個接口都要寫一遍setXXX()方法
        param.setUserId(request.getHeader("userId"));
        param.setUserName(request.getHeader("userName"));
        return templateClient.createTemplate(param).toResultVO();
    }
}   
@Data
public class TemplateParam{
    private Long templateId; 
    private Long userId;
    private String userName;
}

解決辦法

大家都知道的兩大利器,

tomcatFilterspringIntercepter(具體為HandlerIntercepter)

實現原理

具體方法為定義一個Filter實現類和一個HandlerIntercepter的實現類。再定義一個HttpServletRequest實現類,其作用分別為

Filter實現類:UserInfoFilter

創(chuàng)建一個入口,在這個入口中定義一個機會:將我們自定義的CustomHttpServletRequestWrapper代替HttpServletRequest隨著請求傳遞下去

HttpServletRequest實現類:customHttpServletRequestWrapper

因為HttpServletRequest對象的body數據只能get,不能set,即不能再次賦值。

而我們的需求是需要給HttpServletRequest賦值,所以需要定義一個HttpServletRequest實現類:customHttpServletRequestWrapper,這個實現類可以被賦值來滿足我們的需求。

HandlerIntercepter的實現類:CustomInterceptor

攔截請求,獲取接口方法相關信息(方法名,參數,返回值等)。從而實現統(tǒng)一的給request body動態(tài)賦值

實現思路如上所述,具體的實現代碼如下

代碼實現

聲明基礎bean: UserInfoParam

UserInfoParam:定義了包含userId,userName的實體bean,要想將用戶信息注入進入,需要入參對象XXXParam繼承UserInfoParam,攔截器中只處理@Requestbody中實現了UserInfoParam類的bean

如上文controllercreate方法的入參:TemplateParam,繼承UserInfoParam

@Data
public class TemplateParam extends UserInfoParam{
    private Long templateId; 
    // private Long userId;
    // private String userName;
}
@Data
public class UserInfoParam {
// 用戶id
private Long userId;
// 用戶名稱
private String userName;
}

定義Filter實現類: UserInfoFilter

@Slf4j
public class UserInfoFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        CustomHttpServletRequestWrapper customHttpServletRequestWrapper = null;
        try {
            HttpServletRequest req = (HttpServletRequest)request;
            customHttpServletRequestWrapper = new CustomHttpServletRequestWrapper(req);
        }catch (Exception e){
            log.warn("customHttpServletRequestWrapper Error:", e);
        }
        chain.doFilter((Objects.isNull(customHttpServletRequestWrapper) ? request : customHttpServletRequestWrapper), response);
    }
}

HttpServletRequest實現類:CustomHttpServletRequestWrapper

public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
    // 保存request body的數據
    private String body;
    // 解析request的inputStream(即body)數據,轉成字符串
    public CustomHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
            }
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;
    }
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
    public String getBody() {
        return this.body;
    }
    // 賦值給body字段
    public void setBody(String body) {
        this.body = body;
    }
}

HandlerIntercepter的實現類:CustomInterceptor

@Slf4j
public class CustomInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        pushUserInfo2Body(request, handlerMethod);
        return true;
    }
    private void pushUserInfo2Body(HttpServletRequest request, HandlerMethod handlerMethod) {
        try{
            String userId = request.getHeader("userId");
            String userName = request.getHeader("userName");
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if(ArrayUtils.isEmpty(methodParameters)) {
                return;
            }
            for (MethodParameter methodParameter : methodParameters) {
                Class clazz = methodParameter.getParameterType();
                if(ClassUtils.isAssignable(UserInfoParam.class, clazz)){
                    if(request instanceof CustomHttpServletRequestWrapper){
                        CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
                        String body = requestWrapper.getBody();
                        JSONObject param = JSONObject.parseObject(body);
                        param.put("userId", userId);
                        param.put("userName", Objects.isNull(userName) ? null : URLDecoder.decode(userName, "UTF-8"));
                        requestWrapper.setBody(JSON.toJSONString(param));
                    }
                }
            }
        }catch (Exception e){
            log.warn("fill userInfo to request body Error ", e);
        }
    }

定義Configuration class,增加攔截器和過濾器的配置

WebMvcConfigurer子類:CustomWebMvcConfigurer

@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        CustomInterceptor customInterceptor= new CustomInterceptor();
        registry.addInterceptor(customInterceptor);
    }
    @Bean
    public FilterRegistrationBean servletRegistrationBean() {
        UserInfoFilter userInfoFilter = new UserInfoFilter();
        FilterRegistrationBean<UserInfoFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(userInfoFilter);
        bean.setName("userInfoFilter");
        bean.addUrlPatterns("/*");
        bean.setOrder(Ordered.LOWEST_PRECEDENCE);
        return bean;
    }
}

到此,實現功能的代碼擼完了。啟動spring boot App,就可以curl訪問restful接口了

http訪問

curl -X POST \
  http://localhost:8080/template/create
  -H 'Content-Type: application/json'
  -H 'username: tiankong天空'
  -H 'userId: 11'
  -d '{
  "templateId": 1000}

效果

可以看到TemplateController.create(…)打出的信息,userIdusername的值正是header中傳的值

toDo

剩下的就看你的了,以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Mybatis查詢返回Map<String,Object>類型的實現

    Mybatis查詢返回Map<String,Object>類型的實現

    本文主要介紹了Mybatis查詢返回Map<String,Object>類型的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • 關于Idea使用git時commit特別慢的問題及解決方法

    關于Idea使用git時commit特別慢的問題及解決方法

    這篇文章主要介紹了關于Idea使用git時commit特別慢的問題及解決方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • IDEA中application.properties的圖標顯示不正常的問題及解決方法

    IDEA中application.properties的圖標顯示不正常的問題及解決方法

    這篇文章主要介紹了IDEA中application.properties的圖標顯示不正常的問題及解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • MybatisPlus 不修改全局策略和字段注解如何將字段更新為null

    MybatisPlus 不修改全局策略和字段注解如何將字段更新為null

    這篇文章主要介紹了MybatisPlus 不修改全局策略和字段注解如何將字段更新為null,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java實現瀏覽器大文件上傳的示例詳解

    Java實現瀏覽器大文件上傳的示例詳解

    文件上傳是許多項目都有的功能,用戶上傳小文件速度一般都很快,但如果是大文件幾個g,幾十個g的時候,上傳了半天,馬上就要完成的時候,網絡波動一下,文件又要重新上傳,所以本文給大家介紹了Java實現瀏覽器大文件上傳的示例,需要的朋友可以參考下
    2024-07-07
  • MyBatis配置與CRUD超詳細講解

    MyBatis配置與CRUD超詳細講解

    這篇文章主要介紹了MyBatis配置與CRUD,CRUD是指在做計算處理時的增加(Create)、讀取(Read)、更新(Update)和刪除(Delete)幾個單詞的首字母簡寫。CRUD主要被用在描述軟件系統(tǒng)中數據庫或者持久層的基本操作功能
    2023-02-02
  • javaweb實現投票系統(tǒng)

    javaweb實現投票系統(tǒng)

    這篇文章主要為大家詳細介紹了javaweb實現投票系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • 詳解Java中綴表達式的實現

    詳解Java中綴表達式的實現

    中綴表達式是一個通用的算術或邏輯公式表示方法。,中綴表達式不容易被計算機解析,但仍被許多程序語言使用,因為它符合人們的普遍用法。本文介紹了實現中綴表達式的方法,需要的可以參考一下
    2022-07-07
  • Spring如何解決單例bean線程不安全的問題

    Spring如何解決單例bean線程不安全的問題

    這篇文章主要介紹了Spring如何解決單例bean線程不安全的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • java的IO流詳細解讀

    java的IO流詳細解讀

    這篇文章主要介紹了java的IO流詳細解讀,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12

最新評論

潼南县| 逊克县| 佛坪县| 清徐县| 文昌市| 武川县| 沙洋县| 乌鲁木齐县| 庄河市| 宁化县| 常德市| 喜德县| 勐海县| 定兴县| 游戏| 潞城市| 调兵山市| 安岳县| 光泽县| 铁岭县| 边坝县| 湘潭县| 讷河市| 锦州市| 塘沽区| 延川县| 大理市| 蓬溪县| 渝中区| 万源市| 安溪县| 安国市| 大方县| 老河口市| 宁津县| 穆棱市| 武胜县| 成都市| 丰镇市| 定日县| 龙泉市|