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@Overridepublic 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);}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("应用程序关闭,可以做一些资源的释放");}
}
/*** localhost:8080/demo1/picture/fetch?name=1.jpg*/
@WebServlet("/picture/fetch")
public class PictureAccessServlet extends HttpServlet {@Overrideprotected 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {ServletContext servletContext = filterConfig.getServletContext();}@Overridepublic 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// 后半部分// 但是一般业务代码都写在前半部分}@Overridepublic 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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(req, resp);}@SneakyThrowsprivate void process(HttpServletRequest request, HttpServletResponse response) {DispatchUtil.dispatch(request,response,this);}@SneakyThrowsprivate 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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {process(req, resp);}@SneakyThrowsprivate void process(HttpServletRequest request, HttpServletResponse response) {DispatchUtil.dispatch(request, response, this);}@SneakyThrowsprivate 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");}}@SneakyThrowsprivate void logout(HttpServletRequest request, HttpServletResponse response){HttpSession session = request.getSession();session.invalidate();response.getWriter().println("注销用户");}@SneakyThrowsprivate 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 {@Overridepublic 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);}@Overridepublic void contextDestroyed(ServletContextEvent sce) {}
}
  • filter目录下
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {List<String> whiteList = null;@SneakyThrows@Overridepublic 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");}@Overridepublic 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");
//        }}@Overridepublic 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 - contextPathString uriSuffix = null;// eg: /demo3/user/nameString requestURI = request.getRequestURI();// eg: /demo3String 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.rhkb.cn/news/292013.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RVM安装ruby笔记

环境 硬件&#xff1a;Macbook Pro 系统&#xff1a;macOS 14.1 安装公钥 通过gpg安装公钥失败&#xff0c;报错如下&#xff1a; 换了几个公钥地址&#xff08;hkp://subkeys.pgp.net&#xff0c;hkp://keys.gnupg.net&#xff0c;hkp://pgp.mit.edu&#xff09;&#xff0c;…

ML-Decoder: Scalable and Versatile Classification Head

1、引言 论文链接&#xff1a;https://openaccess.thecvf.com/content/WACV2023/papers/Ridnik_ML-Decoder_Scalable_and_Versatile_Classification_Head_WACV_2023_paper.pdf 因为 transformer 解码器分类头[1] 在少类别多标签分类数据集上表现得很好&#xff0c;但由于其查询…

css3之动画animation

动画animation 一.优点二.定义和使用三.动画序列和解释四.常见属性及解释五.简写&#xff08;名字和时间不能省略&#xff09;&#xff08;持续时间在何时开始的时间前&#xff09;&#xff08;简写中无animation-play-state)六.例子1.大数据热点图2.奔跑的熊大&#xff08;一个…

设计模式6--抽象工厂模式

定义 案例一 案例二 优缺点

代码随想录-二叉树(路径)

目录 257. 二叉树的所有路径 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 404. 左叶子之和 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 513.找树左下角的值 题目描述&#xff1a; 输入输出描述&#xff1a;…

Android裁剪图片为波浪形或者曲线形的ImageView

如果需要做一个自定义的波浪效果的进度条&#xff0c;裁剪图片&#xff0c;对ImageView的图片进行裁剪&#xff0c;比如下面2张图&#xff0c;如何实现&#xff1f; 先看下面的效果&#xff0c;看到其实只需要对第一张高亮的图片进行处理即可&#xff0c;灰色状态的作为背景图。…

基于SSM的戒烟网站(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的戒烟网站&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMv…

腾讯云优惠券领取方法大公开,省钱不再是难事

腾讯云—腾讯倾力打造的云计算品牌&#xff0c;以卓越科技能力助力各行各业数字化转型&#xff0c;为全球客户提供领先的云计算、大数据、人工智能服务&#xff0c;以及定制化行业解决方案和提供可靠上云服务&#xff0c;助力企业和开发者稳定上云&#xff01; 然而&#xff0…

数据结构进阶篇 之 【二叉树顺序存储(堆)】的整体实现讲解(赋完整实现代码)

做人要谦虚&#xff0c;多听听别人的意见&#xff0c;然后记录下来&#xff0c;看看谁对你有意见 一、二叉树的顺序&#xff08;堆&#xff09;结构及实现 1.二叉树的顺序结构 2.堆的概念及结构 3.堆的实现 3.1 向下调整算法 AdJustDown 3.2 向上调整算法 AdJustUP 3.3 …

C语言例1-8:设 char x,y; ,scanf(“x=%c,y=%c“,x,y); 后使 x 为 ‘X‘, y为 ‘Y‘,则键盘上的正确输入是

代码如下&#xff1a; #include<stdio.h> int main(void) {char x,y;scanf("x%c,y%c",&x,&y);printf("x%c,y%c\n",x,y);return 0; } 键盘输入选项A: xXyY 结果如下&#xff1a; 键盘输入选项B: xX,yY 结果如下&#xff1a; 键盘输入选项…

通过Jmeter准备压测数据-mysql示例

1、新建线程组 总共30万条数据 2、创建jdbc链接 创建jdbc连接配置 配置mysql连接 需要在jmeter安装的路径\apache-jmeter-5.6.3\lib\ext 目录下添加mysql 驱动 3、创建jdbc请求 jdbc链接名称需要与上一步中的保持一致&#xff0c;同时添加insert语句 例如 INSERT INTO test…

关系型数据库mysql(7)sql高级语句①

目录 一.MySQL常用查询 1.按关键字&#xff08;字段&#xff09;进行升降排序 按分数排序 &#xff08;默认为升序&#xff09; 按分数升序显示 按分数降序显示 根据条件进行排序&#xff08;加上where&#xff09; 根据多个字段进行排序 ​编辑 2.用或&#xff08;or&…

Python Flask框架 -- flask-migrate迁移ORM模型

# 之前使用的这个db.create_all()很有局限性&#xff0c;它不能把在class里修改的东西同步上数据库&#xff0c;所以不用了 # with app.app_context(): # 请求应用上下文 # db.create_all() # 把所有的表同步到数据库中去 例如&#xff0c;在User类中增加一个email字段&…

C语言例1-3:设 int a; ,语句 for(a=0;a==0;a++); 和语句 for(a=0;a=0;a++); 执行的循环次数分别是

答案&#xff1a;1,0 代码如下&#xff1a; #include<stdio.h> int main(void) {int a;for(a0;a0;a){printf("1\n");} return 0; } 结果如下&#xff1a; 代码如下&#xff1a; #include<stdio.h> int main(void) {int a;for(a0;a0;a){printf("…

【前端】layui学习笔记

参考视频&#xff1a;LayUI 1.介绍 官网&#xff1a;http://layui.apixx.net/index.html 国人16年开发的框架,拿来即用,门槛低 … 2. LayUi的安装及使用 Layui 是一套开源的 Web UI 组件库&#xff0c;采用自身轻量级模块化规范&#xff0c;遵循原生态的 HTML/CSS/JavaScript…

深入解析大语言模型显存占用:训练与推理

深入解析大语言模型显存占用&#xff1a;训练与推理 文章脉络 估算模型保存大小 估算模型在训练时占用显存的大小 全量参数训练 PEFT训练 估算模型在推理时占用显存的大小 总结 对于NLP领域的从业者和研究人员来说&#xff0c;有没有遇到过这样一个场景&#xff0c;你的…

C语言例1-11:语句 while(!a); 中的表达式 !a 可以替换为

A. a!1 B. a!0 C. a0 D. a1 答案&#xff1a;C while()成真才执行&#xff0c;所以!a1 &#xff0c;也就是 a0 原代码如下&#xff1a; #include<stdio.h> int main(void) {int a0;while(!a){a;printf("a\n");} return 0; } 结果如…

平台介绍-搭建赛事运营平台(8)

平台介绍-搭建赛事运营平台&#xff08;5&#xff09;提到了字典是分级的&#xff0c;本篇具体介绍实现。 平台级别的代码是存储在核心库中&#xff0c;品牌级别的代码是存储在品牌库中&#xff08;注意代码类是一样的&#xff09;。这部分底层功能封装为jar包&#xff0c;然后…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…

Stable Diffusion之核心基础知识和网络结构解析

Stable Diffusion核心基础知识和网络结构解析 一. Stable Diffusion核心基础知识1.1 Stable Diffusion模型工作流程1. 文生图(txt2img)2. 图生图3. 图像优化模块 1.2 Stable Diffusion模型核心基础原理1. 扩散模型的基本原理2. 前向扩散过程详解3. 反向扩散过程详解4. 引入Late…