Java如何替換RequestBody和RequestParam參數(shù)的屬性
本文主要講解在Java環(huán)境中如何替換RequestBody和RequestParam參數(shù)中的屬性
背景
近期由于接手的老項目中存在所有接口中新增一個加密串來給接口做一個加密效果(項目歷史原因,不方便上Jwt授權(quán)這套),所以就研究了一下Http請求鏈路,發(fā)現(xiàn)可以通過 javax.servlet.Filter去實現(xiàn)
替換RequestParam參數(shù)
首先通過繼續(xù)HttpServletRequestWrapper來達到獲取和替換RequestParam中的參數(shù)信息,接下來我們通過javax.servlet.Filter去獲取ServletRequest中參數(shù)的信息,并且定義對應規(guī)則,來實現(xiàn)替換參數(shù)
代碼示例:
package com.simplemessage.cloudpayservice.infrastructure.config.http;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
/**
* @CreateAt: 2023/10/24 12:13
* @ModifyAt: 2023/10/24 12:13
* @Version 1.0
*/
public class MyRequestWrapper extends HttpServletRequestWrapper {
private Map params = new HashMap<>();
public MyRequestWrapper(HttpServletRequest request, Map newParams) {
super(request);
if(request.getParameterMap() != null){
this.params.putAll(request.getParameterMap());
}
if(newParams != null){
this.params.putAll(newParams);
}
}
/**
* 獲取參數(shù)
* @return
*/
@Override
public Map getParameterMap() {
return params;
}
@Override
public Enumeration getParameterNames() {
Vector l = new Vector(params.keySet());
return l.elements();
}
@Override
public String[] getParameterValues(String name) {
Object v = params.get(name);
if (v == null) {
return null;
} else if (v instanceof String[]) {
return (String[]) v;
} else if (v instanceof String) {
return new String[]{(String) v};
} else {
return new String[]{v.toString()};
}
}
/**
* 根據(jù)參數(shù)的key獲取參數(shù)
* @param name
* @return
*/
@Override
public String getParameter(String name) {
Object v = params.get(name);
if (v == null) {
return null;
} else if (v instanceof String[]) {
String[] strArr = (String[]) v;
if (strArr.length > 0) {
return strArr[0];
} else {
return null;
}
} else if (v instanceof String) {
return (String) v;
} else {
return v.toString();
}
}
}package com.simplemessage.cloudpayservice.infrastructure.config.http;
import com.fasterxml.jackson.core.io.JsonEOFException;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.RequestFacade;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @CreateAt: 2023/10/24 12:16
* @ModifyAt: 2023/10/24 12:16
* @Version 1.0
*/
@Slf4j
@Component
@WebFilter(filterName = "replaceGetRequestFilter", urlPatterns = {"/*"})
public class ReplaceGetRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
long start = System.currentTimeMillis();
//獲取HttpServletRequest對象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
//判斷當前是否為Get請求
if ("GET".equalsIgnoreCase(httpServletRequest.getMethod())) {
// 獲取參數(shù)信息
String param= request.getParameter("param");
//判斷參數(shù)是否為空,為空則放行
if (StringUtils.isEmpty(param)) {
chain.doFilter(request, response);
return;
} else {
Map<String, String[]> newParameterMap = new HashMap<>();
// 替換參數(shù)(自定義規(guī)則)
String newParama="test";
newParameterMap.put("param", newParama);
// 實現(xiàn)參數(shù)替換
MyRequestWrapper myRequestWrapper = new MyRequestWrapper(httpServletRequest, newParameterMap);
chain.doFilter(myRequestWrapper, response);
}
} else {
try {
chain.doFilter(request, response);
} catch (HttpMessageNotReadableException httpMessageNotReadableException) {
log.error(((RequestFacade) request).getRequestURI() + ", " + httpMessageNotReadableException.getMessage());
} catch (JsonEOFException jsonEOFException) {
log.error(((RequestFacade) request).getRequestURI() + ", " + jsonEOFException.getMessage());
}
}
long end = System.currentTimeMillis();
log.info("{} 接口耗時:{} ms", httpServletRequest.getRequestURI(), (end - start));
}
@Override
public void destroy() {
}
}
替換RequestBody參數(shù)
主要思路就是通過獲取Post中請求的輸入流信息,解析輸入流信息,按照對應的規(guī)則進行替換參數(shù)信息,最后將對應的流信息包裝進行返回
代碼示例:
package com.simplemessage.cloudpayservice.infrastructure.config.http;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;
/**
* @version 1.0
* @createAt: 2023/10/24 12:23:23
* @modifyAt: 2023/10/24 12:23:23
*/
@RestControllerAdvice
@Slf4j
public class DecryptRequestBodyHandler implements RequestBodyAdvice {
/**
* 該方法用于判斷當前請求,是否要執(zhí)行beforeBodyRead方法
* methodParameter方法的參數(shù)對象
* type方法的參數(shù)類型
* aClass 將會使用到的Http消息轉(zhuǎn)換器類類型
* 注意:此判斷方法,會在beforeBodyRead 和 afterBodyRead方法前都觸發(fā)一次。
* @return 返回true則會執(zhí)行beforeBodyRead
*/
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
/**
* 在Http消息轉(zhuǎn)換器執(zhí)轉(zhuǎn)換,之前執(zhí)行
* inputMessage 客戶端請求的信息
* parameter 參數(shù)信息
* targetType 參數(shù)類型
* converterType Http消息轉(zhuǎn)換器類類型
*
* @return 返回 一個自定義的HttpInputMessage
*/
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
// 如果body是空內(nèi)容直接返回原來的請求
if (inputMessage.getBody().available() <= 0) {
return inputMessage;
}
// 請求中的header信息
HttpHeaders headers = inputMessage.getHeaders();
// 將輸入流讀出來,注意 body 里面的流只能讀一次
ByteArrayOutputStream requestBodyDataByte = new ByteArrayOutputStream();
try {
//復制流信息
IOUtils.copy(inputMessage.getBody(), requestBodyDataByte);
} catch (Exception e) {
log.error("參數(shù)流拷貝失敗: ", e.toString());
return inputMessage;
}
ByteArrayOutputStream requestBodyDataByteNew = null;
try {
JSONObject body = JSON.parseObject(requestBodyDataByte.toByteArray(), JSONObject.class);
if (ObjectUtils.isEmpty(body)) {
return inputMessage;
}
//自定義規(guī)則西悉尼
if (body.containsKey("param")) {
String custId = body.getString("param");
String newParam="";
body.put("custId", newParam);
requestBodyDataByteNew = new ByteArrayOutputStream();
//拷貝流信息
IOUtils.copy(new ByteArrayInputStream(body.toJSONString().getBytes()), requestBodyDataByteNew);
}
} catch (Throwable e) {
log.error("流轉(zhuǎn)換異常 ", e.toString());
}
// 如果上述發(fā)生異常,仍然使用原來的請求內(nèi)容
requestBodyDataByte = requestBodyDataByteNew != null ? requestBodyDataByteNew : requestBodyDataByte;
InputStream rawInputStream = new ByteArrayInputStream(requestBodyDataByte.toByteArray());
inputMessage.getHeaders().set(HttpHeaders.CONTENT_LENGTH, String.valueOf(rawInputStream.available()));
return new HttpInputMessage() {
@Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
@Override
public InputStream getBody() throws IOException {
return rawInputStream;
}
};
}
/**
* 在Http消息轉(zhuǎn)換器執(zhí)轉(zhuǎn)換,之后執(zhí)行
* body 轉(zhuǎn)換后的對象
* inputMessage 客戶端的請求數(shù)據(jù)
* parameter handler方法的參數(shù)類型
* targetType handler方法的參數(shù)類型
* converterType 使用的Http消息轉(zhuǎn)換器類類型
*
* @return 返回一個新的對象
*/
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
/**
* 參數(shù)與afterBodyRead相同,不過這個方法body為空的情況
*/
@Override
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
}
到此這篇關(guān)于Java替換RequestBody和RequestParam參數(shù)的屬性的文章就介紹到這了,更多相關(guān)Java替換RequestBody和RequestParam參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實現(xiàn)MapperScan添加動態(tài)配置(占位符)
這篇文章主要介紹了SpringBoot實現(xiàn)MapperScan添加動態(tài)配置(占位符),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01
MyBatis-Plus攔截器對敏感數(shù)據(jù)實現(xiàn)加密
做課程項目petstore時遇到需要加密屬性的問題,而MyBatis-Plus為開發(fā)者提供了攔截器的相關(guān)接口,本文主要介紹通過MyBatis-Plus的攔截器接口自定義一個攔截器類實現(xiàn)敏感數(shù)據(jù)如用戶密碼的加密功能,感興趣的可以了解一下2021-11-11
RocketMQ特性Broker存儲事務消息實現(xiàn)
這篇文章主要為大家介紹了RocketMQ特性Broker存儲事務消息實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08
spring和quartz整合,并簡單調(diào)用(實例講解)
下面小編就為大家?guī)硪黄猻pring和quartz整合,并簡單調(diào)用(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07

