Servlet day04

Servlet day04

1 Filter(过滤器)

Filter(过滤器)中抽取Servlet中的共性代码,用来解决多个Servlet中代码重复的问题。下面我们来学习下Filter的工作流程和开发步骤。

1.1 Filter的工作流程

Filter的作用和工作流程类似于生活中小区的门卫和警卫。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqZlpYaJ-1631153116780)(Servlet day04.assets/image-20210529195730899.png)]

门卫警卫的工作流程:

  1. 访客要拜访程序员,需要经过门卫和警卫才能访问到程序员
  2. 离开时也要经过门卫和警卫,途径顺序和来访时相反
  3. 警卫可以拒绝不满足条件的访客的来访请求,改变其流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q47143LH-1631153116783)(Servlet day04.assets/image-20210529201003592.png)]

Filter的工作流程:

  1. Client发起对Servlet的请求,要先经过Filter后才能到达Servlet
  2. Servlet中的响应结果也要反向经过Filter
  3. Filter可以改变Client的请求流向
  4. Filter中通常抽取Servlet中的共性代码

1.2 Filter的开发步骤

  1. 编码

    class FirstFilter implements Filter{
        //过滤请求时执行的方法
        public void doFilter(req,resp,chain) throws IOException,ServletException{
            //抽取Servlet中共性的代码
            
            //放行请求,没有这行代码,请求不会继续向后传递
            chain.doFilter(req,resp);
        }
    }
    
  2. 配置

    //配置Filter的过滤请求的范围
    <filter>
    	<filter-name>filter的名字</filter-name>
        <filter-class>filter的全类名</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>filter的名字</filter-name>
        <!-- 用来配置filter的过滤请求的范围
     	    /*   过滤所有请求
            /前缀/* 过滤以url-pattern以 /前缀/开头的servlet
       示例:/student/* 过滤url-pattern以 /student/开头的servlet
    	-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    

1.3 Filter的语法细节

  1. Filter可以精确配置

    <filter>
      	<filter-name>FirstFilter</filter-name>
      	<filter-class>com.baizhi.filter.FirstFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>FirstFilter</filter-name>
          <!-- 不使用通配符时,是精确配置 -->
      	<url-pattern>/a</url-pattern>
      </filter-mapping>
    
  2. Filter可以配置多个url-pattern

    <filter>
      	<filter-name>FirstFilter</filter-name>
      	<filter-class>com.baizhi.filter.FirstFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>FirstFilter</filter-name>
      	<url-pattern>/a</url-pattern>
      	<url-pattern>/b</url-pattern>
      </filter-mapping>
    
  3. 多个Filter的执行顺序

    多个Filter过滤了相同的请求,那么执行顺序和web.xml中配置顺序一致!!!
    下面的配置就是先经过First再经过Second
    <filter>
      	<filter-name>FirstFilter</filter-name>
      	<filter-class>com.baizhi.filter.FirstFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>FirstFilter</filter-name>
      	<url-pattern>/a</url-pattern>
      	<url-pattern>/b</url-pattern>
      </filter-mapping>
      
       <filter>
      	<filter-name>SecondFilter</filter-name>
      	<filter-class>com.baizhi.filter.SecondFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>SecondFilter</filter-name>
      	<url-pattern>/*</url-pattern>
      </filter-mapping>
    
  4. Filter不但能拦截Servlet的请求,还可以拦截对静态资源的请求

    有项目结构如下:
    +servlet-day04
    	-login.html
    	-register.html
    	+person
    		-addPerson.html
    	+WEB-INF
    		+classes
    			@WebServlet("/person/showAllPersons")
    			-com.baizhi.controller.ShowAllPersonsController
    
    动态资源查询Controller的URL:
    http://localhost:8989/servlet-day04/person/showAllPersons
    静态资源addPerson.html的URL:
    http://localhost:8989/servlet-day04/person/addPerson.html
    
    有Filter的url-pattern为/person/*,那么上面的2个资源的请求都会被此Filter过滤。
    
  5. Filter的生命周期

    • 创建时期:web应用启动时
    • 销毁时期:web应用关闭时

1.4 Filter典型应用场景

1.4.1 编码过滤器
  1. 编码

    public class CharacterEncodingFilter implements Filter  {
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		//设置编解码集
    		request.setCharacterEncoding("utf-8");
    		response.setCharacterEncoding("utf-8");
    		//放行请求
    		chain.doFilter(request, response);
    		
    	}
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    
  2. 配置

    <filter>
      	<filter-name>CharacterEncodingFilter</filter-name>
      	<filter-class>com.baizhi.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>CharacterEncodingFilter</filter-name>
      	<url-pattern>/*</url-pattern>
      </filter-mapping>
    
1.4.2 登录过滤器
  1. 编码

    public class LoginFilter implements Filter {
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		// TODO Auto-generated method stub
    		//强制登录判断
    		//父接口引用强转为子接口引用
    		HttpServletRequest httpReq = (HttpServletRequest)request;
    		HttpServletResponse httpResp = (HttpServletResponse)response;
    		
    		HttpSession session = httpReq.getSession();
    		Object o = session.getAttribute("login");
    		//如果满足条件,放行请求
    		if(o != null) {
    			chain.doFilter(request, response);
    		}else {
    		//不满足条件,重定向到登录页面
    			String contextPath = httpReq.getContextPath();
    			httpResp.sendRedirect(contextPath+"/login.html");
    		}
    	}
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    
  2. 配置

    <filter>
      	<filter-name>LoginFilter</filter-name>
      	<filter-class>com.baizhi.filter.LoginFilter</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>LoginFilter</filter-name>
      	<url-pattern>/student/*</url-pattern>
      </filter-mapping>
    

2 ServletContext

ServletContext对象表示一个web应用。无论何时何人只要访问的是同1个应用,那么获取到是同1个ServletContext对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uXhcSq4Z-1631153116784)(Servlet day04.assets/image-20210529221050540.png)]

//获取ServletContext作用域
ServletContext servletContext = req.getServletContext();

ServletContext还可以作为作用域对象。
作用域对象的使用:

//保存数据
servletContext.setAttribute("key",数据);
//获取数据
servletContext.getAttribute("key");
//移除数据
servletContext.removeAttribute("key");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yE9bOeIb-1631153116785)(Servlet day04.assets/image-20210529222259746.png)]

作用范围:

  1. request作用域:一次请求,forward间传递数据
  2. session作用域:一个浏览器的多次请求
  3. servletContext作用域:可以在多个浏览器间传递数据

3 Listener

监听器可以监听Web应用一些特定的事件,在事件发生时执行一些代码。

3.1 HttpSessionListener

监听Session的创建和销毁

  1. 编码

    public class MyHttpSessionListener implements HttpSessionListener {
    
    	@Override
    	//监听到session对象创建时执行
    	public void sessionCreated(HttpSessionEvent arg0) {
    		// TODO Auto-generated method stub
    		System.out.println("session创建了");
    	}
    
    	@Override
    	//监听到session对象销毁时执行
    	public void sessionDestroyed(HttpSessionEvent arg0) {
    		// TODO Auto-generated method stub
    		System.out.println("session销毁了");
    	}
    
    }
    
  2. 配置

    <listener>
      	<listener-class>com.baizhi.listener.MyHttpSessionListener</listener-class>
    </listener>
    

3.2 ServletContextListener

监听web应用的启动和关闭。

  1. 编码

    public class MyServletContextListener implements ServletContextListener  {
    
    	@Override
    	//web应用关闭时执行
    	public void contextDestroyed(ServletContextEvent arg0) {
    		// TODO Auto-generated method stub
    		System.out.println("web应用关闭了,执行一些释放资源的代码");
    	}
    
    	@Override
    	//web应用启动时执行
    	public void contextInitialized(ServletContextEvent arg0) {
    		// TODO Auto-generated method stub
    		System.out.println("web应用启动了,执行一些需要在应用启动早期执行的代码");
    	}
    
    }
    
    
  2. 配置

    <listener>
      	<listener-class>com.baizhi.listener.MyServletContextListener</listener-class>
      </listener>
    

4 Servlet拾遗

4.1 动态获取当前项目名

在Servlet中如果重定向跳转,跳转路径需要以 /项目名 开头。

resp.sendRedirect("/项目名/url-pattern");

直接硬编码项目名存在维护问题,如果日后项目名发生变化,程序中需要修改很多地方。解决方案:动态获取web项目名

String contextPath = req.getContextPath();// 获取到当前项目名
//重定向代码示例
resp.sendRedirect(contextPath+"/login.html");

4.2 完善更新功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWUONgs7-1631153116786)(Servlet day04.assets/image-20210526141610763.png)]

完善后的更新流程:

  1. 点击更新先发起查询详情的请求
  2. 查询详情Controller跳转到View中,动态生成更新表单。表单中的input通过字符串拼接赋初始值
  3. 在View生成的更新页面中发起更新请求

4.3 Servlet收参:根据一个name获取多个value

Client发送的请求参数通常是一个key对应1个value,但是也有1个key对应多个value的情况,典型场景是复选框发送数据。

<!-- 
	此时选中前3个复选框,请求参数:favorites=1&favorites=2&favorites=3
-->
<form>
    爱好: 	
    	<input type="checkbox" name="favorites" value="1"><input type="checkbox" name="favorites" value="2"><input type="checkbox" name="favorites" value="3"> Rap
    <input type="checkbox" name="favorites" value="4"> 打篮球 <br>
    <input type="submit"/>
</form>

Servlet中就不能通过getParameter获取value,需要通过getParameterValues获取多个value。

String[] values = req.getParameterValues("favorites");

**使用场景:**批量删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EciGWnto-1631153116787)(Servlet day04.assets/image-20210529224620561.png)]


Rap
打篮球

```

Servlet中就不能通过getParameter获取value,需要通过getParameterValues获取多个value。

String[] values = req.getParameterValues("favorites");

**使用场景:**批量删除

[外链图片转存中…(img-EciGWnto-1631153116787)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值