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对象");}}
- Java Web之三 Servlet Filter Listener
- java-web三大组件(Servlet/Filter/Listener)
- Java Web 之 Servlet - Listener、Filter、Decorator 精辟
- java web.xml listener filter servlet
- java filter servlet listener
- JAVA基础(三) web.xml 中的listener、 filter、servlet 加载顺序及其详解
- web.xml之context-param,listener,filter,servlet加载顺序
- Listener、Filter、Servlet与Java Web项目初始化的工作
- Java web项目listener Filter servlet启动顺序和配置
- Java web项目listener Filter servlet启动顺序和配置
- Java web项目listener Filter servlet启动顺序和配置
- Java web项目listener Filter servlet启动顺序和配置
- java web.xml listener servlet 和filter的加载顺序
- java web servlet/filter/listener/interceptor区别与联系
- [Java Web]servlet/filter/listener/interceptor区别与联系
- Java中Filter、Servlet、Listener
- Java中Filter、Servlet、Listener
- Java的Listener、Filter、Servlet
- 继续下一阶段学习
- C++学习中的函数模版(显式具体化、隐式具体化、显式实例化)
- Andriod从入门到精通第2章:Android模拟器与常用命令
- zend 实现多数据库却换
- MT6589开机启动简析
- Java Web之三 Servlet Filter Listener
- HDU 3681 Prison Break floyd+状压+二分
- ubuntu+php环境下的Memcached 安装方法
- Perl——数组、foreach
- Ext JS4序列教程之一 :Layout布局
- Javascript 中的false、0、null、undefined和空字符串对象
- dom4j 把 文本 转成 XML
- Android:BaseAdapter优化之ViewHolder 显示系统已经安装应用并打开
- 秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别