JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)
JavaEE学习日志(六十)
过滤器
过滤器:符合条件的过去,不符合条件的不能过。
客户端需要访问目标资源,在客户端和资源之间设置过滤器。
符合则放行。
过滤器快速入门
- 定义类,实现接口Filter
- 重写抽象方法
- 在web.xml配置(注解)
现在有一个servlet1
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("servlet1");
System.out.println("servlet1");
}
servlet2
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("servlet2");
System.out.println("servlet2");
}
过滤器1
package com.itheima.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器MyFilter");
//放行,允许访问目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
过滤器2
package com.itheima.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器MyFilter2");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
配置xml:过滤器1对所有servlet进行过滤;过滤器2只对servlet2进行过滤
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--
过滤器配置
和Servlet配置方式基本一致
-->
<filter>
<filter-name>my</filter-name>
<filter-class>com.itheima.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>my</filter-name>
<!--
配置的是过滤器需要配置的资源
/* 过滤WEB应用下的所有资源
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>my2</filter-name>
<filter-class>com.itheima.filter.MyFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>my2</filter-name>
<!--
只过滤Servlet2
-->
<url-pattern>/servlet2</url-pattern>
</filter-mapping>
</web-app>
过滤器的执行过程
过滤器的生命周期
- 过滤器对象的创建:Tomcat服务器启动
init(FilterConfig config)
过滤器对象被创建时调用,FilterConfig对象由Tomcat引擎创建 - 过滤器执行过滤的方法:过滤被访问的资源时执行,资源必须被过滤器过滤
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
- 过滤器销毁的方法:销毁之前调用,服务器关闭之前(或项目删除)调用
destroy()
过滤器的配置
- 完全匹配:只过滤指定的资源
<url-pattern>/servlet2</url-pattern>
- 目录匹配(最实用):
/abc/*
过滤abc目录下的所有资源
<url-pattern>/abc/*</url-pattern>
- 后缀名匹配:一般不使用
*.jsp
访问所有的jsp文件都过滤
<url-pattern>*.jsp</url-pattern>
过滤器的注解配置
@WebFilter(urlPatterns="/过滤资源 ")
过滤器的执行顺序
web.xml配置:配置文件的编写顺序决定运行的顺序。准确的说,根据mapping的顺序决定。
注解开发:按照类名的自然顺序运行,如AFilter比BFilter先运行。
注意:
- 如果有配置文件,则配置文件优先执行。
- 如果配置文件和注解并存,则两者都会运行。
过滤器的拦截方式
默认方式一:REQUEST,请求时拦截
<filter-mapping>
<filter-name>my</filter-name>
<!--
配置的是过滤器需要配置的资源
/* 过滤WEB应用下的所有资源
-->
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
方式二:FORWARD,转发时拦截
<dispatcher>FORWARD</dispatcher>
方式三:INCLUDE,包含时拦截
<dispatcher>INCLUDE</dispatcher>
方式三:ERROR,错误时拦截
<dispatcher>ERROR</dispatcher>
拦截方式写在注解中
@WebFilter(urlPatterns = "/*",dispatcherTypes = {DispatcherType.FORWARD})
过滤器解决全站中文乱码
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class ChinaFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//设置request对象的编码表
servletRequest.setCharacterEncoding("utf-8");
//设置response缓冲区的编码表,并通知浏览器解码
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
监听器
监听器:监听某个组件变化的对象,事件源是固定的,主要是request,session,servletContext域对象
监听的是域对象的变化:
- 域对象的创建和销毁
- 域对象中存储数据的变化
ServletContext监听器入门
实现步骤
- 创建类实现监听器接口ServletContextListener
- 重写抽象方法
- web.xml配置(注解)
package com.itheima.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
/*
ServletContext对象被创建时调用
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象创建");
}
/*
被销毁前调用
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象销毁");
}
}
如果使用配置文件
<listener>
<listener-class>com.itheima.listener.MyServletContextListener</listener-class>
</listener>
ServletContextEvent对象方法
Object getSource()
获取到被监听的事件源ServletContext getServletContext()
获取到被监听的事件源
除了返回值以外,这两个方法的功能一样。这样设计的目的是为了通用性。其他监听器事件对象,都有一个共同的方法getSource();
package com.itheima.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
/*
ServletContext对象被创建时调用
ServletContextEvent方法参数:ServletContext域对象的事件对象
此方法由Tomcat引擎创建
ServletContextEvent方法:
Object getSource() 获取到被监听的事件源
ServletContext getServletContext() 获取到被监听的事件源
除了返回值以外,功能一样。这样设计的目的是为了通用性。其他监听器事件对象,
都有一个共同的方法getSource();
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext context = (ServletContext)servletContextEvent.getSource();
System.out.println(context);
ServletContext context2= servletContextEvent.getServletContext();
System.out.println(context2);
System.out.println("ServletContext域对象创建");
}
/*
被销毁前调用
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象销毁");
}
}
Servlet抽取
对于一个商品数据,基本的功能有4个,增删改查。
会有一个问题:Servlet会越来越多
解决方法:Servlet抽取。
基本抽取
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
用户操作Servlet
登录 login
注册 register
修改密码 updatePassword
退出 loginOut
共性:接收请求,实现响应
4个方法的参数:request,response
需要客户端配合:使用功能的时候,提交一个参数
Servlet判断参数是什么,选择调用哪个方法
*/
@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取提交的参数
String md = request.getParameter("method");
//判断参数,调用不同的方法
if("login".equals(md)){
login(request,response);
}else if ("register".equals(md)){
register(request,response);
}else if ("updatePassword".equals(md)){
updatePassword(request,response);
}else if ("loginOut".equals(md)){
loginOut(request,response);
}
}
//登录 login
public void login(HttpServletRequest request, HttpServletResponse response){
System.out.println("登录");
}
//注册 register
public void register(HttpServletRequest request, HttpServletResponse response){
System.out.println("注册");
}
//改密 updatePassword
public void updatePassword(HttpServletRequest request, HttpServletResponse response){
System.out.println("修改密码");
}
//登出 loginOut
public void loginOut(HttpServletRequest request, HttpServletResponse response){
System.out.println("登出");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
<%--超链接,服务器端的提交,在请求地址上用?拼接参数--%>
<a href="${pageContext.request.contextPath}/user?method=login">登录</a><br>
<a href="${pageContext.request.contextPath}/user?method=register">注册</a><br>
<a href="${pageContext.request.contextPath}/user?method=updatePassword">修改密码</a><br>
<a href="${pageContext.request.contextPath}/user?method=loginOut">退出</a><br>
基本抽取优化
使用反射进行优化:不写一个if语句
@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//获取提交的参数
String md = request.getParameter("method");
//换一个思考方式:不写if 使用反射
//反射技术获取方法执行
Class clazz = this.getClass();
//获取方法
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
//执行方法,对象,实际参数
method.invoke(this,request,response);
}catch (Exception e){
e.printStackTrace();
}
}
//登录 login
public void login(HttpServletRequest request, HttpServletResponse response){
System.out.println("登录");
}
//注册 register
public void register(HttpServletRequest request, HttpServletResponse response){
System.out.println("注册");
}
//改密 updatePassword
public void updatePassword(HttpServletRequest request, HttpServletResponse response){
System.out.println("修改密码");
}
//登出 loginOut
public void loginOut(HttpServletRequest request, HttpServletResponse response){
System.out.println("登出");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
BaseServlet抽取
BaseServlet
public abstract class BaseServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//获取提交的参数
String md = request.getParameter("method");
//换一个思考方式:不写if 使用反射
//反射技术获取方法执行
Class clazz = this.getClass();
//获取方法
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
//执行方法,对象,实际参数
method.invoke(this,request,response);
}catch (Exception e){
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
其他的Servlet继承BaseServlet,不再继承HttpServlet
@WebServlet(urlPatterns = "/product")
public class ProductServlet extends BaseServlet {
//添加 addProduct
public void addProduct(HttpServletRequest request, HttpServletResponse response){
System.out.println("添加商品");
}
//添加 addProduct
public void updateProduct(HttpServletRequest request, HttpServletResponse response){
System.out.println("更新商品");
}
//添加 addProduct
public void delProduct(HttpServletRequest request, HttpServletResponse response){
System.out.println("删除商品");
}
}
@WebServlet(urlPatterns = "/user")
public class UserServlet extends BaseServlet {
//登录 login
public void login(HttpServletRequest request, HttpServletResponse response){
System.out.println("登录");
}
//注册 register
public void register(HttpServletRequest request, HttpServletResponse response){
System.out.println("注册");
}
//改密 updatePassword
public void updatePassword(HttpServletRequest request, HttpServletResponse response){
System.out.println("修改密码");
}
//登出 loginOut
public void loginOut(HttpServletRequest request, HttpServletResponse response){
System.out.println("登出");
}
}