1. 서블릿 필터
1.1 필터는 무엇입니까?
필터는 서틀 또는 JSP 페이지가 관련된 서버에서 실행되는 프로그램입니다. 필터는 하나 이상의 서블릿 또는 JSP 페이지에 연결되어 있으며 이러한 리소스를 입력하는 요청 정보를 확인할 수 있습니다. 그런 다음 필터를 다음과 같이 선택할 수 있습니다.
① 정기적 인 방법으로 리소스를 호출하십시오 (즉, 서블릿 또는 JSP 페이지에 전화).
② 수정 된 요청 정보를 사용하여 리소스를 호출하십시오.
wall 리소스를 발산하지만 클라이언트에 응답을 보내기 전에 수정하십시오.
resour 리소스 호출을 블로킹하고 대신 다른 리소스로 이동하여 특정 상태 코드를 반환하거나 교체 출력을 생성하십시오.
1.2 서블릿 필터의 기본 원리
서블릿을 필터로 사용하면 고객 요청을 처리 할 수 있습니다. 처리가 완료되면 처리를 위해 다음 필터로 전달되므로 요청이 대상으로 전송 될 때까지 클라이언트의 요청이 필터 체인에서 하나씩 처리됩니다. 예를 들어, 웹 사이트에는 "수정 된 등록 정보"를 제출하는 웹 페이지가 있습니다. 사용자가 수정 된 정보를 채우고 제출 한 후에는 처리 할 때 서버가 두 가지 작업을 수행해야합니다. 클라이언트 세션이 유효한지 확인하십시오. 제출 된 데이터를 균일하게 인코딩합니다. 이 두 작업은 두 필터로 구성된 필터 체인으로 처리 할 수 있습니다. 필터 프로세스가 성공하면 제출 된 데이터가 최종 대상으로 전송됩니다. 필터 프로세스가 실패하면 뷰가 지정된 오류 페이지에 배포됩니다.
2. 서블릿 필터 개발 단계
서블릿 필터를 개발하기위한 단계는 다음과 같습니다.
filter 필터 인터페이스를 구현하는 서블릿 클래스를 작성하십시오.
web.xml의 Configure 필터.
필터를 개발하려면 필터 인터페이스를 구현해야합니다. 필터 인터페이스는 다음 방법을 정의합니다.
Web이 필터를 초기화하기 위해 Web Container에서 DEARTORY ()를 호출합니다.
② init (FilterConfig FilterConfig)를 웹 컨테이너에서 호출 하여이 필터를 초기화합니다.
dofilter (Servletrequest 요청, ServletRepronse 응답, Filterchain 체인) 특정 필터링 처리 코드.
3. 필터 프레임 워크의 예
SimpleFilter1.java
패키지 com.zj.sample; import java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servletrequest; javax.servletrpronge; 공개 클래스 SimpleFilter1은 필터 {@suppresswarnings ( "Unused") Private FilterConfig FilterConfig; public void init (filterconfig config) servletexception {this.filterconfig = config; } public void dofilter (ServletRequest 요청, ServletRepsonge 응답, FilterChain 체인) {try {System.out.println ( "SimpleFilter1 내에서 : 요청 필터링 ..."); chain.dofilter (요청, 응답); // 프로세싱을 다음 필터 시스템으로 보낸다. } catch (ioexception ioe) {ioe.printstacktrace (); } catch (servletexception se) {se.printstacktrace (); }} public void destroy () {this.filterconfig = null; }}
SimpleFilter2.java
패키지 com.zj.sample; import java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servletrequest; javax.servletrpronge; 공개 클래스 SimpleFilter2는 필터 {@suppresswarnings ( "Unused") Private FilterConfig FilterConfig; public void init (filterconfig config) servletexception {this.filterconfig = config; } public void dofilter (ServletRequest 요청, ServletRepsonge 응답, FilterChain 체인) {try {System.out.println ( "SimpleFilter2 내에서 : 요청 필터링 ..."); Chain.dofilter (요청, 응답); // 프로세싱을 다음 필터 시스템으로 보냅니다. out.println ( "SimpleFilter2 내에서 : 응답 필터링 ..."); } catch (ioexception ioe) {ioe.printstacktrace (); } catch (servletexception se) {se.printstacktrace (); }} public void destroy () {this.filterconfig = null; }}
web.xml
<Filter> <Filter-Name> filter1 </filter-name> <filter-class> com.zj.sample.simplefilter1 </filter-class> </filter> <filter-mapping> <filter-name> filter1 </filter-name> <url-pattern>/*</url-pattern> // filter </filter-mapping> <filter-name> filter2 </filter-name> <filter-class> com.zj.sample.simplefilter2 </filter-class> </filter> <filter-mapping> <filter-name> filter2 </filter-name> <Url-pattern>/*</url-pattern> // filter </필터-매핑>
웹 컨테이너의 모든 페이지를 열면 결과를 출력하십시오. (필터에서 실행 된 요청/응답 순서 참고)
SimpleFilter1 내에서 : 요청 필터링 ... SimpleFilter2 내에서 : 요청 필터링 ... SimpleFilter2 내에서 : 응답 필터링 ... SimpleFilter1 내에서 : 응답 필터링 ...
4.보고 필터
관련 서블릿 또는 JSP 페이지를 호출하여 표준 출력에 메시지를 인쇄하는 간단한 필터를 실험 해 보겠습니다. 이 기능을 구현하기 위해, 필터링 동작은 도필터 방법으로 수행됩니다. 이 필터와 관련된 서블릿 또는 JSP 페이지가 호출 될 때마다 도필터 메소드는 요청 된 호스트와 통화의 URL을 나열하는 인쇄물을 생성합니다. getRequestUrl 메소드는 ServletRequest 대신 httpservletrequest에 위치하므로 ServletRequest 객체는 httpservletrequest 유형으로 구성됩니다. 3 장에서 SimpleFilter1.java를 변경합시다.
SimpleFilter1.java
패키지 com.zj.sample; import java.io.ioexception; import java.util.date; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; 공개 클래스 SimpleFilter1은 필터 {@suppresswarnings ( "Unused") Private FilterConfig FilterConfig; public void init (filterconfig config) servletexception {this.filterconfig = config; } public void dofilter (ServletRequest 요청, ServletRepsonge 응답, FilterChain 체인) {try {System.out.println ( "SimpleFilter1 내에서 : 요청 필터링 ..."); httpservletrequest req = (httpservletrequest) 요청; System.out.println (req.getRemoteHost () + "Access"ac Chain.dofilter (요청, 응답); System.out.println ( "SimpleFilter1 내에서 : 응답 필터링 ..."); } catch (ioexception ioe) {ioe.printstacktrace (); } catch (servletexception se) {se.printstacktrace (); }} public void destroy () {this.filterconfig = null; }}
Web.xml 설정은 동일한 3 장에서 변경되지 않습니다.
시험:
[url] http : // localhost : 8080/test4jsp/login.jsp [/url]를 입력하십시오.
결과:
SimpleFilter1 내에서 : 요청 필터링 ... 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 : 1 [url] http : // localhost : 8080/test4jsp/login.jsp [/url]에서 [/url] on mar 04 17:01:37 CST 2007. SimpleFilter2 : 응답 필터링 ... SimpleFilter1 내에서 : 응답 필터링 ...
5. 액세스시 필터 (서블릿을 사용하여 필터에서 매개 변수를 초기화)
다음은 INT를 사용하여 일반 액세스 시간 범위를 설정 하여이 기간이 아닌 액세스를 기록하는 것입니다. 3 장에서 SimpleFilter2.java를 변경합시다.
SimpleFilter2.java.
패키지 com.zj.sample; import java.io.ioexception; import java.text.dateformat; import java.util.calendar; import java.util.gregoriancalendar; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filtercoconfig -rigge javax.servlet.servletcontext; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpervletrequest; 공개 클래스 SimpleFilter2는 필터 {@suppresswarnings ( "Unused") 개인 FilterConfig 구성; 개인 ServletContext 컨텍스트; 개인 int starttime, 종료 시간; 개인 날짜 형식 형식; public void init (filterconfig config) servletexception {this.config = config; context = config.getServletContext (); formatter = dateformat.getDateTimeInstance (dateFormat.Medium, dateFormat.Medium); {starttime = integer.parseint (config.getInitParameter ( "starttime")); // web.xml endtime = integer.parseint (config.getInitParameter ( "endtime")); // web.xml} catch (numberformatexception nfe) {// default : 10 pm에서 액세스하십시오. starttime = 22; // 10:00 pm endtime = 6; // 6:00 AM}} public void dofilter (servletrequest 요청, ServletReponse 응답, 필터 체인 체인) {try {system.out.println ( "SimpleFilter2 내 : 요청 필터링 ..."); httpservletrequest req = (httpservletrequest) 요청; GregorianCalendar Calendar = New GregorianCalendar (); int currenttime = calendar.get (calendar.hour_of_day); if (iSunusualTime (현재 시간, 시작 시간, endTime)) {context.log ( "경고 :" + req.getRemoteHost () + "ac // 로그 파일은 <Catalina_Home> /logs. } chain.dofilter (요청, 응답); System.out .println ( "SimpleFilter2 내에서 : 응답 필터링 ..."); } catch (ioexception ioe) {ioe.printstacktrace (); } catch (servletexception se) {se.printstacktrace (); }} public void destroy () {} // 시작과 끝 사이의 현재 시간은 // 비정상 액세스 시간으로 표시되는 시간입니까? Private Boolean isunusualTime (int currentTime, int startTime, int endtime) {// 시작 시간이 종료 시간보다 작은 경우 (예 : // 같은 날에 두 번) // 현재 시간이 시작과 종료 시간 사이에있는 경우 비정상적인 것으로 간주됩니다. if (starttime <endtime) {return ((currenttime> = starttime) && (currenttime <endtime)); } // 시작 시간이 // 종료 시간보다 크거나 동일하다면 (예 : 시작 시간은 하루에 있고 // 종료 시간은 다음 날에 있습니다), 현재 // 시간은 // 끝과 시작 시간 사이에 있지 않으면 비정상적인 것으로 간주됩니다. else {return (! isunusualtime (현재 시간, 종료 시간, 시작 시간)); }}}
Web.xml 설정은 변경되지 않았습니다.
Tomcat 로그 처리와 관련하여 다음은 추가 소개가 있습니다. config.getServletContext (). log ( "log message")는 <catalina_home>/logs 폴더에 로그 정보를 씁니다. 파일 이름은 localhost_log.2007-03-04.txt이어야합니다 (하나는 날짜별로 생성되며 다음날 볼 수 있음). 그러한 로그 파일을 얻으려면 다음과 같아야합니다.
<logger classname = "org.apache.catalina.logger.filelogger"prefix = "catalina_log" 접미사 = ". txt"timestamp = "true"/>
6. 사이트 필터는 금지되어 있습니다
필터가 비정상적인 예외를 감지 할 때 후속 필터링 프로세스 중간에 후속 필터링 프로세스를 방해하려면 다음을 수행 할 수 있습니다.
public void dofilter (servletrequest 요청, ServletRepronse 응답, 필터 체인 체인) servletexception, ioexception {httpservletrequest req = (httpservletrequest) 요청; httpservletresponse res = (httpservletresponse) 응답; if (isunusualCondition (req)) {res.SendRedirect ( "http://www.somesite.com"); } else {chain.dofilter (req, res); }} 다음 예는 금지 된 사이트 필터입니다. 일부 사이트에서 웹 사이트에 액세스 할 수없는 경우 Web.xml의 Param-Value에 사이트를 나열한 다음 위의 원리를 적용하여 일반 필터링에서 뛰어 내려 금지 된 페이지를 제공 할 수 있습니다.
bannanccessfilter.java
package com.zj.sample; import java.io.ioexception; import java.io.printwriter; import java.net.malformedurlexception; import java.net.url; import java.util.hashset; import java.util.stringtoken, import javax.servlet.filter; import javax.servlet.filterchain; javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpervletrequest; 공개 클래스 bannanccessfilter는 필터 {private Hashset <string> bannedsitetable; /*** 요청이 배너 사이트에서 제공되거나 배너 사이트에서 여기에 참조되는 경우 액세스 거부. */ public void dofilter (servletrequest 요청, ServletRepsonge 응답, 필터 체인 체인) servletexception, ioexception {system.out.println ( "BannedAccessFilter 내에서 : 요청 필터링 ..."); httpservletrequest req = (httpservletrequest) 요청; 문자열 requestinghost = req.getRemoteHost (); 문자열 참조 host = getReferringhost (req.getheader ( "CERERER")); 문자열 bannedsite = null; 부울 isbanned = false; if (bannedSitetable.contains (requestingHost)) {bannedSite = requestHost; isbanned = true; } else if (bannedSitetable.contains (참조)) {bannedsite = pretringhost; isbanned = true; } if (isbanned) {showwarning (응답, 금지); } else {chain.dofilter (요청, 응답); } system.out.println ( "BannanccessFilter 내에서 : 응답 필터링 ..."); } /*** 초기화 매개 변수를 기반으로 배너 사이트 테이블을 만듭니다.* 서블릿 API의 버전 2.3은* Java 2 플랫폼 사용을 의무화합니다. 따라서 Clumsier hashtable* (각 키에 대한 값이있는) 대신 해시 세트 (주어진 키가 존재하는지 여부)를 사용하는 것이 안전합니다. String bannedSites = config.getInitParameter ( "BannedSites"); // 기본 토큰 세트 : 공백. StringTokenizer Tok = New StringTokenizer (BannedSites); while (tok.hasmoretokens ()) {String bannedsite = tok.nexttoken (); bannedsitetable.add (bannedsite); System.out.println ( "Banned" + BannedSite); }} public void destroy () {} private String getReferringHost (String 참조 링어 스트링) {try {url prothringUrl = new URL (참조 링어 스트링); return (referringurl.gethost ()); } catch (marformedurlexception mue) {// rolformed 또는 null return (null); }} // 배너 사이트에서 출신이거나 여기에있는 사용자에게 반환되는 교체 응답. 개인 void showwarning (ServletResponse Response, String BannedSite)은 servletexception, ioexception {response.setContentType ( "text/html"); printwriter out = response.getwriter (); 문자열 doctype = "<! doctype html public/"-// w3c // dtml 4.0 " +"Transitional // en/">/n"; out.println (doctype + "<html>/n" + "<head> <title> 액세스 금지 금지 </title> </head>/n" + " +"<body bgcolor =/"white/">/n " +"<h1> 액세스 prohibed </h1>/n " +"미안, Access, Access, Access " +" + " +" + " +" + " "</body> </html>"); }}
web.xml
<filter> <filter-name> bannanceAccessFilter </filter-name> <filter-class> com.zj.sample.bannedAccessFilter </filter-class> <init-param> <param-name> bannedsites </param-name> <param-value> [url] url] url] [url] [url] www.moreservlets.com [/url] 127.0.0.1//we 테스트 </param-value> </init-param> </filter> <filter-mapping> <filter-name> bannanccessfilter </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
시험:
[url] http : // localhost : 8080/test4jsp/[/url]
결과:
7. 필터를 교체하십시오
7.1 응답 수정
필터는 자원에 대한 액세스를 차단하거나 활성화되지 않도록 할 수 있습니다. 그러나 필터가 리소스에 의해 생성 된 응답을 변경하려는 경우. 무엇을해야합니까? 리소스에 의해 생성 된 응답에 액세스 할 수있는 방법이없는 것 같습니다. Dofilter (ServletResponse)의 두 번째 매개 변수는 클라이언트에게 새 출력을 보내는 방법을 제공하지만 서블릿 또는 JSP 페이지 출력에 액세스하는 방법을 필터에 제공하지는 않습니다. 왜 이런 일이 일어나고 있습니까? Dofilter 방법이 처음으로 요구 될 때 서블릿 또는 JSP 페이지가 실행되지 않았기 때문입니다. FilterChain 객체의 도필터 메소드가 호출되면 응답을 수정하기에는 너무 늦어 보입니다. 즉, 데이터가 클라이언트로 전송되었습니다.
그러나, 필터 체인 객체로 전달 된 도필터 메소드의 응답 객체를 수정하는 방법이 있습니다. 일반적으로 서블릿 또는 JSP 페이지에서 생성 된 모든 출력 버전의 캐시를 작성하십시오. Servlet API 버전 2.3은 이에 대한 유용한 리소스, 즉 httpservletResponseWrapper 클래스를 제공합니다. 이 클래스의 사용에는 다음과 같은 5 단계가 포함됩니다.
1) 응답 래퍼를 만듭니다. javax.servlet.http.httpservletresponsewrapper를 확장합니다.
2) 출력을 캐시하는 인쇄기를 제공하십시오. GetWriter 메서드를 과부하시키고, 모든 것을 저장하는 인쇄기를 반환하고, 결과를 나중에 액세스 할 수있는 필드에 저장하십시오.
3)이 래퍼를 도필터로 전달하십시오. 이 호출은 httpservletresponsewrapper가 httpservletresponse를 구현하기 때문에 합법적입니다.
4) 출력을 추출하고 수정하십시오. 필터 체인의 도필터 방법을 호출 한 후, 2 단계에서 제공된 메커니즘을 사용하여 원래 자원의 출력을 얻을 수 있습니다. 응용 프로그램에 적합한 한 수정하거나 교체 할 수 있습니다.
5) 수정 된 출력을 클라이언트에게 보냅니다. 원래 리소스는 더 이상 클라이언트에 출력을 보내지 않기 때문에 (이 출력은 이미 응답 래퍼에 저장되어 있음) 이러한 출력을 보내야합니다. 이런 식으로 필터는 원래 응답 객체에서 인쇄기 또는 출력 스트림을 가져 와서 수정 된 출력을 스트림으로 전달해야합니다.
7.2 재사용 가능한 응답 래퍼
다음 예제는 필터가 리소스의 출력을 수정하려는 대부분의 응용 분야에서 사용할 수있는 래퍼를 제공합니다. charArrayWrapper 클래스는 GetWriter 메소드를 과부하시켜 큰 문자 배열로 모든 것을 축적하는 인쇄기를 반환합니다. 개발자는 ToChararray (Original Char []) 또는 Tostring (char []에서 파생 된 문자열)를 사용 하여이 결과를 얻을 수 있습니다.
charArrayWrapper.java
package com.zj.sample; import java.io.chararraywriter; import java.io.printwriter; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpservletresponsewrapper; /** * 클라이언트가 정상적으로 출력하여 하나의 큰 문자 배열로 저장하는 응답 래퍼. */public class charArrayWrapper 확장 httpservletResponseWrapper {private charArrayWriter charWriter; /*** 래퍼를 초기화합니다. * <p> * 먼저이 생성자는 상위 생성자를 호출합니다. 그 전화 * *는 잔인하여 응답이 저장되어 Setheader, *Setstatus, AddCookie 등이 정상적으로 작동하도록합니다. * <p> * 둘째,이 생성자는 응답을 축적하는 데 사용되는 charArraywriter를 만듭니다. */ public charArrayWrapper (httpservletResponse 응답) {super (응답); charwriter = new charArraywriter (); } /*** 서블릿이나 JSP 페이지가 작가에게 요청할 때, 그들에게* 진짜를주지 마십시오. 대신, 그들에게 문자 배열에 쓸 수있는 버전을 제공하십시오. * 필터는 배열의 내용을* 클라이언트로 보내야합니다 (아마도 수정 후). */ public printwriter getwriter () {return (new printwriter (charwriter)); } /*** 전체 버퍼의 문자열 표현을받습니다. * <p> * 동일한 * 래퍼 에서이 방법을 여러 번 호출하려면 CharArraywriter의 API는 이전 값을 "기억"한다고 보장하지 않으므로 호출은 매번 새 문자열을 만들 수 있습니다. */ public String toString () {return (charWriter.toString ()); } /** 기본 문자 배열을 얻습니다. */ public char [] tochararray () {return (charwriter.tochararray ()); }}
7.3 필터를 교체하십시오
다음은 이전 섹션에 제공된 charArrayWrapper의 일반적인 응용 프로그램입니다. 다중 발생 대상 문자열을 대체 문자열로 변경합니다.
7.3.1 일반 교체 필터
REPLECTFILTER.JAVA는 ChararraryWrapper에서 응답을 래핑하는 필터를 제공하고 래퍼를 FilterChain 객체의 도필터 방법으로 전달하고 모든 리소스의 출력을 제공하는 문자열 유형 값을 추출하고 대상 문자열의 모든 발생을 대체 문자열로 대체하며 수정 된 결과를 클라이언트에 보냅니다.
이 필터에 대한 두 가지 사항이 있습니다. 첫째, 그것은 추상적 인 수업입니다. 이를 사용하려면 getTargetString 및 GetReplacementString 메소드의 구현을 제공하는 서브 클래스를 작성해야합니다. 이 치료의 예는 다음 하위 섹션에 제공됩니다. 둘째, 실제 문자열 교체를 위해 더 작은 유틸리티 클래스 (Filterutils.java 참조)를 사용합니다. String 및 StringTokenizer에서 저수준 및 지루한 방법을 사용하는 대신 새로운 정규 표현 패키지를 사용할 수 있습니다.
replacefilter.java
패키지 com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servlet.servletrepest; javax.servlet.servletresponse; import javax.servlet.http.httpservletresponse; /*** 주어진 문자열의 모든 발생을* 교체로 대체하는 필터. * 이것은 추상 클래스입니다 : 당신은 gettargetString* 및 getReplacementString 메소드를 서브 클래스로 무시해야합니다.*이 메소드 중 첫 번째 방법은 교체 해야하는 응답*을 지정합니다. 이 사양 중 두 번째는 대상 문자열의 각 발생을 대체 해야하는 문자열*입니다. */public Abstract Class ReplarFilter 구현 필터 {private filterconfig config; public void dofilter (servletrequest 요청, ServletRepronse 응답, 필터 체인 체인) servletexception, ioException {charArrayWrapper responskWrapper = new charArrayWrapper ((httpserVletResponse) 응답); // 래퍼의 출력을 축적하고 자원을 호출합니다. Chain.dofilter (요청, 응답 표시); // 전체 출력을 하나의 큰 문자열로 전환합니다. 문자열 responseString = ResponseWrapper.ToString (); // 출력에서 대상 문자열의 모든 발생을 대체품으로 바꾸십시오. ResponseString = FilterUtils.Replace (responseString, getTargetString (), getReplacementString ()); // 컨텐츠 길이 헤더를 업데이트합니다. 업데이트 헤더 (응답, 응답); printwriter out = response.getwriter (); out.write (responseString); } /*** 서브 클래스가 원하는 경우 FilterConfig 객체를 저장합니다. */ public void init (FilterConfig Config) servletexception {this.config = config; } Protected FilterConfig getFilterConfig () {return (config); } public void destrove () {} /*** 교체가 필요한 문자열.* 하위 클래스 에서이 메소드를 무시하십시오. */ public Abstract String getTargetString (); /*** 대상을 대체하는 문자열. 이 메소드를 * 서브 클래스에서 무시하십시오. */ public Abstract String getReplacementString (); /*** 응답 헤더를 업데이트합니다. 이 간단한 버전은 컨텐츠 길이 헤더를 설정합니다. 문자 당 1 바이트를 사용하는* 문자 세트를 사용하고 있다고 가정 할 때* 다른 문자 세트의 경우이 방법을 무시하여* 다른 로직을 사용하거나 지속적인 HTTP 연결을 포기하십시오. */ public void updateHeaders (servletResponse 응답, String responseString) {response.setContentLength (responseString.length ()); }}
Filterutils.java
패키지 com.zj.sample; /*** 문자열을 반환하는 응답 포장지를 지원하는 작은 유틸리티. * /public class filterutils { /*** 주류의 모든 원산지 발생을 대체 할 수 있습니다. */ public static string 교체 (문자열 메인 스트링, 문자열 원리, 문자열 교체) {문자열 result = ""; int oldindex = 0; int index = 0; int origlength = orig.length (); while ((index = mainstring.indexof (Orig, OldIndex))! = -1) {result = result + mainstring.substring (OldIndex, index) + 대체; OldIndex = index + Orylength; } result = result + mainstring.substring (OldIndex); 반환 (결과); }} 7.3.2 문자 교체 필터를 구현합니다. Baidu가 Google (가설)을 인수했다고 가정하면 모든 페이지에 Google이라는 단어가있는 모든 텍스트는 Baidu로 대체되어야합니다! replacesiteNameFilter.java 위의 REPLECTFILTER.java를 상속 하여이 기능을 구현합니다. ReplacesItenamefilter.javapackage com.zj.sample; public class replacesiteNameFilter 확장 replaceFilter {public String getTargetString () {return ( "google.com.cn"); } public String getReplacementString () {return ( "baidu.com"); }}
web.xml
<filter> <filter-name> ReplacesIteNameFilter </filter-name> <filter-class> com.zj.sample.replacesitenamefilter </filter-class> </filter> <filter-mapping> <filter-name> replacesItenameFilter </filter-name> <Url-fattern>/login.jsp </url-potn>
테스트 결과 :
필터링하기 전에
필터링 후
8. 압축 필터
압축 컨텐츠를 처리 할 수있는 몇 가지 최신 브라우저가 있으며, 컨텐츠 인코딩 응답 헤더 값으로 GZIP로 압축 파일을 자동으로 풀고 원본 문서와 마찬가지로 결과를 처리합니다. 이러한 압축 콘텐츠를 보내면 서버에서 문서를 압축하는 데 걸리는 시간이 파일을 다운로드하는 데 걸리는 시간과 비교하여 클라이언트의 문서를 취소하는 데 걸리는 시간이 많기 때문에 많은 시간을 절약 할 수 있습니다. 이 프로그램 Longservlet.java는 압축을위한 성숙한 서블릿 인 길고 중복 된 일반 텍스트 출력이있는 서블릿을 제공합니다. GZIP를 사용하는 경우 출력을 1/300으로 압축 할 수 있습니다!
브라우저 가이 압축 기능을 지원하면 압축 필터는 7 장에 소개 된 chararraywrapper를 사용하여 컨텐츠를 압축 할 수 있습니다. 이 작업을 완료하려면 다음 내용이 필요합니다.
1) 필터 인터페이스를 구현하는 클래스. 이 클래스는 compressionFilter입니다. Init Method는 서브 클래스가 서블릿 환경 또는 필터 이름에 액세스 해야하는 경우 필터 콘피드 오브젝트를 필드에 저장합니다. 로토리 방법의 몸은 비어 있습니다.
2) 랩핑 된 응답 객체. Dofilter 메소드는 ServletResponse 객체를 ChararrayWrapper에 감싸고이 래퍼를 Filterchain 객체의 Dofilter 메소드로 전달합니다. 이 호출이 완료되면 다른 모든 필터와 최종 리소스가 실행되고 출력이 래퍼 내에 있습니다. 이러한 방식으로 원래의 도필터는 모든 리소스의 출력을 나타내는 다양한 문자를 추출합니다. 클라이언트가 압축을 지원한다고 말하면 (즉, gzip을 허용 인코딩 헤더의 값으로 취하는) 필터는 gzipoutputstream을 BytearRayoutputStream에 추가하고 문자 배열을이 스트림에 복사하고 컨텐츠 인코딩 응답 헤더를 GZIP로 설정합니다. 클라이언트가 GZIP를 지원하지 않으면 수정되지 않은 문자 배열을 BytearRayoutputStream에 복사하십시오. 마지막으로, Dofilter는 전체 문자 배열 (아마도 압축)을 원래 응답과 관련된 출력 스트림으로 작성하여 결과를 클라이언트에 보냅니다.
3) Longservlet을 등록하십시오.
compressionFilter.java
package com.zj.sample; import java.io.bytearrayoutputStream; import java.io.ioexception; import java.io.outputStream; import java.io.outputstreamwriter; import java.util.zip.gzipoutputStream; import javax.servlet.filter; javax.servlet.filterchan; javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; import javax.servlet.httpprespone; /** * GZIP로 출력을 압축하는 필터 (브라우저가 * gzip을 지원한다고 가정). */public class compressionFilter는 필터 {private filterconfig config; /*** 브라우저가 GZIP를 지원하지 않으면 자원을 정상적으로 호출하십시오. 브라우저 * <i>가 GZIP를 지원하는 경우 컨텐츠 인코딩 응답 헤더를 설정하고 * 모든 출력을 수집하는 랩핑 된 응답으로 리소스를 호출하십시오. * 출력을 추출하여 gzipped 바이트 어레이에 씁니다. 마지막으로, 해당 배열을 클라이언트의 출력 스트림에 쓰십시오. */ public void dofilter (servletrequest 요청, ServletRepsonge 응답, 필터 체인 체인) servletexception, ioexception {httpservletrequest req = (httpservletrequest) 요청; httpservletresponse res = (httpservletresponse) 응답; if (! isgzipsupported (req)) {// 자원을 정상적으로 호출합니다. Chain.dofilter (req, res); } else {// 브라우저를 알려 주면 GZIPPED 데이터를 보냅니다. res.setheader ( "Content-Encoding", "Gzip"); // 래퍼의 출력을 축적하고 자원을 호출합니다. charArrayWrapper responsewrapper = new CharArrayWrapper (RES); chain.dofilter (req, responsewrapper); // 출력을 나타내는 문자 배열을 가져옵니다. char [] responsechars = responswprapper.tochararray (); // 데이터를 압축하고 바이트 배열에 넣는 작가를 만드십시오. BytearRayoutputStream Bytestream = 새로운 BytearRayoutputStream (); gzipoutputStream Zipout = 새로운 gzipoutputStream (bytestream); outputStreamwriter tempout = new OutputStreamWriter (Zipout); // 원래 출력을 압축하여 바이트 배열에 넣습니다. tempout.write (responsechars); // GZIP 스트림은 명시 적으로 닫아야합니다. tempout.close (); // 컨텐츠 길이 헤더를 업데이트합니다. res.setContentLength (bytestream.size ()); // 클라이언트에게 압축 결과를 보냅니다. outputStream realout = res.getOutputStream (); bytestream.writeto (Realout); }} /*** 서브 클래스가 원하는 경우 FilterConfig 객체를 저장합니다. */ public void init (FilterConfig Config) servletexception {this.config = config; } Protected FilterConfig getFilterConfig () {return (config); } public void destroy () {} private boolean isgzipsupported (httpservletrequest req) {String BrowserEncodings = req.getheader ( "accept-encoding"); return ((browserencodings! = null) && (browserencodings.indexof ( "gzip")! = -1); }} longservlet.javapackage com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httrequestrequestrequestrequestrequestrequestrequestrequestrectp.htttp.http.http.http.http.http javax.servlet.http.httpservletresponse; /*** <b> long </b> 출력이있는 서블릿. 9 장의 압축 효과를 테스트하는 데 사용됩니다. */ public class longservlet는 httpservlet {public void doget (httpservletrequest request, httpservletreponse 응답)을 servletexception, ioexception {response.setContentType ( "text/ html"); printwriter out = response.getwriter (); 문자열 doctype = "<! doctype html public/"-// w3c // dtml 4.0 " +"Transitional // en/">/n"; 문자열 제목 = "긴 페이지"; out.println (doctype + "<html>/n" + "<head> <title>" + title + "</title> </head>/n" + "<body bgcolor =/"#fdf5e6/">/n" + "<h1 align =/"center/">" + title + "</h1>/n"); String line = "Blah, Blah, Blah, Blah, Blah." + "Yadda, Yadda, Yadda, Yadda."; for (int i = 0; i <10000; i ++) {out.println (line); } out.println ( "</body> </html>"); }}
web.xml
<filter> <filter-name> compressionFilter </filter-name> <filter-class> com.zj.sample.compressionfilter </filter-class> </filter> <filter-mapping> <filter-name> compressionfilter </filter-name> longservlet </servlet-name> </filter-mapping> <servlet-name> longservlet </servlet-name> <servlet-class> com.zj.sample.longservlet </servlet-class> </servlet> <servlet-mapping> <servlet-name> longservlet </servlet-name> <url-pattern>/longservlet </url-pattern> </servlet-mapping>