09_Web组件

news2024/11/26 2:41:21

文章目录

  • Web组件
    • Listener监听器
      • ServletContextListener
      • 执行过程
    • Filter过滤器
      • Filter与Servlet的执行
    • 案例(登录案例)
  • 小结
    • Web组件

Web组件

  • JavaEE的Web组件(三大Web组件):
    1. Servlet → 处理请求对应的业务
    2. Listener → 监听器
    3. Filter → 过滤器

Listener监听器

  • 监听器在监听到主体做了XX事情,就会触发对应的事件
  • 监听的东西与命名有关系
  • 要加上注解@WebListener

ServletContextListener

监听的主体就是ServletContext,当发现ServletContext做了事情,Listener(监听器)就会执行该事件特定的方法。

  • ServletContext如果初始化,则会执行监听器的初始化方法contextInitialized
    • ServletContext应用程序启动的时候初始化,就意味着应用程序启动
  • ServletContext如果销毁,则会执行监听器的销毁方法contextDestroy
    • ServletContext应用程序关闭的时候销毁,意味着应用程序关闭
  • 应用程序启动的时候会执行ServletContextListenercontextInitialized方法;应用程序关闭的时候会执行contextDestroy

执行过程

当应用程序启动的过程中,逐步加载Web组件

  • 首先加载ServletContextListener组件
    • ServletContext伴随着应用程序初始化,它开始初始化,然后ServletContextListener监听到ServletContext初始化,会执行Listener的Initialized方法
  • 然后初始化loadOnStartup为正数的Servlet

在这里插入图片描述
eg:

@WebListener
public class PropertyInitServletContextListener implements ServletContextListener {
    @SneakyThrows
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();

        InputStream inputStream = PropertyInitServletContextListener.class.getClassLoader()
        .getResourceAsStream("parameter.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        String picPath = properties.getProperty("pic.path");

        servletContext.setAttribute("picPath", picPath);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("应用程序关闭,可以做一些资源的释放");
    }
}

/**
 * localhost:8080/demo1/picture/fetch?name=1.jpg
 */
@WebServlet("/picture/fetch")
public class PictureAccessServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // InputStream inputStream = PictureAccessServlet.class.getClassLoader()
        //         .getResourceAsStream("parameter.properties");
        // Properties properties = new Properties();
        // properties.load(inputStream);
        // String path = properties.getProperty("pic.path");
        String path = (String) getServletContext().getAttribute("picPath");

        File file = new File(path,request.getParameter("name"));
        FileInputStream fileInputStream = new FileInputStream(file);

        ServletOutputStream outputStream = response.getOutputStream();
        int length = 0;
        byte[] bytes = new byte[1024];
        while((length = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes,0,length);
        }
        fileInputStream.close();
        outputStream.close();
    }
}


Filter过滤器

  • Filter是一个执行过滤任务的一个对象
    • 它既可以作用于Request对象,也可以作用于Response对象,或者两者均作用
  • 就是Servlet中获取请求之前,Servlet响应之后

在这里插入图片描述

Filter与Servlet的执行

  • URL-Pattern和Servlet之间存在着映射关系,URL-Pattern和Filter之间也存在着映射关系
    • 1个URL-Pattern只能对应一个Servlet,但是可以对应多个Filter
    • Servlet和URL-Pattern之间是一对多的关系,但是URL-Pattern和Servlet之间是一对一
  • 其实,一个URL-Pattern对应的请求
    • 对应1个Servlet
    • 对应多个Filter

在这里插入图片描述
eg:

@WebFilter("/user/*")
public class CharacterEncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ServletContext servletContext = filterConfig.getServletContext();
    }

    @Override
    public void doFilter(ServletRequest servletRequest
            , ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        // 做过滤,里面写的就是通用的业务
        // 前半部分
        
        // 这部分是解决中文乱码问题
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        filterChain.doFilter(servletRequest, servletResponse); // 执行下一个过滤器或者Servlet

        // 后半部分
        // 但是一般业务代码都写在前半部分

    }

    @Override
    public void destroy() {

    }
}


案例(登录案例)

  • 需求
    • /user/login
    • /user/logout
    • /user/info
    • /order/list
    • 增加web组件中的filter功能
    • 增加web组件中的listener功能
    • 增加白名单功能

在这里插入图片描述

  • bean目录下
@Data
public class Order {
    private Integer id;
    private String name;
    private Double price;
    private Integer userId;
}
@Data
public class User {
    private Integer id;

    private String username;

    private String password;

    private Integer age;

    private Date birthday;

    private Date createdate;

    private String mobile;

}
  • mapper目录下
public interface OrderMapper {
    List<Order> selectByUserId(Integer id);
}
public interface UserMapper {
    List<User> selectByUserNameAndPassword
            (@Param("username") String username, @Param("password") String password);

    User selectByPrimaryKey(Integer id);
}
  • servlet目录下
@WebServlet("/order/*")
public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @SneakyThrows
    private void process(HttpServletRequest request, HttpServletResponse response) {
        DispatchUtil.dispatch(request,response,this);
    }

    @SneakyThrows
    private void list(HttpServletRequest request, HttpServletResponse response){
        // 先判断是否是登录状态
        // 如果没有登录,则跳转到登录页面
        // 这里filter帮我们完成了

        // 如果已经登录,则查询orderlist信息
        OrderMapper orderMapper = MybatisUtil.getSqlSession().getMapper(OrderMapper.class);
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        List<Order> orders = orderMapper.selectByUserId(user.getId());
        response.getWriter().println(orders);
    }
}
@WebServlet("/user/*")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @SneakyThrows
    private void process(HttpServletRequest request, HttpServletResponse response) {
        DispatchUtil.dispatch(request, response, this);
    }

    @SneakyThrows
    private void login(HttpServletRequest request, HttpServletResponse response){
        // 获取username和password,查询user记录
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        UserMapper userMapper = MybatisUtil.getSqlSession().getMapper(UserMapper.class);
        List<User> users = userMapper.selectByUserNameAndPassword(username, password);

        // 有可能用户名和密码相同,则取第一条数据
        if (users != null && users.size() > 0) {
            User user = users.get(0);
            HttpSession session = request.getSession();
            session.setAttribute("user",user);
            response.getWriter().println("登录成功");
        } else {
            response.getWriter().println("用户名或密码错误,即将跳转到登录页面...");
            response.setHeader("refresh","2;url=/demo3/login.html");
        }
    }

    @SneakyThrows
    private void logout(HttpServletRequest request, HttpServletResponse response){
        HttpSession session = request.getSession();
        session.invalidate();
        response.getWriter().println("注销用户");
    }

    @SneakyThrows
    private void info(HttpServletRequest request, HttpServletResponse response){
        // 先判断是否是登录状态
        // 如果没有登录,则跳转到登录页面
        // 这里filter帮我们做了

        // 如果已经登录,可以从session中获取信息 -> 响应信息
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        response.getWriter().println(user);
    }
}
  • listener目录下
@WebListener
public class PropertyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();

        Properties properties = new Properties();

        InputStream inputStream = PropertyServletContextListener.class.getClassLoader()
                .getResourceAsStream("application.properties");

        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String whiteList = properties.getProperty("whiteList");

        String[] whiteListStr = whiteList.split(",");

        List<String> list = Arrays.asList(whiteListStr);

        servletContext.setAttribute("whiteList", list);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}
  • filter目录下
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
    List<String> whiteList = null;

    @SneakyThrows
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 方法1:
//        Properties properties = new Properties();
//        InputStream inputStream = CharacterEncodingFilter.class.getClassLoader()
//                .getResourceAsStream("application.properties");
//        properties.load(inputStream);
//        String whiteListStr = properties.getProperty("whiteList");
//        String[] whiteArray = whiteListStr.split(",");
//        whiteList = Arrays.asList(whiteArray);

        // 方法2:
        // 可以先把配置文件在Listener的时候放入
        whiteList = (List<String>) filterConfig.getServletContext().getAttribute("whiteList");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse
            , FilterChain filterChain)
            throws IOException, ServletException {
        // List<String> list = Arrays.asList("/user/login", "/user/logout", "/login.html");

        // 强转
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String uriSuffix = UriUtil.getUriSuffix(request);
        if (whiteList.contains(uriSuffix)) {
            if (!uriSuffix.endsWith("html")) {
                // 1. 解决字符集
                request.setCharacterEncoding("utf-8");
                // 响应的字符集问题
                response.setContentType("text/html;charset=utf-8");
            }
            filterChain.doFilter(request, response);
        }

        // 1. 解决字符集
        request.setCharacterEncoding("utf-8");
        // 响应的字符集问题
        response.setContentType("text/html;charset=utf-8");

        // 2. 解决登录状态的判断
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");

        // 2.1 如果已经登录(或者登录/注销请求)就放行
        if (user != null) {
            filterChain.doFilter(request, response);
        } else {
            // 2.2 如果没有登录就提示,跳转到登录页面
            response.getWriter().println("没有登录,请先登录,即将跳转到登录页面...");
            response.setHeader("refresh", "2;url=/demo3/login.html");
        }


//        String requestURI = request.getRequestURI();


//        if (requestURI.endsWith("html")) {
//            filterChain.doFilter(request, response);
//        }

        // 2.1 如果已经登录(或者登录/注销请求)就放行
//        if (user != null || requestURI.endsWith("login")
//                || requestURI.endsWith("logout")){
//            filterChain.doFilter(request, response);
//        } else {
//            // 2.2 如果没有登录就提示,跳转到登录页面
//            response.getWriter().println("没有登录,请先登录,即将跳转到登录页面...");
//            response.setHeader("refresh","2;url=/demo3/login.html");
//        }
    }

    @Override
    public void destroy() {

    }
}
  • util目录下
public class DispatchUtil {
    public static void dispatch(String operation, HttpServletRequest request, HttpServletResponse response, HttpServlet instance)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = instance.getClass().getDeclaredMethod(operation, HttpServletRequest.class, HttpServletResponse.class);
        method.setAccessible(true);
        method.invoke(instance, new Object[]{request, response});
    }

    public static void dispatch(HttpServletRequest request, HttpServletResponse response, HttpServlet userServlet)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        String requestURI = request.getRequestURI();
        String operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);
        dispatch(operation, request, response, userServlet);
    }
}
public class MybatisUtil {
    private static SqlSession sqlSession;

    static{
        try {
            sqlSession = new SqlSessionFactoryBuilder()
                    .build(Resources.getResourceAsStream("mybatis.xml")).openSession(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSession;
    }
}
public class UriUtil {

    // Suffix的意思是后缀
    public static String getUriSuffix(HttpServletRequest request) {
        // uri - contextPath
        String uriSuffix = null;
        // eg: /demo3/user/name
        String requestURI = request.getRequestURI();
        // eg: /demo3
        String contextPath = request.getContextPath();
        if (contextPath == null || contextPath.length() == 0) {
            // 这是一个root应用
            uriSuffix = requestURI;
        } else {
            uriSuffix = requestURI.replaceAll(contextPath, "");
            // 或者:uriSuffix = requestURI.substring();
        }
        return uriSuffix;
    }
}
  • UserMapperxml目录
<mapper namespace="com.coo1heisenberg.demo3.mapper.OrderMapper">

    <select id="selectByUserId" resultType="com.coo1heisenberg.demo3.bean.Order">
        select id, name, price, user_id as userId from test_product
        <where>
            user_id = #{user_id}
        </where>
    </select>
</mapper>
<mapper namespace="com.coo1heisenberg.demo3.mapper.UserMapper">

    <select id="selectByUserNameAndPassword" resultType="com.coo1heisenberg.demo3.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            username = #{username} and password = #{password}
        </where>
    </select>

    <select id="selectByPrimaryKey" resultType="com.coo1heisenberg.demo3.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            id = #{id}
        </where>
    </select>
</mapper>

小结

Web组件

  • 核心Servlet处理核心业务
  • Listener,用来做资源的初始化
  • Filter,在Servlet处理前后增加通用的处理

11

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1557380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图论做题笔记:dfs

Leetcode - 797&#xff1a;所有可能的路径 题目&#xff1a; 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节…

公司官网怎么才会被百度收录

在互联网时代&#xff0c;公司官网是企业展示自身形象、产品与服务的重要窗口。然而&#xff0c;即使拥有精美的官网&#xff0c;如果不被搜索引擎收录&#xff0c;就无法被用户发现。本文将介绍公司官网如何被百度收录的一些方法和步骤。 1. 创建和提交网站地图 创建网站地图…

el-select的错误提示不生效、el-select验证失灵、el-select的blur规则失灵

发现问题 在使用el-select进行表单验证的时候&#xff0c;发现点击下拉列表没选的情况下&#xff0c;他不会提示没有选择选项的信息&#xff0c;我设置了rule如下 <!--el-select--><el-form-item label"等级" prop"level"><el-select v-m…

代码随想录算法训练营Day39|LC62 不同路径LC63 不同路径II

一句话总结&#xff1a;不是太难&#xff0c;状态转移方程好想。 原题链接&#xff1a;62 不同路径 位置为(i, j)的点只能从上面或者左边过来&#xff0c;由此可列出状态转移方程。状态转移方程的初始化为所有第一排和第一列的点都初始化为1即可。 class Solution {public i…

MATLAB 点云高程渲染赋色(50)

MATLAB 点云高程渲染赋色(50) 一、算法介绍二、算法实现1.步骤2.代码3.效果一、算法介绍 自己写的高程渲染算法,点云的渲染效果更接近软件中的效果,具体的算法步骤和实现代码,以及最后的实现效果如下所示: 二、算法实现 1.步骤 1 首先读取了原始的点云数据 CSDN.ply…

【御控物联】JavaScript JSON结构转换(12):对象To数组——键值互换

文章目录 一、JSON结构转换是什么&#xff1f;二、核心构件之转换映射三、案例之《JSON对象 To JSON数组》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换…

Adobe Illustrator 2023 for Mac/Win:创意无限,设计无界

在数字艺术与设计领域&#xff0c;Adobe Illustrator 2023无疑是一颗璀璨的明星。这款专为Mac和Windows用户打造的矢量图形设计软件&#xff0c;以其强大的功能和卓越的性能&#xff0c;赢得了全球设计师的广泛赞誉。 Adobe Illustrator 2023在继承前代版本优点的基础上&#…

【DETR系列目标检测算法代码精讲】01 DETR算法01 DETR算法框架和网络结构介绍

为什么要有DETR 总所周知&#xff0c;传统的目标检测算法非常依赖于anchor和nms等手工设计操作&#xff0c;非常费时费力&#xff0c;自然而然的就产生了取消这些操作的想法。但是我们首先需要思考的是&#xff0c;为什么我们需要anchor和nms&#xff1f; 因为我们是没有指定…

正大国际:期货入门的基础知识是什么?

期货的概念很简单&#xff0c;就是一种远期合同&#xff0c;买卖双方约定交易物、交易价格与交易时间。难就难在如何理解它具备的杠杆率&#xff0c;人们是如何在这上面暴富或破产的 很多人抱有这么个错觉&#xff0c;觉得期货是一个小众市场。但其实&#xff0c;世界上所发生…

P-MapNet:Far-seeing Map Generator Enhanced by both SDMap and HDMap Priors

主页&#xff1a;homepage 参考代码&#xff1a;P-MapNet 动机与出发点 在感知系统中引入先验信息是可以提升静态元素感知网络的上限的&#xff0c;这篇文章对SD地图采用栅格化表示&#xff08;也就是图像形式&#xff09;&#xff0c;之后用CNN网络去抽取栅格化SD地图的信息&…

软件测试面试——你准备好了吗?

软件的生命周期 计划阶段-〉需求分析-〉设计阶段-〉编码->测试->运行与维护 测试用例&#xff1a;用例ID&#xff0c;测试项&#xff0c;重要级别&#xff0c;优先级别&#xff0c;预置条件&#xff0c;测试标题&#xff0c;操作步骤&#xff0c;预期结果。&#xff08…

Mybatis (1)

mybatis 1、入门2、事务管理机制3、日志和junit配置3、mybatis工具类4、CRUD4.1 insert4.1.1 map方式4.1.2 对象方式 4.2 delete4.3 update4.4 select&#xff08;Retrieve&#xff09;4.4.1 查询一个结果4.4.2 查询多个结果 4.5 命名空间 1、入门 ①创建一个空项目&#xff1…

java电话号码的字母组合(力扣Leetcode17)

电话号码的字母组合 力扣原题链接 问题描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 示例 1&#xff1a;…

理解游戏服务器架构-部署架构

目录 前言 我所理解的服务器架构 什么是否部署架构 部署架构的职责 进程业务职责 网络链接及通讯方式 与客户端的连接方式 服务器之间连接关系 数据落地以及一致性 数据库的选择 数据访问三级缓存 数据分片 读写分离 分布式数据处理 负载均衡 热更新 配置更新 …

flowable-ui后台显式非中文

把flowable-ui的war包发布后&#xff0c;后台界面显示的是非中文 用的是6.7.2版本&#xff0c;经过了解该版本是有国际化配置文件的&#xff0c;支持中文 猜测可能是浏览器语言导致未显示中文&#xff0c;在控制台输入navigator.language&#xff0c;查看到果然是英文 解决方案…

[项目实践]---RSTP生成树

[项目实践] 目录 [项目实践] 一、项目环境 二、项目规划 三、项目实施 四、项目测试 |验证 ---RSTP生成树 一、项目环境 Jan16 公司为提高网络的可靠性&#xff0c;使用了两台高性能交换机作为核心交换机&#xff0c;接入层交 换机与核心层交换机互联&#xff0c;形成冗…

【Linux】生产者消费者模型{基于BlockingQueue的PC模型/RAII风格的加锁方式/串行,并行,并发}

文章目录 1.认识PC模型2.基于BlockingQueue的PC模型2.1串行&#xff0c;并行&#xff0c;并发2.2理解linux下的并发2.2RAII风格的加锁方式2.3阻塞队列2.4深入理解pthread_cond_wait2.5整体代码1.Task.hpp2.lockGuard.hpp3.BlockQueue.hpp4.pcModel.cc 3.总结PC模型 1.认识PC模型…

蓝桥杯第十三届电子类单片机组程序设计

目录 前言 单片机资源数据包_2023 一、第十三届比赛省赛 1.比赛题目 2.赛题解读 二、部分功能实现 1.继电器的开启与关闭 2.长按切换显示状态功能的实现 3.对于温度传感器小数部分的处理 4.其他处理 1&#xff09;关于数码管显示小数的处理 2&#xff09;关于5s后继…

(完结)Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(三)项目优化

本文参考自 Springboot3微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本文是仿12306项目实战第&#xff08;三&#xff09;章——项目优化&#xff0c;本篇将讲解该项目最后的优化部分以及一些压测知识点 本章目录 一、压力测试-高并发优化前后的性能对比1.压力测试相关…

系统需求分析报告(原件获取)

第1章 序言 第2章 引言 2.1 项目概述 2.2 编写目的 2.3 文档约定 2.4 预期读者及阅读建议 第3章 技术要求 3.1 软件开发要求 第4章 项目建设内容 第5章 系统安全需求 5.1 物理设计安全 5.2 系统安全设计 5.3 网络安全设计 5.4 应用安全设计 5.5 对用户安全管理 …