Java Web 项目入门指南(http、Servlet、Request、Response、ServletContext、会话技术[cookie、session]、Filter、Listener)4

简介: Java Web 项目入门指南(http、Servlet、Request、Response、ServletContext、会话技术[cookie、session]、Filter、Listener)4

filter 的拦截方式


filter 默认只拦截 Request(浏览器过来的请求,包括重定向),不拦截 Forward(服务器内部的请求,即请求转发)


如果想让filter拦截服务器内部的请求:


  • 注解方式


配置 dispatcherTypes 属性,属性值新增 DispatcherType.FORWARD

@WebFilter(dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD})


该注解属性配置既会拦截浏览器过来的请求,又会拦截服务器内部的请求

xml 方式配置

在 <filter-mapping> 的标签中添加标签 <dispatcher>FORWARD</dispatcher> ,但是这种配置将 filter 默认的拦截方式给覆盖了,只会拦截服务器内部的请求,不会再拦截默认的浏览器请求了



想让 filter 拦截服务器内部的请求又拦截浏览器过来的请求:

  <filter-mapping>
        <filter-name>MyFilter2</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>  <!-- 配置拦截服务器内部请求 -->
        <dispatcher>REQUEST</dispatcher>  <!-- 配置拦截浏览器的请求 -->
  </filter-mapping>




使用案例


解决全站乱码

浏览器发出的任何请求,通过过滤器统一处理中文乱码。

@WebFilter(filterName = "EnCodingFilter",urlPatterns = "/*")
public class EnCodingFilter implements Filter {
     @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 在执行servlet获取数据和响应数据之前执行该代码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 放行之前 处理中文乱码
        chain.doFilter(req, resp);
    }
    @Override
    public void destroy() {}




非法字符的拦截

@WebFilter(filterName = "FeifaFilter",urlPatterns = "/sd3")
public class FeifaFilter implements Filter {
    private List<String> list;
    //服务器启动就执行 且只执行一次
    @Override
    public void init(FilterConfig config) throws ServletException {
        // 加载一个非法字符的文档(properties)
          //底层:会自动去src下加载后缀名为properties的文件
        ResourceBundle bundle = ResourceBundle.getBundle("feifa");
        String value = bundle.getString("feifa"); 
        // 读取文档中的数据,放入到集合中
        String[] arr = value.split(",");
        list = Arrays.asList(arr);
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
       // 获取用户发表的言论
        HttpServletRequest request=(HttpServletRequest)req;
        HttpServletResponse response=(HttpServletResponse)resp;
        String info = request.getParameter("info");
        // 判断言论是否合法
          // 遍历循环集合,将集合的非法字符和接受到的数据做包含
      // 包含上:就是非法  没包含上:就是合法
        for(String value:list){
             if(info.contains(value)){
                 // 不合法--不放行 直接给浏览器响应信息
                 // 包含上:就是非法
                 response.getWriter().print("你发表的言论有非法行为,请思考后再发表...");
                 return;
             }
        }
        //合法--直接放行
        chain.doFilter(request, resp);
    }
    @Override
    public void destroy() {}




Listener:监听器


概述

web 监听器是一种 Servlet 中的特殊的类,可以帮助开发者监听web中的特定事件,比如 ServletContext, HttpSession, ServletRequest 的创建和销毁等。可以在某些动作前后增加处理,实现监控。


Listener 的作用:监听 ServletContext, HttpSession, ServletRequest 三大域对象的状态变化(三个域对象的创建和销毁)



使用场景:

  • 系统启动时初始化信息


ServletContextListenner 用来监听 ServletContext 对象的创建和销毁的


当项目启动,servletContext 对象被创建时,会调用 ServletContextListenner 的 contextInitialized 方法,所以可以在此方法中初始化项目需要的信息


注:spring 框架会使用到它



统计在线人数


每当一个用户访问项目的时候,都会创建一个 session 会话。所以当前 session 会话被创建,当前在线用 户 +1,每当 session 会话被销毁,当前在线用户 -1



  • HttpSessionListener 可以用来监听 session 对象的创建和销毁的,所以可以在 HttpSessionListener 中的监听 session 对象创建和销毁的方法中控制在线人数的加减

java 提供了监听器规范,不同的监听器规范要监听的内容不一样



常见监听器:


ServletContextListener(常用):监听 ServletContext 对象的创建和销毁


例如:框架的配置文件在服务器启动就执行


ServletRequestListener :监听 ServletRequest 对象的创建和销毁


HttpSessionListener :监听 HttpSession 对象的创建和销毁



listener 的使用

API

  • ServletContextListenner 接口
// 监听 servletcontext 对象的创建
void contextInitialized(ServletContextEvent sce)
// 监听 servletcontext 对象的销毁
void contextDestroyed(ServletContextEvent sce)


ServletRequestListener 接口

// 监听 ServletRequest 对象的创建
void requestInitialized(ServletRequestEvent servletRequestEvent)
// 监听 ServletRequest 对象的创建
void requestDestroyed(ServletRequestEvent servletRequestEvent)


HttpSessionListener 接口

// 监听 HttpSession 对象的创建
void sessionCreated(HttpSessionEvent httpSessionEvent)
// 监听 HttpSession 对象的创建
void sessionDestroyed(HttpSessionEvent httpSessionEvent)



使用步骤(以 ServletContextListenner 监听器为例)


  1. 创建一个类实现 ServletContextListenner 接口,并实现方法 contextInitialized() 和contextDestroyed()
// 监听servletContext对象的创建和销毁。需实现java提供的监听器规范(ServletContextListener)
//@WebListener
public class ServletContextLoaderListener implements ServletContextListener {
    // 当servletContext对象被创建了,监听器触发,该方法执行
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("servletContext对象被创建了...");
        // 让服务器一加载,就读取框架的配置信息,进行加载
        ServletContext servletContext = servletContextEvent.getServletContext();
        String value = servletContext.getInitParameter("spring");
        System.out.println("就可以正式根据获取到的配置文件名,对该文件的内容进行加载了:"+value);
        System.out.println("正在加载该配置文件中....");
    }
    @Override //当servletContext对象被销毁了 监听器触发 该方法执行
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("servletContext对象被销毁了...");
    }
}



注册监听器

  • 方式1:在实现类上添加注解 @WebListene
  • 方式2:在 xml 中配置
<listener> 
    <listener‐class>com.itheima.listenner.MyServletContextListenner1</listener‐class> </listener>



案例

统计网站当前在线人数 HttpSessionListener

session 监听器,统计 session 个数

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener()
public class MyHttpSession implements HttpSessionListener { 
    //当前在线人数的属性名称 
    private static final String NUMBER = "NUMBER";
    /* 
     * session 创建时触发 
     */ 
    @Override 
    public void sessionCreated(HttpSessionEvent event) { 
        //会话创建了,有新用户访问网站
        HttpSession session = event.getSession();
        //新创建的会话对象 
        ServletContext servletContext = session.getServletContext();
        //获取当前项目环境对象 
        System.out.println("session创建了" + session.getId()); 
        Integer n = (Integer) servletContext.getAttribute(NUMBER);
        //当前在线人数 
        if( n== null){
            //如果 n==null 说明是第一个用户 ,直接设置n=1 
            servletContext.setAttribute(NUMBER, 1); 
        }else{
            //如果n != null 直接累加 
            servletContext.setAttribute(NUMBER, ++n); 
        }
        //如果 n==null 说明是第一个用户 ,直接设置n=1 
        //如果 n != null 直接累加 
    }
    /* 
    * session销毁时触发 
    */ 
    @Override 
    public void sessionDestroyed(HttpSessionEvent event) { 
        //会话销毁了,有用户的会话对象销毁了 
        HttpSession session = event.getSession();
        //新创建的会话对象 
        ServletContext servletContext = session.getServletContext();
        //获取当前项目环境对象 
        System.out.println("session销毁了" + session.getId()); 
        Integer n = (Integer) servletContext.getAttribute(NUMBER);
        //当前在线人数 //直接减1 
        servletContext.setAttribute(NUMBER, ‐‐n);
    }
}




拓展


浏览器和服务器交互中文乱码处理


  • 浏览器页面的中文数据请求给服务器,如果使用的 post 提交,服务器接受会发生乱码


解决:处理请求的中文数据乱码

request.setCharacterEncoding("utf-8");



服务器给浏览器中文数据的时候,浏览器会发生乱码行为

解决: 处理响应的中文数据乱码

response.setContentType("text/html;charset=utf-8");


服务器给浏览器附件框的时候,附件框上有中文,会发生乱码行为(下载才会有附件框)

解决:

  • 获取用户的浏览器版本
    火狐版本的浏览器:返回去的附件中文设置 base64 编码
    其它版本的浏览器:返回去的附件中文设置 utf-8 编码
String value = request.getHeader("user-agent");
String encode;
if(value.contains("Firefox")){
    //火狐浏览器中文(base64)
    Base64.Encoder encoder = Base64.getEncoder();
    encode = "=?utf-8?B?" + encoder.encodeToString(fileName.getBytes("utf-8")) + "?=";
} else {
    //其它浏览器中文(utf-8)
    encode = URLEncoder.encode(fileName, "utf-8");
}
//小说.txt  --%E5%B0%8F%E8%AF%B4.txt
response.setHeader("content-disposition", "attachment;filename=" + encode); 



请求转发和重定向的区别


  • 重定向多次请求,请求转发一次请求

  • 重定向是浏览器向服务器发送访问,请求转发是服务器内部资源互相访问

  • 重定向是response对象的API,请求转发是request对象的API

  • 重定向可以访问自己的项目也可以访问别的项目,请求转发只能访问当前自己的项目a

// 重定向。可以访问外部项目
response.sendRedirect(request.getContextPath() + "/sd11"); 
// 请求转发。只能访问当前项目
request.getRequestDispatcher("/sd7").forward(request,response);



域对象的总结


域对象可以在多个 servlet/jsp 之间进行数据传递


java 后端的域对象有 3 个:


ServletContext(公共数据)


创建:服务器只要启动就创建,且只创建一个


销毁:服务器关闭就销毁


存入数据的作用范围:整个 web 项目的所有 servlet 都共享

因为整个 web 项目只有一个 ServletContext,所有 servlet 中获取的都是同一个 ServletContext 对象

request


创建:请求一次创建一次


销毁:响应即销毁


存入数据的作用范围:只能是一次请求的多次转发中共享数据


只有在一次请求的多次转发中涉及到的多个 servlet 使用的才是一个 request 对象

session(私有数据)


创建:java 认为当浏览器首次执行到了 request.getSession 方法的时候创建 session 对象


销毁:

   被动销毁:默认当前 session 30 分钟不使用会被销毁

   主动销毁:session.invalidate()

   服务器非正常关闭 session 会销毁

   服务器正常关闭 session 不会销毁,会持久化到硬盘上,服务器开启后,会默认从硬盘上回到服务器中

存入数据的作用范围:在一次会话中涉及的多个servlet可以共享数据


因为一次会话中,多个 sevlet 中获取的 session 是同一个




域对象操作的 API

// 存放数据
void setAttribute(String name, Object value)
// 获得数据
Object getAttribute(String name)
// 删除数据
void removeAttribute(String name)


相关文章
|
6天前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
34 11
|
15天前
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
50 7
|
20天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
16天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
16天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
1月前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
29天前
|
Java 程序员 数据库连接
Java中的异常处理:从入门到精通
在Java编程的海洋中,异常处理是一艘不可或缺的救生艇。它不仅保护你的代码免受错误数据的侵袭,还能确保用户体验的平稳航行。本文将带你领略异常处理的风浪,让你学会如何在Java中捕捉、处理和预防异常,从而成为一名真正的Java航海家。
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
160 3
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
173 45
下一篇
DataWorks