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

Springboot應(yīng)用中過濾器如何修改response的header和body內(nèi)容

 更新時間:2023年07月19日 10:06:08   作者:彼岸花@開  
這篇文章主要介紹了Springboot應(yīng)用中過濾器如何修改response的header和body內(nèi)容問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Springboot過濾器修改response的header和body內(nèi)容

springboot添加過濾器,繼承Filter接口,實現(xiàn)doFilter方法

方法一,實現(xiàn)類增加注解@WebFilter,注解參數(shù)filterName表示過濾器名稱,urlPatterns表示要過濾的url路徑,在啟動類增加注解@ServletComponentScan,表示能掃描到該類。

當(dāng)有多個過濾器時,通過注解@Order,注解參數(shù)大小表示過濾器執(zhí)行的縣厚順序,越小越先執(zhí)行

@WebFilter(filterName = "responseFilter",urlPatterns = "/*")
public class ResponseFilter implements Filter

方法二,創(chuàng)建新配置類,添加 @Configuration 注解,將自定義Filter加入過濾鏈。

@Configuration
public class DefinedFilterConfig {
? ? @Bean
? ? public FilterRegistrationBean responseFilter() {
? ? ? ? FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
? ? ? ? ResponseFilter responseFilter = new ResponseFilter();
? ? ? ? filterRegistrationBean.setFilter(responseFilter);
? ? ? ? filterRegistrationBean.addUrlPatterns("/*");//配置過濾規(guī)則
? ? ? ? filterRegistrationBean.setName("responseFilter");//設(shè)置過濾器名稱
? ? ? ? filterRegistrationBean.setOrder(1);//執(zhí)行次序
? ? ? ? return filterRegistrationBean;
? ? }
}

springboot在response中添加或者修改header

分兩種情況

  • 情況1,在chain.doFilter(servletRequest, servletResponse)代碼之前
servletResponse.addHeader("XXX", "xxxx");

或者

servletResponse.setHeader("XXX", "xxxx");

兩者的區(qū)別是addHeader不會覆蓋,只會追加,會照成headerName重名

setHeader會覆蓋重名的headerName

這樣是可以添加成功

  • 情況2,在chain.doFilter(servletRequest, servletResponse)代碼之后

添加addHeader或者serHeader無效,是因為這和過濾器的處理流程以及對header的處理時機(jī)有關(guān)

首先過濾器鏈的處理流程是:進(jìn)入到一個過濾器的doFitler方法中,處理一些邏輯,然后調(diào)用chain.doFilter(request, httpServletResponse);進(jìn)入到過濾器鏈的下一個過濾器的doFilter方法中.當(dāng)在過濾器鏈上最后一個過濾器的doFilter方法中調(diào)用chain.doFilter(request, httpServletResponse);時,將會把請求轉(zhuǎn)發(fā)到Servlet中,再分配到對應(yīng)的Controller的方法中。當(dāng)從Controller的方法中退出,再回到最后一個過濾器的doFilter方法中之前,就將會把respone對象上的header寫入到headerBuffer中。

所以,在chain.doFilter()方法之后,一方面是給response對象設(shè)置header不會成功,因為發(fā)現(xiàn)response對象的狀態(tài)已經(jīng)是commited狀態(tài),就不會再寫入到headers里,另一方面,即便通過反射的方式寫入了,也不會輸出給客戶端,因為headers已經(jīng)處理過了。

springboot在response中修改body

spring提供了HttpServletResponse的包裝類HttpServletResponseWrapper

首先需要繼承該包裝類,生成自定義包裝類BodyCachingHttpServletResponseWrapper

public class BodyCachingHttpServletResponseWrapper extends HttpServletResponseWrapper {
? ? private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
? ? private HttpServletResponse response;
? ? private PrintWriter pwrite;
? ? public BodyCachingHttpServletResponseWrapper(HttpServletResponse response) {
? ? ? ? super(response);
? ? ? ? this.response = response;
? ? }
? ? public byte[] getBytes() {
? ? ? ? if(pwrite != null) {
? ? ? ? ? ? pwrite.close();
? ? ? ? ? ? return byteArrayOutputStream.toByteArray();
? ? ? ? }
? ? ? ? if(byteArrayOutputStream != null) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? byteArrayOutputStream.flush();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return byteArrayOutputStream.toByteArray();
? ? }
? ? @Override
? ? public ServletOutputStream getOutputStream() {
? ? ? ? return new ServletOutputStreamWrapper(this.byteArrayOutputStream , this.response);
? ? }
? ? @Override
? ? public PrintWriter getWriter() throws IOException {
? ? ? ? pwrite = new PrintWriter(new OutputStreamWriter(this.byteArrayOutputStream , this.response.getCharacterEncoding()));
? ? ? ? return pwrite;
? ? }
? ? private static class ServletOutputStreamWrapper extends ServletOutputStream {
? ? ? ? private ByteArrayOutputStream outputStream;
? ? ? ? private HttpServletResponse response;
? ? ? ? public ServletOutputStreamWrapper(ByteArrayOutputStream outputStream, HttpServletResponse response) {
? ? ? ? ? ? super();
? ? ? ? ? ? this.outputStream = outputStream;
? ? ? ? ? ? this.response = response;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean isReady() {
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void setWriteListener(WriteListener listener) {
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void write(int b) throws IOException {
? ? ? ? ? ? this.outputStream.write(b);
? ? ? ? }
// ? ? ? ?@Override
// ? ? ? ?public void flush() throws IOException {
// ? ? ? ? ? ?if (! this.response.isCommitted()) {
// ? ? ? ? ? ? ? ?byte[] body = this.outputStream.toByteArray();
// ? ? ? ? ? ? ? ?ServletOutputStream outputStream = this.response.getOutputStream();
// ? ? ? ? ? ? ? ?outputStream.write(body);
// ? ? ? ? ? ? ? ?outputStream.flush();
// ? ? ? ? ? ?}
// ? ? ? ?}
? ? }

然后通過過濾器,將自定義包裝類BodyCachingHttpServletResponseWrappe傳遞到chain.doFilter(servletRequest, bodyCachingHttpServletResponseWrapper ),通過bodyCachingHttpServletResponseWrapper .getBytes()方式獲得原有body的內(nèi)容。

最后自己根據(jù)自己的邏輯代碼,修改原有body的內(nèi)容,重新寫入輸出流即可

public class ResponseFilter implements Filter {
? ? @Override
? ? public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
? ? ? ? ? ? throws IOException, ServletException {
? ? ? ? BodyCachingHttpServletResponseWrapper responseWrapper = new BodyCachingHttpServletResponseWrapper((HttpServletResponse) servletResponse);
? ? ? ? //獲取當(dāng)前accessToken
? ? ? ? Optional<String> currentUserAccessTokenOptional = SecurityUtils.getCurrentUserAccessToken();
? ? ? ? String currentUserAccessToken = null;
? ? ? ? if(currentUserAccessTokenOptional.isPresent()) {
? ? ? ? ? ? currentUserAccessToken = currentUserAccessTokenOptional.get();
? ? ? ? }
? ? ? ? responseWrapper.addHeader("xuncai_access_token", currentUserAccessToken);
? ? ? ? chain.doFilter(servletRequest, responseWrapper);
? ? ? ? Optional<String> xTotalCount = Optional.ofNullable(responseWrapper.getHeader("X-Total-Count"));
? ? ? ? byte[] writeValueByte = null;
? ? ? ? if(xTotalCount.isPresent() && responseWrapper.getBytes() != null) {
? ? ? ? ? ? String currentTotal = xTotalCount.get();
? ? ? ? ? ? String currentData = new String(responseWrapper.getBytes());
? ? ? ? ? ? String writeValue = "{\"total\":"+currentTotal+",\"data\":"+currentData+"}";
? ? ? ? ? ? writeValueByte = writeValue.getBytes();
? ? ? ? }else {
? ? ? ? ? ? writeValueByte = responseWrapper.getBytes();
? ? ? ? }
? ? ? ? //重新寫入輸出流
? ? ? ? ServletOutputStream outputStream = servletResponse.getOutputStream();
? ? ? ? outputStream.write(writeValueByte);
? ? ? ? outputStream.flush();
? ? ? ? outputStream.close();
? ? }
}

經(jīng)過測試,一切OK。

Springboot在絕大部分過濾器中修改請求頭信息

實現(xiàn)方式

反射。

代碼

package one.util;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.util.ObjectUtils;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class HeadersEdit {
    private final HttpServletRequest request;
    private Map<String, String> modifyHeaders;
    private MimeHeaders itsHeaders;
    private boolean isDeleteKnown=true;
    public HeadersEdit(HttpServletRequest request){
        this.request=request;
        modifyHeaders= new HashMap<>();
        itsHeaders=getMimeHeaders(getRequestFacade());
    }
    private HttpServletRequest getRequestFacade(){
        try{
            Field field= ServletRequestWrapper.class.getDeclaredField("request");
            HttpServletRequest result;
            field.setAccessible(true);
            result=(HttpServletRequest)field.get((request));
            while(!(result instanceof RequestFacade)){
                result=(HttpServletRequest)field.get((result));
            }
            return result;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("HeadersEdit Error!");
        }
    }
    private MimeHeaders getMimeHeaders(HttpServletRequest requestFacade){
        try{
            Field itsRequest= RequestFacade.class.getDeclaredField("request");
            itsRequest.setAccessible(true);
            HttpServletRequest o5=(HttpServletRequest) itsRequest.get(requestFacade);
            Field coyoteField= Request.class.getDeclaredField("coyoteRequest");
            coyoteField.setAccessible(true);
            org.apache.coyote.Request coyoteRequest=(org.apache.coyote.Request) coyoteField.get(o5);
            Field headers=org.apache.coyote.Request.class.getDeclaredField("headers");
            headers.setAccessible(true);
            return (MimeHeaders)headers.get(coyoteRequest);
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("HeadersEdit Error!");
        }
    }
    private boolean setValueExecutor(Map<String,String>newHeaders){
        String key;
        for(Map.Entry<String, String> entry : newHeaders.entrySet()){
            key=entry.getKey();
            if(itsHeaders.getHeader(key)!=null){
                if(isDeleteKnown){
                    itsHeaders.removeHeader(key);
                }else{
                    return false;
                }
            }
            itsHeaders.addValue(key).setString(entry.getValue());
        }
        return true;
    }
    public boolean setValue(String key,String value){
        if(ObjectUtils.isEmpty(key)||ObjectUtils.isEmpty(value)){
            return false;
        }
        Map<String,String>map=new HashMap<>();
        map.put(key,value);
        return setValueExecutor(map);
    }
    public boolean setValue(Map<String,String>newHeaders){
        if(ObjectUtils.isEmpty(newHeaders)){
            return false;
        }
        return setValueExecutor(newHeaders);
    }
    public void changeCheck(){
        isDeleteKnown=!isDeleteKnown;
    }
}

測試環(huán)境

springsecurity中的過濾器、以及普通的過濾器。

原理簡述

許多過濾器都間接繼承了ServletRequestWrapper類,它有個屬性叫request。

springsecurity或者普通的過濾器類只是將其包裝了多層,通過反射一層一層剝開即可。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

元氏县| 叶城县| 平罗县| 唐海县| 精河县| 朝阳区| 油尖旺区| 井陉县| 莎车县| 贺州市| 揭西县| 龙川县| 台安县| 扶风县| 兴化市| 咸阳市| 闵行区| 望谟县| 敖汉旗| 饶平县| 定兴县| 信阳市| 庆云县| 怀远县| 新蔡县| 白玉县| 南投市| 通辽市| 红原县| 临沧市| 文水县| 余干县| 广南县| 海安县| 黑水县| 庆城县| 木里| 微山县| 阳新县| 会宁县| 旌德县|