隨筆-193  評論-715  文章-1  trackbacks-0

          我們常常有需要在每一個(gè)頁面中加入一些內(nèi)容,而這些內(nèi)容又是固定的一些根據(jù)某些配置産生的內(nèi)容,利如我們可以為每個(gè)頁面引入共用的編碼,引入共用的JavaScript等等。

          我們知道,利用JavaEE的Filter機(jī)制,可以截獲Request和Response,並對其進(jìn)行修改。Filter實(shí)質(zhì)上是一個(gè)Chain,對其原理的解釋,可以參考網(wǎng)路上的文章,有很多講得很好,大家有空可以看看。

          1、實(shí)現(xiàn)一個(gè)Filter,代碼如下:

          public class MyFilter implements Filter {

          public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain filterChain) {
          CheckFrameHttpServletResponseWrapper wrapper = new CheckFrameHttpServletResponseWrapper(
          (HttpServletResponse) response);
          try {
          filterChain.doFilter(request, wrapper);
          } catch (Exception e) {
          e.printStackTrace();
          }
          }

          public void destroy() {

          }

          public void init(FilterConfig arg0) throws ServletException {

          }
          }


          2、實(shí)現(xiàn)一個(gè)HttpServletResponseWrapper

          public class CheckFrameHttpServletResponseWrapper extends
          HttpServletResponseWrapper {

          public CheckFrameHttpServletResponseWrapper(HttpServletResponse response) {

          super(response);
          }

          public PrintWriter getWriter() throws IOException{
          return new CheckFrameWriter(super.getWriter());
          }

          }

          3、實(shí)現(xiàn)一個(gè)Writer

          public class CheckFrameWriter extends PrintWriter {
          String checkString = "<script>\n if(window.top.frames.length==0){\n"
          + "window.location.href=\"https://aix:9080/sso/mainlayout.faces?"
          + "contentURL=http://aix:9080/security/paramsMaintain/"
          + "addParams.faces?roleId=0001\"\n" + "}\n</script>\n";

          public CheckFrameWriter(Writer out) {
          super(out);
          }

          public void write(int c) {
          super.write((char) c);
          }

          public void write(char buf[], int off, int len) {
          StringBuffer sb = new StringBuffer(len);
          for (int i = 0; i < len; i++) {
          sb.append(buf[off + i]);
          }
          String s = sb.toString();
          int bodyIndex = s.indexOf("<body>");
          if (bodyIndex > -1) {
          String part1 = s.substring(0, bodyIndex);
          String part2 = s.substring(bodyIndex );
          s = part1 + checkString + part2;
          }
          for (int i = 0; i < s.length(); i++) {
          write(s.charAt(i));
          }
          }

          public void write(String s, int off, int len) {
          for (int i = 0; i < len; i++) {
          write(s.charAt(off + i));
          }
          }
          }


          在Writer中,你便可以隨心所欲的修改Response的內(nèi)容了。

          4、在Web.xml中加入相應(yīng)的配置,對JSP進(jìn)行攔截。


          問題:

          現(xiàn)在發(fā)現(xiàn)對於HTML後綴的請求,沒有辦法改寫,即使我配置Filter匹配為/*,HTML請求也有進(jìn)行Filter,但還是無法改變其內(nèi)容。目前還沒有想通是為什麼?如何改進(jìn)?哪位大俠可以給予指點(diǎn)。

          posted on 2007-07-15 19:06 Robin's Programming World 閱讀(7178) 評論(4)  編輯  收藏 所屬分類: Java

          評論:
          # re: 利用Filter修改Response 2007-07-15 19:53 | xuefeng
          你的wrapper實(shí)現(xiàn)有問題。應(yīng)當(dāng)在內(nèi)存中開辟一個(gè)ByteOutputStream,然后將攔截的響應(yīng)寫入byte[],寫入完畢后,再將wrapper的byte[]寫入真正的response對象

          下面的例子是《Spring 2.0核心技術(shù)與最佳實(shí)踐》中的例子:

          package net.livebookstore.web.filter;

          import java.io.*;

          import javax.servlet.*;
          import javax.servlet.http.*;

          /**
          * This class is used for wrapped response for getting cached data.
          *
          * @author Xuefeng
          */
          class CachedResponseWrapper extends HttpServletResponseWrapper {

          /**
          * Indicate that getOutputStream() or getWriter() is not called yet.
          */
          public static final int OUTPUT_NONE = 0;

          /**
          * Indicate that getWriter() is already called.
          */
          public static final int OUTPUT_WRITER = 1;

          /**
          * Indicate that getOutputStream() is already called.
          */
          public static final int OUTPUT_STREAM = 2;

          private int outputType = OUTPUT_NONE;

          private int status = SC_OK;
          private ServletOutputStream output = null;
          private PrintWriter writer = null;
          private ByteArrayOutputStream buffer = null;

          public CachedResponseWrapper(HttpServletResponse resp) throws IOException {
          super(resp);
          buffer = new ByteArrayOutputStream();
          }

          public int getStatus() { return status; }

          public void setStatus(int status) {
          super.setStatus(status);
          this.status = status;
          }

          public void setStatus(int status, String string) {
          super.setStatus(status, string);
          this.status = status;
          }

          public void sendError(int status, String string) throws IOException {
          super.sendError(status, string);
          this.status = status;
          }

          public void sendError(int status) throws IOException {
          super.sendError(status);
          this.status = status;
          }

          public void sendRedirect(String location) throws IOException {
          super.sendRedirect(location);
          this.status = SC_MOVED_TEMPORARILY;
          }

          public PrintWriter getWriter() throws IOException {
          if(outputType==OUTPUT_STREAM)
          throw new IllegalStateException();
          else if(outputType==OUTPUT_WRITER)
          return writer;
          else {
          outputType = OUTPUT_WRITER;
          writer = new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding()));
          return writer;
          }
          }

          public ServletOutputStream getOutputStream() throws IOException {
          if(outputType==OUTPUT_WRITER)
          throw new IllegalStateException();
          else if(outputType==OUTPUT_STREAM)
          return output;
          else {
          outputType = OUTPUT_STREAM;
          output = new WrappedOutputStream(buffer);
          return output;
          }
          }

          public void flushBuffer() throws IOException {
          if(outputType==OUTPUT_WRITER)
          writer.flush();
          if(outputType==OUTPUT_STREAM)
          output.flush();
          }

          public void reset() {
          outputType = OUTPUT_NONE;
          buffer.reset();
          }

          /**
          * Call this method to get cached response data.
          * @return byte array buffer.
          * @throws IOException
          */
          public byte[] getResponseData() throws IOException {
          flushBuffer();
          return buffer.toByteArray();
          }

          /**
          * This class is used to wrap a ServletOutputStream and
          * store output stream in byte[] buffer.
          */
          class WrappedOutputStream extends ServletOutputStream {

          private ByteArrayOutputStream buffer;

          public WrappedOutputStream(ByteArrayOutputStream buffer) {
          this.buffer = buffer;
          }

          public void write(int b) throws IOException {
          buffer.write(b);
          }

          public byte[] toByteArray() {
          return buffer.toByteArray();
          }
          }

          }

            回復(fù)  更多評論
            
          # re: 利用Filter修改Response 2007-07-15 20:00 | xuefeng
          在Filter中調(diào)用:

          public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain) throws IOException, ServletException
          {
          HttpServletRequest httpRequest = (HttpServletRequest) request;
          HttpServletResponse httpResponse = (HttpServletResponse)response;
          CachedResponseWrapper wrapper = new CachedResponseWrapper(httpResponse);
          // 寫入wrapper:
          chain.doFilter(request, wrapper);
          // 首先判斷status, 只對200狀態(tài)處理:
          if(wrapper.getStatus()==HttpServletResponse.SC_OK) {
          // 對響應(yīng)進(jìn)行處理,這里是進(jìn)行GZip壓縮:
          byte[] data = GZipUtil.gzip(wrapper.getResponseData());
          httpResponse.setContentType(getContentType());
          httpResponse.setContentLength(data.length);
          httpResponse.setHeader("Content-Encoding", "gzip");
          ServletOutputStream output = response.getOutputStream();
          output.write(data);
          output.flush();
          }
          }

          需要判斷狀態(tài),正確設(shè)置Content-Length,具體可參考《Spring 2.0核心技術(shù)與最佳實(shí)踐》第十一章12節(jié):利用Filter實(shí)現(xiàn)內(nèi)存緩存和靜態(tài)文件緩存
            回復(fù)  更多評論
            
          # re: 利用Filter修改Response 2007-07-16 10:19 | Robin's Java World
          @xuefeng
          謝謝!
          有機(jī)會看看你推薦的書.  回復(fù)  更多評論
            
          # re: 利用Filter修改Response 2007-07-24 13:58 | xuefeng
          這本書是我寫的,呵呵,做個(gè)廣告  回復(fù)  更多評論
            
          主站蜘蛛池模板: 大城县| 临清市| 揭东县| 萍乡市| 哈密市| 东源县| 斗六市| 扎兰屯市| 监利县| 仁怀市| 丹棱县| 若羌县| 博湖县| 甘谷县| 大兴区| 山丹县| 琼结县| 米易县| 甘洛县| 涟源市| 凌海市| 满洲里市| 闵行区| 兰坪| 雷州市| 佳木斯市| 咸阳市| 博罗县| 孙吴县| 普格县| 靖江市| 云浮市| 台北市| 长春市| 高州市| 阳春市| 林周县| 崇信县| 皮山县| 彭阳县| 区。|