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

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

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

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

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

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

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

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

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

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

springboot在response中添加或者修改header

分兩種情況

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

或者

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

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

setHeader會(huì)覆蓋重名的headerName

這樣是可以添加成功

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

添加addHeader或者serHeader無(wú)效,是因?yàn)檫@和過(guò)濾器的處理流程以及對(duì)header的處理時(shí)機(jī)有關(guān)

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

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

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();
// ? ? ? ? ? ?}
// ? ? ? ?}
? ? }

然后通過(guò)過(guò)濾器,將自定義包裝類BodyCachingHttpServletResponseWrappe傳遞到chain.doFilter(servletRequest, bodyCachingHttpServletResponseWrapper ),通過(guò)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)過(guò)測(cè)試,一切OK。

Springboot在絕大部分過(guò)濾器中修改請(qǐng)求頭信息

實(shí)現(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;
    }
}

測(cè)試環(huán)境

springsecurity中的過(guò)濾器、以及普通的過(guò)濾器。

原理簡(jiǎn)述

許多過(guò)濾器都間接繼承了ServletRequestWrapper類,它有個(gè)屬性叫request。

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

總結(jié)

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

相關(guān)文章

最新評(píng)論

垦利县| 且末县| 阜新市| 清镇市| 金乡县| 北辰区| 商水县| 平乡县| 乐清市| 舟曲县| 龙门县| 当雄县| 隆子县| 巴楚县| 江北区| 金秀| 衡东县| 咸宁市| 宝山区| 呼伦贝尔市| 寻甸| 富蕴县| 潮州市| 合山市| 岑巩县| 常熟市| 礼泉县| 讷河市| 阳山县| 新源县| 盐亭县| 木里| 天镇县| 琼中| 工布江达县| 辽源市| 吴川市| 蒲江县| 陆良县| 板桥市| 肥乡县|