09_Web组件

文章目录

  • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

权限提升-Linux系统权限提升篇Vulnhub辅助项目SUID权限SUDO指令版本漏洞

知识点 1、Web权限或普通用户到Linux-配置不当-判断&利用 2、Web权限或普通用户到Linux-配置不当-SUID&GUID 3、普通用户到Linux-配置不当-SUDO&CVE漏洞 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及…

CVE-2023-38408漏洞修复 - 升级openssl和openssh

CVE-2023-38408 OpenSSH 代码问题漏洞修复 - 升级openssl和openssh ※ 重要说明&#xff1a; 1、升级后会导致无法用ssh远程登录&#xff0c;提示“Permission denied, please try again.” 2、解决方案请查看本章节【三、解决升级后无法用ssh远程登录】 目录 CVE-2023-38408 O…

c语言例题,逐个打印数字

今天来分享个比较简单的程序例题&#xff0c;也是比较经典的一个新手例题&#xff0c;逐个打印输入的数字。我们直接从主函数看起&#xff0c;先定义一个num变量&#xff0c;同时变量的类型是unsigned int&#xff0c;这个类型的意思是无符号的整型变量&#xff0c;unsigned&am…

手把手在K210上部署自己在线训练的YOLO模型

小白花了两天时间学习了一下K210&#xff0c;将在线训练的模型部署在K210&#xff08;代码后面给出&#xff09;上&#xff0c;能够识别卡皮巴拉水杯&#xff08;没错&#xff0c;卡皮巴拉&#xff0c;情绪稳定&#xff0c;真的可爱&#xff01;&#xff09;。数据集是用K210拍…

C++:一次性搞定vector模拟实现中必须关注的细节

vector模拟实现的细节 1. vector的模拟实现源码2. 重要接口注意事项2.1 const修饰2.2 begin()和end()2.3 构造函数&#xff08;1&#xff09;迭代器区间初始化&#xff08;2&#xff09;构造函数冲突问题发现​问题分析问题​解决问题 &#xff08;3&#xff09;特殊的构造函数…

LDR6023,大功率OTG快充芯片,引领充电新时代!

在科技日新月异的当下&#xff0c;数据交互方式已经深入我们生活的每一个角落&#xff0c;对日常生活和工作产生着无可替代的影响。然而&#xff0c;在OTG技术诞生之前&#xff0c;数据交互的过程常常显得繁琐且耗时。想象一下&#xff0c;需要将数码相机中的照片导入笔记本电脑…

《科技创新与应用》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答&#xff1a; 问&#xff1a;《科技创新与应用》是什么级别期刊&#xff1f; 答&#xff1a;省级&#xff1b;主管单位&#xff1a;黑龙江省科学技术协会&#xff1b;主办单位&#xff1a;黑龙江省创联文化传媒有限公司 问&#xff1a;《科技创新与应用》是核心期刊…

查找链表中的中间结点

略。。。。。 提升题的难度&#xff0c;不知道输入数据节点的个数。 方法一&#xff1a;对链表进行两次遍历。第一次遍历时&#xff0c;我们统计链表中的元素个数 N&#xff1b;第二次遍历时&#xff0c;我们遍历到第 N/2 个元素时&#xff0c;将该元素返回即可。 方法二&am…

粉丝免费福利第一期-海浪型手机支架

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN博客专家&#xff0c;华为云云享专家&#xff0c;阿里云专家博主 &#x1f4cc; 擅长领域&#xff1a;全栈工程师&#xff0c;大模型&#xff0c;爬虫、ACM算法 &#x1f492; 公众号&#xff…

不小心将某个分支的本地代码推到另外一个远程分支上

不小心将某个分支的本地代码推到另外一个远程分支上&#xff0c;是不会产生效果的&#xff0c;若提示了“Everything up-to-date ”&#xff0c;说明没有内容被提交到了远程&#xff0c;某个分支的本地代码仍然在本地仓库。 若想将改动的代码提交到另外一个远程分支上&#xf…

不懂技术的老板,如何避免过度依赖核心技术人员

在这个日新月异、技术驱动的时代&#xff0c;即使作为非技术背景的老板&#xff0c;也深知核心技术人员的价值。然而&#xff0c;过度依赖某几位核心技术人员&#xff0c;不仅可能带来经营风险&#xff0c;还可能限制企业的创新与发展。那么&#xff0c;不懂技术的老板&#xf…

【python基础教程】2. 算法的基本要素与特性

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;python基础教程 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、…

创建第一个51文件

1.找一个文件目录创建一个main.c 比如我的 F:\my_project\project_of_51\0.first_of_51 什么你不会&#xff1f; 先把这里的文件扩展名打开; 再创建一个文本文件&#xff0c;重新命名为main.c // 修改.c 后弹出一个确认修改的框&#xff0c;选确认即可 2.kei操作: 1&#xf…

学生成绩管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 1. 管理员功…

Taskflow:条件任务(Conditional Tasking)

基本使用 条件任务评估一组指令&#xff0c;并返回要执行的下一个后续任务的整数索引。 该索引是根据其继任者结构的顺序定义的&#xff0c;首先&#xff0c;创建一个最简单的if else条件模块: #include <taskflow/taskflow.hpp>int main() {tf::Taskflow taskflow;tf:…

暴力破解pdf文档密码

首先安装pdfcrack工具包 apt install pdfcrack 默认密码字典存储在/usr/share/wordlists里&#xff0c;是gz文件&#xff0c;将它解压并copy到pdf目录 然后使用pdfcrack破解 密码在最后一行user-password的单引号里

计算机网络——31数据链路层和局域网引论和服务

数据链路层和局域网 WAN&#xff1a;网络形式采用点到点链路 带宽大&#xff0c;距离远&#xff08;延迟大&#xff09; 贷款延迟积大 如果采用多点连接方式 竞争方式&#xff1a;一旦冲突代价大令牌等协调方式&#xff1a;在其中协调节点的发送代价大 点到点链路的链路层服…

基于SpringBoot和Vue的教学管理系统的设计与实现

今天要和大家聊的是一款基于SpringBoot和Vue的教学管理系统的设计与实现 &#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通过文章末尾名片咨询我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;李同学 &#x1f495;&#x1f…

理解游戏服务器架构-逻辑底层架构

目录 前言 什么是逻辑底层架构 逻辑底层架构的职责 1&#xff09;Thread-线程 线程管理 线程通讯 线程安全锁机制 2&#xff09;Network-网络 网络模型 网络消息协议 断线重连 网络安全 防范重复消息 防范篡改消息内容 防范篡改内存数据 网络承载 3&#xff0…

使用nvm管理nodejs版本

文章目录 1、下载NVM2、选择NVM安装3 、查询版本号&常用命令4、nvm命令安装指定版本node4.1 安装指定node4.2 查看是否安装成功4.3 切换node版本到你想要的版本4.4 再次查看nvm版本列表4.5 nvm其他常用命令 这个是每个全能前端经常会用到的&#xff0c;之前用过现在重装了&…