整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          JavaEE中統(tǒng)一修改http響應(yīng)體內(nèi)容的方法

          JavaEE中統(tǒng)一修改http響應(yīng)體內(nèi)容的方法

          之前的文章中介紹過Spring Boot開發(fā)中統(tǒng)一修改http響應(yīng)體內(nèi)容的方法

          spring-boot中統(tǒng)一修改http響應(yīng)體內(nèi)容的方法

          今天給大家再介紹另一種方案也能實現(xiàn)同樣的效果,那就是JavaEE中通過使用Filter過濾器來修改http響應(yīng)體~

          工作原理

          JavaEE中提供了HttpServletResponseWrapper,該類實現(xiàn)了HttpServletResponse接口,通過重寫該類的getOutputStream、getWriter方法來攔截Servlet響應(yīng)內(nèi)容,結(jié)合Filter的使用,就可以在Filter中統(tǒng)一修改http響應(yīng)體了
          JavaEE官方文檔說明:https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletResponseWrapper.html

          使用方式

          1.編寫HttpServletResponseWrapper的實現(xiàn)類,來包裝HttpServletResponse,等下在Filter中會用于替換真正的HttpServletResponse對象

          示例代碼:https://github.com/netbuffer/javaee-demo/blob/master/src/main/java/cn/netbuffer/filter/wrapper/ModifyHttpResponseWrapper.java

          public class ModifyHttpResponseWrapper extends HttpServletResponseWrapper {
          
              private CharArrayWriter bufferWriter;
              private ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
              private HttpServletResponse httpServletResponse;
          
              public ModifyHttpResponseWrapper(HttpServletResponse response) {
                  super(response);
                  bufferWriter=new CharArrayWriter();
                  httpServletResponse=response;
              }
          
              @Override
              public ServletOutputStream getOutputStream() {
                  return new ServletOutputStreamWrapper(this.byteArrayOutputStream, this.httpServletResponse);
              }
          
              @Override
              public PrintWriter getWriter() throws IOException {
                  return new PrintWriter(bufferWriter);
              }
          
              public String getResult() {
                  return bufferWriter.toString();
              }
          
              public String getContent() {
                  return new String(byteArrayOutputStream.toByteArray());
              }
          
              @Override
              public void setContentType(String type) {
                  super.setContentType(type);
              }
          
              private class ServletOutputStreamWrapper extends ServletOutputStream {
          
                  private ByteArrayOutputStream outputStream;
                  private HttpServletResponse response;
          
                  public ServletOutputStreamWrapper(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response) {
                      this.outputStream=byteArrayOutputStream;
                      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();
                      }
                  }
              }
          }
          

          2.編寫Filter過濾器來攔截http響應(yīng),達到最終修改http響應(yīng)體的目的
          示例代碼:https://github.com/netbuffer/javaee-demo/blob/master/src/main/java/cn/netbuffer/filter/ModifyHttpResponseFilter.java

          @WebFilter(filterName="ModifyHttpResponseFilter", urlPatterns={"/json/*"})
          public class ModifyHttpResponseFilter implements Filter {
          
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {
              }
          
              @Override
              public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                  HttpServletResponse httpServletResponse=(HttpServletResponse) servletResponse;
                  ModifyHttpResponseWrapper modifyHttpResponseWrapper=new ModifyHttpResponseWrapper(httpServletResponse);
                  System.out.println("-----------------before ModifyHttpResponseFilter------------------");
                  filterChain.doFilter(servletRequest, modifyHttpResponseWrapper);
                  System.out.println("-----------------after ModifyHttpResponseFilter------------------");
                  JSONObject jsonObject=JSON.parseObject(StringUtils.isBlank(modifyHttpResponseWrapper.getResult()) ? modifyHttpResponseWrapper.getContent() : modifyHttpResponseWrapper.getResult());
                  jsonObject.put("msg", "wrapper[" + jsonObject.getString("msg") + "]");
                  HttpServletResponse response=(HttpServletResponse) modifyHttpResponseWrapper.getResponse();
                  response.setContentType("application/json; charset=UTF-8");
                  PrintWriter printWriter=response.getWriter();
                  printWriter.write(jsonObject.toJSONString());
                  printWriter.flush();
                  printWriter.close();
              }
          
              @Override
              public void destroy() {
              }
          
          }
          

          3.編寫測試用的Servlet,來測試http響應(yīng)體改寫情況
          完整示例代碼:https://github.com/netbuffer/javaee-demo/blob/master/src/main/java/cn/netbuffer/servlet/JSONServlet.java

          @WebServlet(name="jsonServlet", urlPatterns={"/json"})
          public class JSONServlet extends HttpServlet {
          
              @Override
              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  JSONObject data=new JSONObject();
                  data.put("success", true);
                  data.put("msg", "invoke success for " + this.getClass().getName());
                  System.out.println("get json=" + data);
                  response.getWriter().write(data.toString());
              }
          
          }
          

          運行效果

          啟動工程,使用Postman工具訪問/json接口測試
          可以看到返回的數(shù)據(jù)中已經(jīng)被wrapper[]包裝了


          請求執(zhí)行流程

          完整測試工程請參考:https://github.com/netbuffer/javaee-demo

          明白了原理,JavaEE中的這種機制我們完全可以用在Spring Boot開發(fā)中~
          示例偽代碼:

               //注冊Filter過濾器來攔截響應(yīng)內(nèi)容,并修改最終的響應(yīng)體
              @Bean
              public FilterRegistrationBean registration() {
                  FilterRegistrationBean registration=new FilterRegistrationBean();
                  //注冊
                  registration.setFilter(new YourFilter());
                  registration.addUrlPatterns("/YourPath/*");
                  registration.setOrder(1000);
                  return registration;
              }
          

          示例過濾器,在doFilter中做自定義的邏輯處理,可以達到統(tǒng)一修改http響應(yīng)體的效果~

            public class YourFilter extends GenericFilterBean {
          
              @Override
              public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                 //todo 自定義處理邏輯
              }
          
            }
          

          完整代碼寫法可以參考我在spring-boot-admin issue中的回答:https://github.com/codecentric/spring-boot-admin/issues/1053#issuecomment-920630443

          、概述

          在 NGINX 中,sub_filtersubs_filter 是兩個用于替換響應(yīng)內(nèi)容中字符串的指令,它們主要用于反向代理和修改響應(yīng)內(nèi)容。下面是它們之間的主要區(qū)別:

          • sub_filter 是基本的字符串替換,不支持正則表達式。
          • subs_filter 支持更靈活的正則表達式替換,可以進行更復(fù)雜的匹配和替換操作。
          • subs_filterngx_http_sub_module 模塊提供的功能,需要確保該模塊被編譯進 NGINX。

          一般來說,如果只需要簡單的字符串替換,使用 sub_filter 就足夠了。如果需要更強大的正則表達式支持,可以使用 subs_filter

          示例:

          # 使用 sub_filter 進行字符串替換
          location / {
              proxy_pass http://backend_server;
              sub_filter 'http://backend_server' 'http://frontend_server';
              sub_filter_once off;  # 可選,允許多次替換,默認為 off。
          }
          
          # 使用 subs_filter 進行正則表達式替換
          location / {
              proxy_pass http://backend_server;
              subs_filter 'http://backend_server' 'http://frontend_server' ig;
          }
          
          

          二、nginx 環(huán)境部署

          環(huán)境部署的詳細過程,可以參考我這篇文章:NGINX - 高級負載均衡器、Web服務(wù)器、反向代理

          官方地址:http://nginx.org

          wget https://nginx.org/download/nginx-1.24.0.tar.gz
          tar -xf nginx-1.24.0.tar.gz
          
          # 編譯部署
          yum install -y gcc pcre-devel openssl-devel
          
          ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
          make
          make install
          

          三、sub_filter

          sub_filter 是 NGINX 提供的用于在響應(yīng)內(nèi)容中進行簡單字符串替換的指令。它的基本語法如下:

          sub_filter old_string new_string;
          

          這里是一個詳細示例,演示如何在 NGINX 中使用 sub_filter 進行字符串替換:

          假設(shè)有一個后端服務(wù)器返回的 HTML 頁面,其中包含了字符串 "Hello, World!",而我們希望將其替換為 "Hello, NGINX!"。

          server {
              listen 80;
              server_name example.com;
          
              location / {
                  proxy_pass http://backend_server;
          
                  # 使用 sub_filter 進行字符串替換
                  sub_filter 'Hello, World!' 'Hello, NGINX!';
                  sub_filter_once off;  # 可選,允許多次替換,默認為 off。
              }
          }
          

          在這個配置中:

          • proxy_pass http://backend_server; 將請求轉(zhuǎn)發(fā)給后端服務(wù)器。
          • sub_filter 'Hello, World!' 'Hello, NGINX!'; 指定了要查找和替換的字符串,將 "Hello, World!" 替換為 "Hello, NGINX!"
          • sub_filter_once off; 可選配置,表示允許多次替換。如果不設(shè)置這個選項,默認只替換第一次出現(xiàn)的字符串。

          這樣,當 NGINX 收到來自后端服務(wù)器的響應(yīng)時,會在響應(yīng)內(nèi)容中查找并替換 "Hello, World!""Hello, NGINX!"。這種功能常用于在反向代理過程中修改響應(yīng)內(nèi)容,例如替換頁面上的鏈接、域名或其他字符串。

          請注意,sub_filter 只能進行簡單的字符串匹配和替換,不支持正則表達式。如果需要更復(fù)雜的匹配和替換操作,可以考慮使用 subs_filter,該指令支持正則表達式。

          四、subs_filter

          subs_filterNGINXngx_http_sub_module 模塊提供的指令,它可以在響應(yīng)內(nèi)容中使用正則表達式進行字符串替換。這使得它比 sub_filter 更靈活,能夠處理更復(fù)雜的匹配和替換操作。

          開始重新編譯NGINX 支持 sub_filter 指令

          git clone git://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
          
          # 開始重新編譯
          # ./configure --add-module=/path/to/module
          ./configure --prefix=/usr/local/nginx --add-module=./ngx_http_substitutions_filter_module --with-http_ssl_module --with-http_stub_status_module
          
          # 安裝
          make && make install
          
          # 重啟nginx
          pkill -9 nginx
          nginx
          
          # 檢查
          nginx -V
          



          以下是一個詳細的示例,演示如何在 NGINX 中使用
          subs_filter

          假設(shè)有一個后端服務(wù)器返回的 HTML 頁面,其中包含了一組鏈接,而我們希望將這些鏈接的域名替換為新的域名。

          server {
              listen 80;
              server_name example.com;
          
              location / {
                  proxy_pass http://backend_server;
          
                  # 使用 subs_filter 進行正則表達式替換
                  subs_filter 'http://old_domain.com' 'http://new_domain.com' ig;
              }
          }
          

          在這個配置中:

          • proxy_pass http://backend_server; 將請求轉(zhuǎn)發(fā)給后端服務(wù)器。
          • subs_filter 'http://old_domain.com' 'http://new_domain.com' ig; 指定了正則表達式,將匹配所有出現(xiàn)的 "http://old_domain.com",并替換為 "http://new_domain.com"。標志 ig 表示忽略大小寫并進行全局替換。

          使用正則表達式的好處是可以更靈活地匹配多個可能的變體,而不僅僅是一個精確的字符串。

          請注意,subs_filter 的語法是:

          subs_filter pattern replacement [flags] [r=number];
          
          • regex: 要替換的正則表達式。
          • replacement_string: 替換后的字符串。
          • flags: 可選,正則表達式的標志。
            • i(大小寫不敏感):如果設(shè)置了 i 標志,將會忽略大小寫,即不區(qū)分大小寫。示例:subs_filter 'pattern' 'replacement' i;
            • g(全局匹配):如果設(shè)置了 g 標志,將會進行全局匹配,即替換所有匹配的字符串,而不僅僅是第一個。示例:subs_filter 'pattern' 'replacement' g;
            • o(替換一次):如果設(shè)置了 o 標志,將只替換第一次匹配到的字符串,不進行全局替換。示例:subs_filter 'pattern' 'replacement' o;
            • n(不進行替換):如果設(shè)置了 n 標志,將不進行實際的替換操作,僅計數(shù)匹配的字符串。示例:subs_filter 'pattern' 'replacement' n;
            • q(不輸出警告):如果設(shè)置了 q 標志,將不輸出關(guān)于替換操作的警告信息。示例:subs_filter 'pattern' 'replacement' q;
            • c(大小寫敏感):如果設(shè)置了 c 標志,將進行大小寫敏感的匹配。示例:subs_filter 'pattern' 'replacement' c;
            • p(省略前導空格):如果設(shè)置了 p 標志,將省略替換后字符串中的前導空格。示例:subs_filter 'pattern' 'replacement' p;
            • e(不進行內(nèi)存溢出檢查):如果設(shè)置了 e 標志,將不進行內(nèi)存溢出檢查。示例:subs_filter 'pattern' 'replacement' e;
          • r=number:可選項,用于指定替換字符串的格式。用于正則匹配。

          下面是一個示例,演示如何使用 r 參數(shù)進行替換字符串的格式控制:

          location / {
              proxy_pass http://backend_server;
          
              # 使用 subs_filter 進行正則表達式替換,并指定 r 參數(shù)
              subs_filter '(\d+)' '<span class="number">$1</span>' ig r;
          }
          
          
          • 在這個示例中,正則表達式 (\d+) 匹配數(shù)字,并使用替換字符串 <span class="number"></span> 進行替換。
          • 表示匹配到的數(shù)字,而 <span class="number"></span> 將數(shù)字包裹在 HTML<span> 元素中,以實現(xiàn)格式化效果。

          通過使用 r 參數(shù),可以在替換字符串中使用正則表達式匹配到的內(nèi)容,從而實現(xiàn)更靈活的替換操作。

          通過使用 subs_filter,可以在 NGINX 中執(zhí)行更復(fù)雜的字符串替換操作,以滿足特定的需求。

          NGINX sub_filter和subs_filter 指令的講解就先到這里了,有任何疑問也可關(guān)注我公眾號:大數(shù)據(jù)與云原生技術(shù)分享,進行技術(shù)交流,如本篇文章對您有所幫助,麻煩幫忙一鍵三連(點贊、轉(zhuǎn)發(fā)、收藏)~

          rowserMob Proxy 是一款基于 Java 的開源工具,廣泛用于監(jiān)控和操作網(wǎng)絡(luò)流量。這對于開發(fā)者和測試工程師來說是一個非常有用的工具,尤其是在進行自動化測試和網(wǎng)絡(luò)優(yōu)化時。以下是一個關(guān)于如何使用 BrowserMob Proxy 的入門指南。

          1. BrowserMob Proxy 簡介

          BrowserMob Proxy 允許你截取、查看和修改瀏覽器或應(yīng)用程序的網(wǎng)絡(luò)請求和響應(yīng)。這在自動化測試中尤為重要,可以用來驗證應(yīng)用程序如何與網(wǎng)絡(luò)接口交互,或者模擬網(wǎng)絡(luò)條件對應(yīng)用行為的影響。

          GitHub地址

          https://github.com/lightbody/browsermob-proxy
          

          2. 環(huán)境設(shè)置

          要開始使用 BrowserMob Proxy,首先需要將其集成到你的 Java 項目中。可以通過 Maven 來管理依賴:

          <dependency>
              <groupId>net.lightbody.bmp</groupId>
              <artifactId>browsermob-core</artifactId>
              <version>2.1.5</version>
          </dependency>
          

          確保你的開發(fā)環(huán)境已經(jīng)安裝了 Maven 和 Java。

          3. 啟動代理服務(wù)器

          BrowserMob Proxy 通過創(chuàng)建一個本地代理服務(wù)器來工作。以下是如何在 Java 代碼中啟動和設(shè)置代理服務(wù)器:

          BrowserMobProxy proxy=new BrowserMobProxyServer();
          proxy.start(0); // 0 表示自動選擇一個可用端口
          System.out.println("Proxy started on port: " + proxy.getPort());
          

          4. 配置 WebDriver

          如果你使用 Selenium 進行自動化測試,需要配置 WebDriver 以使用 BrowserMob Proxy。這樣,所有通過 WebDriver 發(fā)起的請求都會經(jīng)過代理服務(wù)器:

          System.setProperty("webdriver.gecko.driver", "path/to/geckodriver");
          WebDriver driver=new FirefoxDriver();
          Proxy seleniumProxy=ClientUtil.createSeleniumProxy(proxy);
          

          5. 攔截和修改 HTTP 請求/響應(yīng)

          BrowserMob Proxy 最強大的功能之一是能夠攔截和修改進出的網(wǎng)絡(luò)請求和響應(yīng)。以下是一個示例,展示如何修改對特定 JavaScript 文件的響應(yīng):

          proxy.addResponseFilter((response, contents, messageInfo) -> {
              if (messageInfo.getOriginalUrl().contains("http://a.b.c/d.js")) {
                  String content=contents.getTextContents();
                  String modifiedContent=content.replace("oldFunction()", "newFunction()");
                  contents.setTextContents(modifiedContent);
              }
          });
          

          6. 注意事項

          使用 BrowserMob Proxy 攔截 HTTPS 流量時,可能需要安裝并信任由 BrowserMob Proxy 動態(tài)生成的 CA 證書,以避免 SSL 錯誤。

          通過以上步驟,你可以開始使用 BrowserMob Proxy 來增強你的開發(fā)和測試工作。這個工具不僅可以幫助你更好地理解應(yīng)用如何與網(wǎng)絡(luò)交互,還可以用于測試應(yīng)用在不同網(wǎng)絡(luò)條件下的表現(xiàn)。


          主站蜘蛛池模板: 久久精品无码一区二区无码 | 波多野结衣一区二区免费视频 | 成人精品一区二区电影| 久久久久人妻精品一区| 久久国产精品最新一区| 久久精品黄AA片一区二区三区 | 国产精品制服丝袜一区| 精品免费国产一区二区| 一区二区精品在线观看| 国产AV国片精品一区二区| 国产丝袜美女一区二区三区| 亚洲一区二区三区播放在线| 日美欧韩一区二去三区| 真实国产乱子伦精品一区二区三区 | 91在线看片一区国产| 国产一区二区三区播放心情潘金莲| 八戒久久精品一区二区三区 | 国产高清在线精品一区| 国产精品一区二区AV麻豆| 一区二区三区视频在线播放| 国产自产在线视频一区| 一本一道波多野结衣AV一区| 冲田杏梨高清无一区二区| 熟女精品视频一区二区三区| 亚洲一区二区三区成人网站| 一区二区三区无码高清| 亚洲天堂一区二区三区四区| 国产成人av一区二区三区在线| A国产一区二区免费入口| 精品动漫一区二区无遮挡| 色一情一乱一区二区三区啪啪高| 精品一区中文字幕| 美女毛片一区二区三区四区| 搜日本一区二区三区免费高清视频| 久久久久人妻精品一区蜜桃| 无码日韩人妻AV一区免费l| 人妖在线精品一区二区三区| 伊人精品视频一区二区三区| 国模无码视频一区二区三区| 久久伊人精品一区二区三区| 亚洲爽爽一区二区三区|