(七)Web三大组件_JavaEE_学习笔记

三大Web组件:Servlet,Listener,Filter

一、Listener(监听器)

1.Web开发过程中的监听器:
监听对象:ServletContext
监听事件:创建和销毁
监听者:自己编写的一个监听器
触发事件:会触发监听器里面的方法

具体应用:
Context创建的时候读取一些配置文件;
Spring实例化的入口 ServletContextListener;

2.如何去编写一个listener?
(1)编写一个类实现ServletContextListener
(2)注册该listener(注解或者web.xml)

listener怎么做到监听的?
ServletContext的创建代码是在tomcat内部的,而且是很久之前就已经写好的,如何做到调用30年后写的代码呢?
伪代码:ServletContext对象的创建和销毁的代码

Class ServletContextXXX{
    多态  将自己编写的listener注入到接口引用中
	ServletContextListener listener;

  	Void create(){
		创建的时候,该方法会被调用
   		Listener.contextInitialized
	}

	Void destroy(){
		在销毁的时候,这个方法会被调用
		Listener.contextDestroyed
	}
}

3.使用场景
初始化配置、Spring程序执行的入口。

二、Filter(过滤器)

游戏中的文字检测到违禁的文字会自动替换成**********。
1.如何编写filter
(1)编写一个类实现Filter接口
(2)声明当前filter(web.xml或注解)
在这里插入图片描述
或者
在这里插入图片描述
任选其一即可。

2.如何让filter和servlet产生关联?让我们调用servlet时中间执行filter?
原来他们之间是没有任何关系的。
最简单的关联方式就是通过url-pattern进行关联,将servlet的url-pattern赋值给filter。
注意此时语法是允许的。
默认情况下filter执行的是拦截操作,如果想要filter放行,那么需要
在这里插入图片描述
3.filter的url-patterns可以设置/ * 吗?
完全可以设置 / * ,不会对我们的程序产生任何影响。
设置编码格式写到filter里面,那么其他servlet、也可以设置编码格式。

4.多个servlet不可以设置多个url-patterns,filter可以设置多个url-patterns吗?
完全可以设置。规定。
规定servlet不可以设置用一个url-patterns
Filter完全可以设置相同的url-patterns

处于功能上的考虑
Servlet:开发动态web资源,处理请求作出响应的,如果多个servlet相同url-pattern调用谁呢?
Filter:过滤器,执行过滤任务的,如果多个filter设置相同url-pattern,那么先后调用即可。

5.多个filter同时匹配时,先后顺序是什么样的呢?
对于web.xml来说,以mapping声明的先后顺序为准。
在这里插入图片描述
在这里插入图片描述
如果是注解呢?注意注解不要写成servlet的注解。
以类名首字母的ASII码先后顺序为准。

如果web.xml和注解同时配置,先xml后注解。

6.整个请求的执行流程
到达应用之前的步骤不会发生变化。区别在于达到应用之后。

  1. 浏览器地址栏输入http://localhost:8080/app/servlet,浏览器构建请求报文
  2. 达到目标机器,被8080端口接收,处理请求报文,生成request对象以及一个response对象
  3. 两个对象传递给engine,挑选host继续处理
  4. 继续传递对象,选择Context来处理
  5. 继续传递对象给context,根据配置的filter的url-patterns,判断能否处理该请求,如果可以,那么加入请求处理的队列中,如果有多个filter同时匹配到,那么就根据上面的原则,确定多个filter之间的调用顺序.
  6. 继续查找servlet的url-patterns,如果有,也加入队列中

登录案例:
LoginServlet.java

package com.cskaoyan.login;

import com.cskaoyan.login.bean.User;
import com.cskaoyan.login.utils.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //JDBC  EE串讲  JSON MVC(JDBC) Maven Project1
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());
        User user = null;
        try {
             user = runner.query("select * from user where username = ? and password = ?",
                    new BeanHandler<User>(User.class), username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        if(user != null){
            request.getSession().setAttribute("user", user);
            response.getWriter().println("登录成功,跳转至个人主页");
            response.setHeader("refresh","2;url=info.jsp");
            return;
        }
        response.getWriter().println("用户名或者密码错误");

    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

GlobalFilter .java

package com.cskaoyan.login.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class GlobalFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }
}

DruidUtils.java

package com.cskaoyan.login.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DruidUtils {

    private static DataSource dataSource;

    static {
        //从ds里面去获取,得到datasource即可
        try {
            Properties properties = new Properties();
            //流 -----> file ----- path
            //假如想将配置文件放在WEB-INF目录下 realPath
            //那么当前配置文件必须要有一个API来接收request或者context,否则无法获取路径
            //但是如果这么做了以后,那么今后该配置文件只能处理EE项目,SE项目需要重新在写一份
            //那么,有没有一种方式,既可以处理EE也可以处理SE呢?
            //有办法。利用类加载器来帮助我们获取流信息
            //输入空字符串的时候,其实是到com同级目录
            InputStream inputStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(inputStream);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }


    public static DataSource getDataSource(){
        return dataSource;
    }
}

User.java

package com.cskaoyan.login.bean;

public class User {

    private Integer id;

    private String username;

    private String password;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

login.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/7/31
  Time: 15:54
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="<%=request.getContextPath()%>/login" method="post">
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="submit">
    </form>
</body>
</html>

info.jsp

<%@ page import="com.cskaoyan.login.bean.User" %><%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/7/31
  Time: 16:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        User user = (User) request.getSession().getAttribute("user");
    %>
    欢迎您,<%=user.getUsername()%>
</body>
</html>

druid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/transfer?characterEncoding=utf-8
username=root
password=123456
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200

三、JDBC

标准JDBC

Class.forName(com.mysql.jdbc.Driver);
Connection conn = DriverManager.getConnection(url,user,password)
PrepareStatement psmt = Conn.prepareStatement(sql);
Psmt.setInt(1,xxx);
Psmt.setString(2,xxx);
ResultSet rs = Psmt.executeQuery();
While(rs.next()){
Rs.getString(columnLabel);
Rs.getInt(columnLabel);

}
Conn.close();
Psmt.close();
Rs.close();

为什么要引入数据库连接池?
因为创建连接的过程是十分消耗系统性能的,频繁创建和销毁连接,极易容易引起系统宕机。
连接先预先创建好,取出一个来使用,用完不要关闭,而是直接放回连接池。
获取DataSource数据源通过getConnection()。
为什么没有releaseConnection呢?即便提供了也没用,无法阻止主动去调用conn.close方法
有没有一种方式,close但是不是真的关闭,而是放回连接池。包装设计模式。
在这里插入图片描述
BeanListHandler:将结果封装为list对象形式
BeanHandler:将结果的第一行数据封装为一个对象
ScalarHandler:用来查询只有一列数据的值(聚合函数 count、max、min、avg)

2.配置文的存放位置
EE项目,配置文件放在哪呢?
最外层package目录同级

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值