Java Web之三 Servlet Filter Listener

来源:互联网 发布:阿里云开启80端口 编辑:程序博客网 时间:2024/05/17 23:15

Servlet

1.什么是Servlet

Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中(如Tomcat Servlet容器负责Servlet和客户的通信以及调用Servlet的方法)。

Servlet可完成如下功能:

创建并返回基于客户请求的动态HTML页面

创建可嵌入到现有HTML页面中的部分HTML页面

与其他服务器资源(java程序、数据库)进行通信

2.Servlet的HelloWorld

(1)新建一个java类实现Servlet

public class HelloServlet implements Servlet{@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("init");}@Overridepublic ServletConfig getServletConfig() {System.out.println("getServletConfig");return null;}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("service");}@Overridepublic String getServletInfo() {System.out.println("getServletInfo");return null;}@Overridepublic void destroy() {System.out.println("destroy");}}</span>
(2)web.xml中注册和映射

<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.ithings.servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>helloServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping></web-app>

3.Servlet的生命周期

(1)构造器:只被调用一次。第一次请求Servlet时创建Servlet的实例,调用构造器。Servlet是单例的
(2)init:只被调用一次。在创建好实例后立即被调用。
(3)service:每次请求都会调用,实际用于响应请求
(4)destory:只被调用一次。当前Servlet所在的web应用被卸载前调用,用于释放当前Servlet所占用的资源


4.load-on-startup参数

用以指定Servlet被创建的时机。若为负数,则在第一次请求时被创建。若为0或正数,则在当前web应用被Servlet容器加载时创建,且数组越小越早被创建。

<servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.ithings.servlet.HelloServlet</servlet-class><load-on-startup>1</load-on-startup></servlet>

5.<serlvet-mapping>通配符

可以用*匹配符配置<serlvet-mapping>,但是要注意,必须是*.do或者/开头的以/*结束的路径。/*.jsp不合法

对于如下的一些映射关系:

Servlet1 映射到 /abc/* 

Servlet2 映射到 /* 

Servlet3 映射到 /abc 

Servlet4 映射到 *.do 

问题:

当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应.        

【Servlet引擎将调用Servlet1。】

当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应.           

【Servlet引擎将调用Servlet3。】

当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应.  

【Servlet引擎将调用Servlet1。】

当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应.                            

【Servlet引擎将调用Servlet2。】

当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应.    

【Servlet引擎将调用Servlet2。】


6.ServletConfig

(1)getInitParameter(String name) 获取Servlet中配置的初始化参数

<servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.ithings.servlet.HelloServlet</servlet-class><init-param><param-name>username</param-name><param-value>Tom</param-value></init-param></servlet>String username = servletConfig.getInitParameter("username");

(2)getInitParameterNames() 获取Servlet初始化参数的名称列表

<servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.ithings.servlet.HelloServlet</servlet-class><init-param><param-name>username</param-name><param-value>Tom</param-value></init-param><init-param><param-name>password</param-name><param-value>123</param-value></init-param></servlet>Enumeration<String> names = servletConfig.getInitParameterNames();while(names.hasMoreElements()){String paramName = names.nextElement();System.out.println(paramName);}
(3)getServletContext() 返回ServletContext(当前web应用)

(4)getServletName() 返回servlet-name

7.ServletContext

(1)可由ServletConfig获取

servletCOnfig.getServletContext();

(2)代表当前web应用,可从中获取当前web应用的各个信息

1)getInitParameter(String name) getInitParameterNames() 获取当前web应用的初始化参数

<span style="white-space:pre"></span><context-param><param-name>driver</param-name><param-value>com.mysql.jdbc.Driver</param-value></context-param>ServletContext servletContext = servletConfig.getServletContext();String driverName = servletContext.getInitParameter("driver");Enumeration names = servletContext.getInitParameterNames();while(names.hasMoreElements()){String paramName = (String) names.nextElement();System.out.println(paramName);}

2)getRealPath(String path) 获取部署在服务器上的绝对路径,而不是部署前的路径

3)getContextPath() 获取当前web应用的名称

4)获取当前web应用的某一个文件对应的输入流

InputStream in = servletContext.getResourceAsStream("db.properties");//使用classloaderClassLoader classLoader = getClass().getClassLoader();        InputStream in = classLoader.getResourceAsStream("db.properties");        System.out.println(in);


8.ServletRequest & ServletResponse

ServletRequest

(1)获取请求参数1)String getParameter(String name) 2)String[] getParameterValues(String name)3)Map getParameterMap()  Map<String,String[]> map = request.getParameterMap();        for(Map.Entry<String,String[]> entry : map.entrySet()){            System.out.println(entry.getKey());            System.out.println(entry.getValue());        }4)Enumeration getParameterNames()  Enumeration names = request.getParameterNames();        while(names.hasMoreElements()){            String name = (String) names.nextElement();        }(2)获取请求的URIHttpServletRequest httpServletRequest = (HttpServletRequest)request;String requestURI = httpServletRequest.getRequestURI();System.out.println(requestURI); //  /HelloFilter/hello(3)获取请求方式 GET/POSTString method = httpServletRequest.getMethod();System.out.println(method);// POST(4)针对GET请求,获取?后的字符串String queryString = httpServletRequest.getQueryString();System.out.println(queryString);// username=aa&password=123(5)获取请求的servlet的路径String servletPath = httpServletRequest.getServletPath();System.out.println(servletPath);//  /hello

ServletResponse

(1)getWriter() 返回PrintWriter对象,调用该对象的print() 方法,把print()中的参数直接打印到客户的浏览器上(2)setContentType()设置相应的内容类型application/msword:word文档

9.GenericServlet

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable

(1)是Servlet接口和ServletConfig接口的实现类,但是一个抽象类,其中的service方法为抽象方法

(2)如果新建的Servlet程序直接继承GenericServlet会使开发更简洁

(3)具体实现:

1)在GenericServlet中声明了一个ServletConfig类型的成员变量,在init(ServletConfig)方法中对其进行了初始化

2)利用ServletConfig成员变量的方法实现了ServletConfig接口的方法

3)还定义了一个init()方法,在init(ServletConfig)方法中对其调用,子类可以直接覆盖init(),在其中实现对Servlet的初始化

4)不建议直接覆盖init(ServletConfig),因为如果忘记写super(ServletConfig),则会出现空指针异常

10.HttpServlet

(1)继承自GenericServlet

(2)在service方法中直接把ServletRequest和ServletResponse转为HttpServletRequest和HttpServletResponse,并调用重载了的service(HttpServletRequest, HttpServletResponse);

(3)实际应用中,直接继承HttpServlet即可


Filter


1.什么是Filter

(1)Filter可以对发送到Servlet的请求进行拦截,并对响应进行拦截

(2)Filter程序是一个实现了Filter接口的Java类,与Servlet程序相似,它由Servlet容器进行调用和执行(Servlet API中定义了三个接口类:Filter、FilterChain、FilterConfig)

(3)Filter程序需要在web.xml文件中进行注册和设置它要拦截的资源(JSP、Servlet、静态图片文件和静态html文件)

2.Filter的HelloWorld

(1)新建一个java类实现Filterpublic class FirstFilter implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("init");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("do");chain.doFilter(request, response);}@Overridepublic void destroy() {System.out.println("destory");}}(2)web.xml中注册和映射<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><filter><filter-name>firstFilter</filter-name><filter-class>com.ithings.FirstFilter</filter-class><init-param><param-name>param</param-name><param-value>value</param-value></init-param></filter><filter-mapping><filter-name>firstFilter</filter-name><url-pattern>/*.jsp</url-pattern></filter-mapping></web-app>

3.Filter的API

(1)public void init(FilterConfig filterConfig)

1)在创建Filter对象被加载时立即被调用,只调用一次。Filter实例是单例的。

2)FilterConfig相当于ServletConfig

3)可以在web.xml中配置当前Filter的初始化参数。配置方式也和Servlet类似。

<filter><filter-name>filterTest</filter-name><filter-class>com.ithings.FilterTest</filter-class><init-param><param-name>param</param-name><param-value>value</param-value></init-param></filter>

(2)public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

1)真正的Filter拦截的代码写在该方法中,每次拦截都会调用该方法

2)FilterChain:Filter链,多个Filter组成一个Filter链

doFilter(ServletRequest request, ServletResponse response) 

把请求传给Filter链的下一个Filter,若当前Filter是Filter链的最后一个Filter,把请求给目标Servlet或JSP

多个Filter拦截的顺序和web.xml文件中配置的filter-mapping的顺序有关

(3)public void destroy()

4 dispatcher元素:指定过滤器所拦截的资源被Servlet容器调用的方式

可以是REQUEST、 INCLUDE、 FORWARD、 ERROR之一,默认REQUEST。可以设置多个<dispatcher>子元素用来指定Filter对资源的多种调用方式进行拦截

    <filter-mapping>        <filter-name>firstFilter</filter-name>        <url-pattern>/hello.jsp</url-pattern>        <dispatcher>REQUEST</dispatcher>    </filter-mapping>

(1)REQUEST:通过GET或POST请求直接访问

(2)FORWARD:通过RequestDispatcher的forward()方法访问

(3)INCLUDE:通过RequestDispatcher的include()方法访问

(4)ERROR:如果目标资源是通过声明式异常处理机制调用时,该过滤器被调用

处理异常的几种方式:1)page指令:<%@ page errorPage="error.jsp" >2)web.xml中配置<error-page><exception-type>java.lang.ArithmeticException</exception-type><location>/error.jsp</location></error-page>3)dispatcher<filter-mapping><filter-name>firstFilter</filter-name><url-pattern>/error.jsp</url-pattern><dispatcher>ERROR</dispatcher></filter-mapping>

5 自定义HttpFilter 

public abstract class HttpFilter implements Filter{private FilterConfig filterConfig;/* * 不建议子类直接覆盖,会造成filterConfig初始化失败 */@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;}/* * 供子类继承的初始化方法 */protected void init(){}/* * 直接返回init(FilterConfig filterConfig)的filterConfig对象 */public FilterConfig getFilterConfig() {return filterConfig;}/* * 原生的doFilter方法,不建议子类直接覆盖 */@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException{HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)res;this.doFilter(request, response, chain);}/* * 抽象方法,需要子类实现 */public abstract void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException;@Overridepublic void destroy() {}}

6. Filter实例之禁用浏览器缓存

public class NoCacheHttpFilter extends HttpFilter{@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {response.setDateHeader("Expires", -1);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");chain.doFilter(request, response);}}

7. Filter实例之设置字符集

public class EncodingFilter extends HttpFilter{@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {//从初始化参数中获取Encoding的值String encoding = getFilterConfig().getServletContext().getInitParameter("encoding");//设置字符集request.setCharacterEncoding(encoding);//放行chain.doFilter(request, response);}}

8.Filter实例之登陆验证

web.xml 

    <!--用户信息放入session中的名称-->    <context-param>        <param-name>userSessionKey</param-name>        <param-value>USERSESSIONKEY</param-value>    </context-param>        <!--未登录,重定向的页面-->    <context-param>        <param-name>redirectPage</param-name>        <param-value>/login/login.jsp</param-value>    </context-param>        <!--不需要拦截的URL列表-->    <context-param>        <param-name>uncheckedUrls</param-name>        <param-value>/login/a.jsp,/login/list.jsp,/login/login.jsp,/login/doLogin.jsp</param-value>    </context-param>        <filter>        <filter-name>loginFilter</filter-name>        <filter-class>com.ithings.filter.LoginFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>loginFilter</filter-name>        <url-pattern>/login/*</url-pattern>    </filter-mapping>

LoginFilter.java

<span style="white-space:pre"></span>public class LoginFilter extends HttpFilter{private String sessionKey = null;private String redirectPage = null;private String uncheckedUrls = null;@Overrideprotected void init(){//从初始化参数中获取sessionKey,redirectPage,uncheckedUrlsServletContext servletContext = getFilterConfig().getServletContext();sessionKey = servletContext.getInitParameter("userSessionKey");redirectPage = servletContext.getInitParameter("redirectPage");uncheckedUrls = servletContext.getInitParameter("uncheckedUrls"); }@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {//1.判断ServletPath是否为不需要检查的url,是则直接放行String servletPath = request.getServletPath();List<String> urls = Arrays.asList(uncheckedUrls.split(","));if(urls.contains(servletPath)){chain.doFilter(request, response);return;}//2.从session中获取sessionKey对应的值,若值不存在,则重定向到redirectPage,若存在,则放行Object user = request.getSession().getAttribute(sessionKey);if(user == null){response.sendRedirect(request.getContextPath() + redirectPage);}else{chain.doFilter(request, response);}}}

9.HttpServletRequestWrapper

(1)包装类public class MyHttpServletRequest extends HttpServletRequestWrapper{public MyHttpServletRequest(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name){String val = super.getParameter(name);if(val != null && val.contains(" fuck ")){val.replace(" fuck ", " **** ");}return val;}}(2)使用HttpServletRequest req = new MyHttpServletRequest(request);chain.doFilter(req, response);

Listener

1.监听域对象自身的创建和销毁的事件监听器 ServletContextListener、HttpSessionListener、HttpServletRequest  

(1)ServletContextListener 创建类,实现ServletContextListener接口

public class HelloServletContextListener implements ServletContextListener{@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("ServletContextListener..init..");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("ServletContextListener..destory..");}}
(2)web.xml中注册   

    <listener>        <listener-class>com.ithings.listener.HelloServletContextListener</listener-class>    </listener>

(3)应用

1)创建数据库连接池

2)创建Spring的IOC容器

3)读取当前WEB应用的初始化参数

(4)API

    //ServletContext对象被创建即当前web应用被加载时,Servlet容器调用该方法    public void contextInitialized(ServletContextEvent sce);    //ServletContext对象被销毁即当前web应用被销毁时,Servlet容器调用该方法    public void contextDestroyed(ServletContextEvent sce);

(5)ServletRequestListener、HttpSessionListener

public class HelloServletContextListener implements ServletContextListener,ServletRequestListener,HttpSessionListener{@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("ServletContext 被创建");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("ServletContext 被销毁");}@Overridepublic void requestInitialized(ServletRequestEvent sre) {System.out.println("ServletRequest 被创建");}@Overridepublic void requestDestroyed(ServletRequestEvent sre) {System.out.println("ServletRequest 被销毁");}@Overridepublic void sessionCreated(HttpSessionEvent se) {System.out.println("HttpSession 被创建");}@Overridepublic void sessionDestroyed(HttpSessionEvent se) {System.out.println("HttpSession 被销毁");}}

2.监听域对象中属性的增加和删除的事件监听器 ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener

public class HelloAttributeListener implements ServletContextAttributeListener, HttpSessionAttributeListener,ServletRequestAttributeListener{  //添加属性时调用    public void attributeAdded(ServletContextAttributeEvent event) {}//移除属性时调用    public void attributeRemoved(ServletContextAttributeEvent event) {}//替换属性时调用    public void attributeReplaced(ServletContextAttributeEvent event) {}    public void attributeAdded(HttpSessionBindingEvent event) {}    public void attributeRemoved(HttpSessionBindingEvent event) {}    public void attributeReplaced(HttpSessionBindingEvent event) {}//可以获取到添加的属性名和属性值    public void attributeAdded(ServletRequestAttributeEvent srae) {        System.out.println("向request中添加了一个属性 " + srae.getName() +" : " + srae.getValue());}    public void attributeRemoved(ServletRequestAttributeEvent srae){}    public void attributeReplaced(ServletRequestAttributeEvent srae) {}}

在web.xml中注册
    <listener>        <listener-class>com.ithings.listener.HelloAttributeListener</listener-class>    </listener>

3.监听绑定到HttpSession域中的某个对象的状态的事件监听器 HttpSessionBindingListener、HttpSessionActivationListener

(1)该监听器不需在web.xml中注册。注:该监听器很少被使用

(2)HttpSessionBindingListener

public class Customer implements HttpSessionBindingListener{/* * 当前对象被绑定到session时调用该方法 */@Overridepublic void valueBound(HttpSessionBindingEvent event) {System.out.println("绑定到session");//提供的三个方法Object value = event.getValue();String sessionName = event.getName();HttpSession session = event.getSession();}/* * 当前对象从session解除时调用该方法 */@Overridepublic void valueUnbound(HttpSessionBindingEvent event) {System.out.println("从session移除");}}<%Customer customer = new Customer();session.setAttribute("customer",customer);System.out.println("---------------------");session.removeAttribute("customer");%>

(3)HttpSessionActivationListener

监听实现了该接口和Serializable的java类。session对象存储在tomcat服务器的work\Catalina\localhost\contextPath目录下

public class HelloHttpSessionBindingListener implements HttpSessionActivationListener,Serializable{@Overridepublic void sessionWillPassivate(HttpSessionEvent se) {System.out.println("向磁盘中写入session对象");}@Overridepublic void sessionDidActivate(HttpSessionEvent se) {System.out.println("从磁盘中读取session对象");}}









0 0
原创粉丝点击