Filter 技术是servlet 2.3新增加的功能。servlet2.3是sun公司于2000年10月发布的,它的开发者包括许多个人和公司团体,充分体现了sun公司所倡导的代码开放性原则。在众多参与者的共同努力下,servlet2.3比以往功能都强大了许多,而且性能也有了大幅提高。
一、Filter(过滤器)
1.过滤器的概念
Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。
优点:过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题
2.过滤器的作用描述
- 在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。
- 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。
- 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
二、Filter体系结构
Filter接口
Servlet API提供三个接口类供我们编写:javax.servlet.Filter;FilterChain和FilterConfig,作为Servlet的拦截器。
- FilterConfig在重写Filter接口时,在init方法里主要通过getInitParameter("参数名")调用web.xml里的配置信息。在destroy里付值null销毁.
- FilterChain在重写Filter接口时,在doFilter方法里通过FilterChain的对象调用doFilter(request,responte)来开始调用Servlet
- Filter重写三个方法init;destroy;doFilter。
可以根据WEB.XML里对Filter的配置来组成Filter链,在配置中的前一个Filter里调用FilterChain的doFilter会跳到配置的下一个去,最后一个就会跳到Servlet去。
HttpServlet类
当编写一个Servlet时,必须直接或间接实现Servlet接口,最可能实现的方法就是扩展javax.servlet.GenericServlet或javax.servlet.http.HttpServlet当实现javax.servlet.Servlet接口时必须实现5个方法
init(ServletConfig config)
service(ServletRequest req,ServletResponse resp)
destroy()
getServletConfig()
getServletInfo()
别的方法就不说了
service是执行应用逻辑的入口点,包容器调用此方法来响应进来得请求,只是在servlet被成功初始化后才能调用它
其实servlet和applet差不多,当一个servlet被实例化后,包容器自动去调用固定的方法首先是init(),然后是service().....
所以service必须有.
GenericServlet类提供了Servlet接口的基本实现,所以他的子类都必须实现service()方法
HttpServlet类扩展了GenericServlet并且提供了Servlet接口中具体于HTTP的实现它更 象一个其他所有的servlet都要扩展的类,其中他定义了两种形式的service方法:
service(Servirequest req,Servletresponse resp)
此方法是GenericServlet的service()方法的实现,他把resquest,response对象分别转化为HttpServletRequest和HttpServletResponse并且调用下面重载的service()方法,所以不应当重载上面的service()方法:
protect void service(HttpServirequest req,HttpServletresponse resp)
他用HTTP的request,response对象作为参数,并且由上面的方法调用,HttpServlet实现这个方法后就成为一个HTTP请求的分发者,他把请求代理给doGet(),doPost().....等doXXXX()方法,因此不应当重载他.
当包容器为一个servlet收到一个请求时,包容器调用公共的service方法在把参数转换为HttpServirequest,HttpServletresponse 后,这个公共的方法调用保护的service根据HTTP请求方法的类型,保护的service方法调用doXXXX()方法之一.
doGet()方法是当得到一个GET类型的请求时调用,把内容放在url上传输,所以最多只能传输240个字节
doPost()方法是当得到一个POST类型的请求时调用
三、多个Filter拦截的顺序
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
四、字符编码过滤器
示例:
index.jsp
<body>
<h2>这里是主页面</h2>
用户名:${uname}<br/>
密码:${upass}
</body>
loginTwo.jsp <body> <h1>登录界面二</h1> <form action="loginTwo.do" method="post"> 用户名:<input type="text" name="uname" /> <br/> 密码:<input type="password" name="upass" /> <br/> <input type="submit" value="登录" /> <br/> </form> </body>
loginOne.jsp<body><h1>登录界面一</h1><form action="loginTwo.do" method="post">用户名:<input type="text" name="uname"><br/>密码:<input type="password" name="upass"><br/><input type="submit" value="登录"><br/></form></body>
success.jsp
<body>
用户名:${uname}<br/>
密码:${upass}
</body>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Web_16</display-name>
<!-- 配置编码filter -->
<filter>
<filter-name>EncodingOneFilter</filter-name>
<filter-class>com.sun.filter.EncodingFilter</filter-class>
</filter>
<!-- 映射Filter -->
<filter-mapping>
<filter-name>EncodingOneFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- 配置编码filter -->
<!-- <filter>
<filter-name>EncodingTwoFilter</filter-name>
<filter-class>com.sun.filter.EncodingFilter</filter-class>
</filter> -->
<!-- 映射Filter -->
<!-- <filter-mapping>
<filter-name>EncodingTwoFilter</filter-name>
<url-pattern>/loginTwo.do</url-pattern>
</filter-mapping> -->
<!--配置servlet-->
<servlet>
<servlet-name>loginOneServlet</servlet-name>
<servlet-class>com.sun.servlet.loginOneServlet</servlet-class>
</servlet>
<!-- 映射 -->
<servlet-mapping>
<servlet-name>loginOneServlet</servlet-name>
<url-pattern>/loginOne.do</url-pattern>
</servlet-mapping>
<!--配置servlet-->
<servlet>
<servlet-name>loginTwoServlet</servlet-name>
<servlet-class>com.sun.servlet.loginTwoServlet</servlet-class>
</servlet>
<!-- 映射 -->
<servlet-mapping>
<servlet-name>loginTwoServlet</servlet-name>
<url-pattern>/loginTwo.do</url-pattern>
</servlet-mapping>
<!-- 配置filter(1) -->
<filter>
<filter-name>OneFilter</filter-name>
<filter-class>com.sun.filter.OneFilter</filter-class>
</filter>
<!-- 映射filter -->
<filter-mapping>
<filter-name>OneFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
<!-- 配置filter(2) -->
<filter>
<filter-name>TwoFilter</filter-name>
<filter-class>com.sun.filter.TwoFilter</filter-class>
</filter>
<!-- 映射filter -->
<filter-mapping>
<filter-name>TwoFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
<!-- 配置filter(3)-->
<filter>
<filter-name>ThreeFilter</filter-name>
<filter-class>com.sun.filter.ThreeFilter</filter-class>
</filter>
<!-- 映射filter -->
<filter-mapping>
<filter-name>ThreeFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
public class EncodingFilter extends HttpFilter{
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
//放出
chain.doFilter(request, response);
System.out.println("进来啦........");
}
}
public class loginOneServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //super.doPost(req, resp); String uname=req.getParameter("uname"); String upass=req.getParameter("upass"); System.out.println("uname:"+uname+" upass:"+upass); req.setAttribute("uname", uname); req.setAttribute("upass", upass); req.getRequestDispatcher("success.jsp").forward(req, resp); } }
public class loginTwoServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
//super.doPost(req, resp);
String uname=req.getParameter("uname");
String upass=req.getParameter("upass");
System.out.println("uname:"+uname+" upass:"+upass);
req.setAttribute("uname", uname);
req.setAttribute("upass", upass);
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
五、Filter的<dispatcher>
<dispatcher>子元素可以设置的值及其意义
REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除
此之外,过滤器不会被调用。
六、检查用户是否登陆
示例:
list.jsp
<body>
你好:${uname}<br/>
<a href="one.jsp">跳至one.jsp</a><br/>
<a href="two.jsp">跳至two.jsp</a><br/>
<a href="three.jsp">跳至three.jsp</a><br/>
</body>
login.jsp
<body>
<h1>登录页面</h1>
<form action="login.do" method="post">
用户名:<input type="text" name="uname"/><br/>
密码:<input type="password" name="upass"/><br/>
<input type="submit" value="登录"/>
</form>
</body>
one.jsp
<body>
这是One.jsp网页
</body>
two.jsp
<body>
这是Two.jsp网页
</body>
three.jsp
<body>
这是Three.jsp网页
</body>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Web_17</display-name>
<!-- 配置默认放行文件 -->
<context-param>
<param-name>discharged</param-name>
<param-value>/login.jsp,/list.jsp,/login.do,/three.jsp</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 配置登录的servlet -->
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.sun.servlet.LoginServlet</servlet-class>
</servlet>
<!-- 映射登录的servlet -->
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
<!-- 配置过滤器 -->
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.sun.filter.LoginFilter</filter-class>
</filter>
<!-- 映射过滤器 -->
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Loginservlet.class
public class LoginServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取登录的用户名密码
String uname=req.getParameter("uname");
String upass=req.getParameter("upass");
if("admin".equals(uname)&&"123".equals(upass)){
//存值
HttpSession session=req.getSession();
//跳转
session.setAttribute("uname",uname);
session.setAttribute("upass",upass);
req.getRequestDispatcher("list.jsp").forward(req, resp);
}else{
//登录不成功,重定向到login.jsp
resp.sendRedirect("login.jsp");
}
}
}
LoginFilter.class
public class LoginFilter extends HttpFilter{
private List<String> list;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取servletContext(application)中的值
ServletContext servletContext=filterConfig.getServletContext();
//获取应用程序初始化的配置信息
String discharged=servletContext.getInitParameter("discharged");
//将配置信息转成集合
String[] str=discharged.split(",");
list=Arrays.asList(str);
System.out.println("discharged"+discharged);
}
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
//获取请求路径
String path=request.getServletPath();
System.out.println(path);
//判断是否包含,包含就放行,不包含继续判断
if(list.contains(path)){
System.out.println("放行啦....");
chain.doFilter(request, response);
}else{
//获取session中的值
HttpSession session=request.getSession();
Object name=session.getAttribute("uname");
if(name!=null){
System.out.println("终于放行啦....");
chain.doFilter(request, response);
}else{
//重定向到登录页面
response.sendRedirect("login.jsp");
}
}
}
}
loginOne.jsp