欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

周总结

程序员文章站 2024-01-29 14:21:04
...

01_会话技术

  • 概念
    • 打开浏览器,访问服务器中资源,关闭浏览器;这个过程就是会话。
  • 会话分类
    • Cookie会话技术;浏览器会话技术
    • Session会话技术;服务器会话技术
  • 作用
    • 解决ServletContext域对象、Request域对象存储数据所存在的问题
  • ServletContext域对象、Request域对象存在的问题
    • ServletContext域对象可以看到所有人的购物车
    • Request域对象,发起结算时购物车是空的

02_Cookie的介绍

  • 概念
    • 网景公司发明。是浏览器的会话技术
  • Cookie的流程
    • 浏览器请求服务器,请求Demo01Servlet,创建一个Cookie对象,名称为cookie1
  • 可以通过响应头Set-Cookie,携带cookie给浏览器进行保存
    • 浏览器再次请求服务器,请求Demo02Servlet,获取cookie1对象

03_Cookie的基本使用

  • 设置Cookie
    • 方式一(不推荐)
      response.addHeader(“set-cookie”,“msg=hellocoolie”);
  • 方式二(推荐)
    Cookie cookie = new Cookie(“msg”,“hellocookie”);
    response.addCookie(cookie);
  • 获取Cookie
    • 开发步骤
      • 通过request对象获取所有的Cookie对象,存储到一个数组中
      • 遍历该数组,匹配Cookie名称
      • 如果匹配上,就知道了指定的Cookie对象
      • 如果匹配不上,就没有指定的Cookie对象
    • 代码实现
Cookie[] cookies = request.getCookies();
Cookie cookie = null;
for(Cookie sonCookie : cookies){
    if("msg".equals(sonCookie.getName())){
        cookie = sonCookie;
    }
}
if(null != cookie){
    System.out.println("name : "+msgCookie.getName() + " , value : "+ msgCookie.getValue());
}

04_Cookie的相关设置

  • 持久化设置
    • cookie的生命周期
      • 默认是随着浏览器的关闭而销毁
    • setMaxAge
      • 设置cookie的存活时长,cookie就可以不随着会话的关闭而销毁!
  • 路径设置
    • 默认情况下,Cookie对象会随着任何一个请求携带到服务器
    • setPath
      • 设置Cookie的访问路径
        Cookie cookie = new Cookie(“msg”,“helloworld”);
        cookie.setPath("/day56/demo04");
        response.addCookie(cookie);
      • cookie对象只有访问路径包含"/day56/demo04",才会跟随请求携带到服务器

05_Cookie案例之记录上一次访问时间

  • 需求:
    • 第一次访问,就直接打印当前时间
    • 不是第一次访问,就打印上一次的访问时间
  • 开发步骤
    • 获取对应的Cookie对象
    • 判断是否是第一次访问
    • 如果是第一次访问
      • 打印当前时间
      • 将当前时间存储到Cookie中
    • 如果不是第一次访问
      • 打印上一次访问时间
      • 将当前时间存储到Cookie中
  • 代码实现
//判断是否是一次请求
Cookie[] cookies = request.getCookies();
Cookie cookie = null;//记录上一次的访问时间
if (cookies != null && cookies.length != 0 ) {
    for (Cookie sonCookie : cookies) {
        if ("lastTime".equals(sonCookie.getName())) {
            cookie = sonCookie;
        }
    }
}
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
if (null == cookie) {
    //第一次访问 ,打印当前时间,并将创建Cookie对象,存储当前时间

    Date currentDate = new Date();
    System.out.println("第一次访问,时间为" + format.format(currentDate));
    cookie = new Cookie("lastTime",currentDate.getTime()+"");
} else {
    //不是第一次访问,从cookie取出上一次的访问时间,并打印。获取当前时间,并存储cookie对象中
    long lastDateMills = Long.parseLong(cookie.getValue());
    Date lastDate = new Date(lastDateMills);
    //获取到了上一次的访问时间
    String lastTimeStr = format.format(lastDate);
    System.out.println("上一次访问,时间为" + lastTimeStr);
    //获取当前时间,并存储cookie对象中
    Date currentDate = new Date();
    //            cookie.setValue(currentDate.getTime()+"");
    cookie = new Cookie("lastTime",currentDate.getTime()+"");
}

response.addCookie(cookie);

06_Cookie案例之商品浏览记录

  • 需求
    • 浏览商品,将商品的浏览的记录起来,并显示!
  • 开发步骤
    • 获取history的Cookie对象
    • 判断商品浏览记录是否为空
    • 如果浏览记录没有
      • 创建Cookie,并将当前的商品记录到Cookie中
    • 如果浏览记录有
      • 有当前的商品,不做任何处理
      • 没有当前商品,就需要将当前的商品拼接到已有记录中
  • 代码实现
    • 页面代码
<a href="/day56/history?id=0">西游记</a><br>
<a href="/day56/history?id=1">红楼梦</a><br>
<a href="/day56/history?id=2">水浒传</a><br>
<a href="/day56/history?id=3">三国志</a><br>
  • 商品浏览记录
String id = request.getParameter("id");
Cookie cookie = null;
Cookie[] cookies = request.getCookies();
if (null != cookies && 0 != cookies.length){
    for (Cookie sonCookie : cookies) {
        if ("history".equals(sonCookie.getName())) {
            cookie = sonCookie;
        }
    }
}

if (null == cookie) {
    //之前没有任何浏览记录 ,创建Cookie对象 ,并存储浏览记录(id)
    cookie = new Cookie("history",id);
} else {
    //之前有一些浏览记录
    String historyStr = cookie.getValue();
    if (!historyStr.contains(id)) {
        //有一些记录,但是不包含当前浏览的商品;
        //将浏览商品拼接到已有浏览记录中
        //120
        //1-2-0
        historyStr += "-"+id;
        cookie.setValue(historyStr);

    } else {
        //有一些记录,包含当前浏览的商品 ,不做任何处理

    }
}
response.addCookie(cookie);
//上述代码,已经完成了商品浏览记录功能,剩下就是要显示商品浏览记录
response.sendRedirect(request.getContextPath()+ File.separator+"showHistory");

07_CookieUtils工具类

  • 获取指定名称的Cookie对象
public static Cookie getCookie(Cookie[] cookies ,String cookieName){
    if (null != cookies && 0 != cookies.length) {
        for (Cookie sonCookie : cookies) {
            if (cookieName.equals(sonCookie.getName())) {
                return sonCookie;
            }
        }
    }
    return null;
}

08_Session基本使用

  • Cookie之所以叫做浏览器会话,原因是Cookie的数据存储到浏览器!
  • Session之所以叫做服务器会话,原因是Session的数据存储到服务器!
  • 执行流程
    • 第一次请求Demo01Servlet时,根据request.getSession方法, 新建一个session对象;
    • 当第一次响应时,会将该session对象的id作为cookie头响应给浏览器保存
      set-cookie:JSESSIONID=4741C65CC84788A204E87EB870196EB0
    • 第二次请求Demo01Servlet时,根据request.getSession方法,请求中会有cookie头
      Cookie:JSESSIONID=4741C65CC84788A204E87EB870196EB0
    • 会根据该JSESSIONID去服务器中找有没有对应的session对象,如果有就直接用,没有就新建!!!

09_Session相关配置

  • 生命周期
    • session默认是有30分钟的存活时间,参考tomcat中的web.xml
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
  • session和cookie是相关联的,cookie中存储了jsessionid,request.getSession方法会根据jsessionid去选择,到底是新建session对象,还是引用原来的session对象;如果,将浏览器关闭了,就意味着cookie中存储的jsessionid就会销毁,对应request.getSession就会新建一个session对象,但是原来的session对象还存在!
  • session.invalidate方法,立马将对应的session对象销毁!后续就会新建session!
  • 注意事项
    • 关闭浏览器,session会怎么样?
    • 销毁session,下一次的geSession怎么样?
  • 总结
    • session只有两种情况会销毁
      • 调用了invalidate方法
      • 过了30分钟

01_session的基本使用

  • setAttribute
    • 往session域对象中存储数据
  • getAttribute
    • 从session域对象中获取数据
  • removeAttribute
    • 把session域对象中的数据移除

02_session案例之登录

  • 登录功能
    • UserDao
public class UserDaoImpl implements UserDao {
    @Override
    public User login(User inputUser) throws SQLException {
//        ComboPooledDataSource就是连接池,连接池包含很多连接对象
//        连接池作用就是减少连接的创建次数!
//        第一个用户,登录,创建一个连接池,创建3个连接
//        第二个用户,登录,创建一个连接池,创建3个连接
//        应该只让连接池创建一次!!后面复用就OK了!!
        QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
        User existUser = queryRunner.query(
                "select * from tb_user where username = ? and password = ?",
                new BeanHandler<User>(User.class),
                inputUser.getUsername(),
                inputUser.getPassword());

        return existUser;
    }
}
  • LoginServlet
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    private UserDao userDao = new UserDaoImpl();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User inputUser = new User();
        inputUser.setUsername(username);
        inputUser.setPassword(password);
        try {
            User existUser = userDao.login(inputUser);
            System.out.println(existUser);
            //判断登录成功
            if (null == existUser) {
                //登录失败,请求转发,跳转到登录页面
                request.getRequestDispatcher("/login.html").forward(request,response);
            } else {
                //登录成功,重定向,跳转到显示用户信息
                //存储existUser
                //request : 跳转到首页,使用了重定向,会有一个新的请求
                //servletContext : 如果存储到ServletContext,就意味着所有人都可以拿到你的用户信息!
                //cookie : 如果存储到cookie中,就是存储到浏览器 , 不安全! cookie中是无法存储中文及一些特殊符号!!
                //session : 数据存储到服务器!!
                request.getSession().setAttribute("existUser",existUser);
                response.sendRedirect("/day57/showIndex");

            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

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

  • 显示用户信息
    • ShowIndexServlet
@WebServlet(name = "ShowIndexServlet" ,urlPatterns = "/showIndex")
public class ShowIndexServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        User existUser = (User) request.getSession().getAttribute("existUser");
        if (null != existUser) {
            //在登录状态
            response.getWriter().write("欢迎回来,"+existUser.getUsername());
        } else {
            //不在登录状态
            //方式一:提示下,未登录
//            response.getWriter().write("您还没有登录,<a href='/day57/login.html'>请登录</a>");
            //方式二:跳转到登录页面
            response.sendRedirect("/day57/login.html");
            //看需求,选择方式一还是方式二
            //登录状态权限管理!!
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
  • 注意事项
    • 第三方jar包,必须放到WEB-INF文件夹中
    • 登录失败使用请求转发、登录成功使用重定向!

03_session案例之随机验证码

  • 显示验证码
    • 创建图片对象
    • 画背景
    • 画边框
    • 画干扰线
    • 产生四位随机数,存储到session
    • 画四位随机数
    • 将图片响应到浏览器
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width = 60;//定义图片宽度
        int height = 32;//定义图片高度
        //创建图片对象
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //创建画笔对象
        Graphics g = image.getGraphics();
        //设置背景颜色
        g.setColor(new Color(0xDCDCDC));
        g.fillRect(0, 0, width, height);//实心矩形
        //设置边框
        g.setColor(Color.black);
        g.drawRect(0, 0, width - 1, height - 1);//空心矩形

        Random rdm = new Random();
        //画干扰椭圆
        for (int i = 0; i < 50; i++) {
            int x = rdm.nextInt(width);
            int y = rdm.nextInt(height);
            g.drawOval(x, y, 0, 0);
        }
        //产生随机字符串
        String hash1 = Integer.toHexString(rdm.nextInt());
        //生成四位随机验证码
        String capstr = hash1.substring(0, 4);
        //将产生的验证码存储到session域中,方便以后进行验证码校验!
        request.getSession().setAttribute("existCode", capstr);
        System.out.println(capstr);
        g.setColor(new Color(0, 100, 0));
        g.setFont(new Font("Candara", Font.BOLD, 24));
        g.drawString(capstr, 8, 24);
        g.dispose();
        //将图片响应到浏览器
        response.setContentType("image/jpeg");
        OutputStream strm = response.getOutputStream();
        ImageIO.write(image, "jpeg", strm);
        strm.close();
    }
//获取输入的验证码
String validateCode = request.getParameter("validateCode");
//将输入的验证码和产生的随机验证码进行校验
String existCode = (String) request.getSession().getAttribute("existCode");
if (validateCode.equals(existCode)) {
    //校验通过,完成登录功能
} else {
    //校验不通过,跳转到登录页面

}

04_自定义DbUtils之增删改

  • 相同点
    • 1,获取连接
    • 4,执行sql语句
    • 5,释放资源
  • 不同点
    • 2,sql语句
    • 3,设置参数
  • 代码实现
public static void update(String sql , Object... parameters){
    Connection connection = null;
    PreparedStatement statement = null;
    try {
        connection = JDBCUtils.getConnection();
        statement = connection.prepareStatement(sql);
        //设置参数值的时候,参照的是parameters的个数! 应该参照有多少个问号?
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        for (int i = 0; i < parameterMetaData.getParameterCount(); i++) {
            statement.setObject(i + 1,parameters[i]);
        }
        statement.executeUpdate();
    } catch (Exception throwables) {
        throwables.printStackTrace();
    } finally {
        JDBCUtils.release(connection, statement);
    }
}

05_自定义DbUtils之查询

  • 相同点
    • 1,获取连接
    • 5,释放资源
  • 不同点
    • 2,sql语句
    • 3,设置参数
    • 4,处理结果集
  • 代码实现
    • MyResultSetHandler接口
      • 处理结果集,并得到想要的类型的数据
public interface MyResultSetHandler<T> {


    /**
     * 处理结果集,并返回想要的类型的数据
     * @param resultSet 结果集
     * @return 要的类型的数据
     * @throws Exception
     */
    T handle(ResultSet resultSet) throws Exception;

}
  • 通用query方法
public static<T> T query(String sql ,MyResultSetHandler<T> handler,Object... parameters ){
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    try {
        connection = JDBCUtils.getConnection();
        statement = connection.prepareStatement(sql);
        for (int i = 0; i < statement.getParameterMetaData().getParameterCount(); i++) {
            statement.setObject(i+1 , parameters[i]);
        }
        resultSet = statement.executeQuery();
        //处理结果集 , 返回结果
        T t = handler.handle(resultSet);
        return t;
    } catch (Exception throwables) {
        throwables.printStackTrace();
    } finally {
        JDBCUtils.release(connection,statement,resultSet);
    }
    return null;
}
  • 测试代码
User existUser = MyDbUtils.query("select * from tb_user where id = ?",
    new MyResultSetHandler<User>() {
    @Override
    public User handle(ResultSet resultSet) throws Exception {
        User user = null;
        while (resultSet.next()) {
            Integer id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            user = new User(id, username, password);
        }
        return user;
    }
}, 2);
System.out.println(existUser);
  • 存在的问题
    • 结果集的处理太麻烦,具体体现在处理结果集的具体实现上!!
  • 解决思路
    • 如果结果集处理之后返回的是单条记录,封装好一个MyBeanHandler
    • 如果结果集处理之后返回的是多条记录,封装好一个MyBeanListHandler

01_自定义DbUtils之MyBeanHandler

  • 概念
    • 封装单条记录的结果集处理
  • 开发步骤
    • MyResultSetHandler接口上的泛型由MyBeanHandler的泛型确定
    • 声明一个Class对象的引用
    • 重写handle方法
  • 代码实现
public class MyBeanHandler<T> implements  MyResultSetHandler<T> {

    private Class<T> clazz;//User类Class对象,也可以是Student类Class对象

    public MyBeanHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public T handle(ResultSet resultSet) throws Exception {
        T t = clazz.newInstance();
        //处理结果集
        while (resultSet.next()){
            //id属性值,username属性值,password属性值
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //字段名称
                String fieldName = field.getName();
                //字段值
                Object fieldValue = resultSet.getObject(fieldName);
                //将字段值设置Class对象对应的java实体对象
                //获取字段对应set方法
                String methodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
                Method method = clazz.getMethod(methodName, field.getType());
                if (null != method) {
                    method.invoke(t,fieldValue);
                }
            }
        }
        return t;
    }
}

02_自定义DbUtils之MyBeanListHandler

  • 概念
    • 封装多条记录的结果集处理
  • 开发步骤
    • MyResultSetHandler接口上的泛型由MyBeanListHandler的泛型确定
      • 已经确定了返回的是集合,只是不确定集合中的元素的类型
      • MyBeanListHandler只确定集合中元素的类型就可以了
    • 声明一个Class对象的引用
    • 重写handle方法
  • 代码实现
public class MyBeanListHandler<T> implements MyResultSetHandler<List<T>> {

    private Class<? extends T> clazz;//集合中元素的Class对象

    public MyBeanListHandler(Class<? extends T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public List<T> handle(ResultSet resultSet) throws Exception {
        List<T> list = new ArrayList<>();
        while (resultSet.next()) {
            //循环一次,就是一条记录,就是一个对象
            T t = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                String fieldName = field.getName();
                Object fieldValue = resultSet.getObject(fieldName);
                //获取set方法
                String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
                Method method = clazz.getMethod(methodName, field.getType());
                if (null != method) {
                    method.invoke(t,fieldValue);
                }
            }
            list.add(t);
        }
        return list;
    }
}

03_过滤器的概念

  • 概念
    • 过滤器就是一个用于在请求之前处理资源的组件
  • 生命周期
    • 随着服务器启动而初始化
    • 随着请求的发出而过滤
    • 随着服务器关闭而销毁
  • 执行流程
    • 浏览器发起请求
    • 服务器会根据这个请求,创建request对象及response对象
    • 过滤器会持有request对象及response对象
    • 只有当过滤器放行之后,request对象及response对象才会传给Serlvet
  • 过滤器链
    • 根据配置顺序,遵从"先过滤,后放行"的原则!

04_过滤器的基本使用

  • 开发步骤
    • 自定义类实现Filter接口
    • 重写init、doFilter、destroy方法
    • 在web.xml中配置过滤器
      • 声明过滤器
      • 过滤器配置过滤路径
  • 代码实现
    • 过滤器
public class Demo01Filter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //Demo01Filter过滤器的初始化
        System.out.println("Demo01Filter初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //Demo01Filter过滤器处理请求
        System.out.println("Demo01Filter放行之前");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Demo01Filter放行之后");
    }

    @Override
    public void destroy() {
        //Demo01Filter过滤器的销毁
        System.out.println("Demo01Filter销毁");
    }
}

web.xml

<!--声明Demo01Filter过滤器-->
<filter>
    <filter-name>Demo01Filter</filter-name>
    <filter-class>com.qfedu.filter.Demo01Filter</filter-class>
</filter>

<!--配置Demo01Filter的过滤路径-->
<filter-mapping>
    <filter-name>Demo01Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

05_过滤器的相关配置

  • 初始化参数
    • Filter配置初始化参数
    <filter>
        <filter-name>Demo03Filter</filter-name>
        <filter-class>com.qfedu.filter.Demo03Filter</filter-class>
        <!--初始化参数-->
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>root123</param-value>
        </init-param>

    </filter>

Filter获取初始化参数

public class Demo03Filter implements Filter {

    public void init(FilterConfig config) throws ServletException {
        Enumeration<String> parameterNames = config.getInitParameterNames();
        while (parameterNames.hasMoreElements()) {
            //获取初始化参数名称
            String parameterName = parameterNames.nextElement();
            //获取初始化参数值
            String parameterValue = config.getInitParameter(parameterName);
            System.out.println("name : " + parameterName + " , value : " + parameterValue);
        }
    }
    
    ......
    
}

Filter的过滤路径

  • 针对 ,以为Filter仅针对Demo01Servlet进行过滤
<filter-mapping>
    <filter-name>Demo03Filter</filter-name>
    <servlet-name>Demo01Servlet</servlet-name>
</filter-mapping>

针对

  • 完全匹配:必须以"/"开头
<filter-mapping>
    <filter-name>Demo03Filter</filter-name>
    <url-pattern>/aa</url-pattern>
</filter-mapping>
    • 过滤器只过滤访问路径目录匹配到“/aa/bb“的资源
  • 后缀名匹配:必须以"*"开头,以后缀名结尾
<filter-mapping>
    <filter-name>Demo03Filter</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>

01_过滤器应用之敏感词屏蔽

  • 代码实现
@WebFilter(
        filterName = "SensitiveWordsFilter" ,
        urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "word1",value = "笨蛋"),
                @WebInitParam(name = "word2" ,value = "老邱"),
                @WebInitParam(name = "word3" ,value = "中邱"),
                @WebInitParam(name = "word4",value = "小邱")
        })
public class SensitiveWordsFilter implements Filter {

    //敏感词
    List<String> sensitiveWords = new ArrayList<>();

    public void init(FilterConfig config) throws ServletException {
        Enumeration<String> parameterNames = config.getInitParameterNames();
        while (parameterNames.hasMoreElements()) {
            String sensitiveWord = config.getInitParameter(parameterNames.nextElement());
            sensitiveWords.add(sensitiveWord);
        }
    }

    public void destroy() {
    }



    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("SensitiveWordsFilter doFilter");
        HttpServletRequest request = (HttpServletRequest) req;
        //增强request下的getParameter方法
        HttpServletRequest requestPrxoy = (HttpServletRequest) Proxy.newProxyInstance(
                request.getClass().getClassLoader(),
                request.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //增强getParameter方法
                        Object returnValue = null;
                        String methodName = method.getName();
                        if ("getParameter".equals(methodName)) {
                            //returnValue就是getParameter方法的返回值,可能会存在敏感词
                            String returnValue1 = (String)method.invoke(request, args);
                            //开始处理敏感词
                            for (String sensitiveWord : sensitiveWords) {
                                if (returnValue1.contains(sensitiveWord)) {
                                    //getParameter方法的返回值包含敏感词
                                    returnValue1 = returnValue1.replace(sensitiveWord,"***");
                                }
                            }
                            return returnValue1;
                        } else {
                            returnValue = method.invoke(request, args);
                        }
                        return returnValue;
                    }
                });
        chain.doFilter(requestPrxoy, resp);
    }
}

02_监听器的介绍

  • 监听器概念
    • 事件源:事件发生的源头
    • 监听器:监听事件发生
    • 绑定:将监听器绑定到事件源
    • 事件:能够触发监听器的事
  • Servlet监听器
    • 事件源:request域对象、session域对象、ServletContext域对象
    • 监听器:Servlet三种监听器
    • 绑定:配置web.xml
    • 事件:域对象发生改变

03_监听器的分类

  • 一类监听器
    • 监听域对象的创建、销毁
  • 二类监听器
    • 监听域对象中的属性变更(属性设置、属性替换、属性移除)
  • 三类监听器
    • 监听域对象的java对象的绑定

04_一类监听器的基本使用

  • 一类监听器
    • ServletRequestListener : 监听ServletRequest域对象的创建、销毁
    • HttpSessionListener :监听HttpSession域对象的创建、销毁
    • ServletContextListener : 监听ServletContext域对象的创建、销毁
  • 开发步骤
    • 自定义类实现一类监听器
    • 重写监听器中的方法
    • 配置web.xml
  • 代码实现
    • 监听器
public class MyListener01 implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //监听ServletContext域的初始化,随着服务器的启动
        System.out.println("ServletContext初始化");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //监听ServletContext域的销毁,随着服务器的关闭
        System.out.println("ServletContext销毁");
    }
}

web.xml(绑定)

<listener>
    <listener-class>com.qfedu.listener.MyListener01</listener-class>
</listener>
    • 事件源: ServletContext域对象
    • 监听器:ServletContextListener
    • 绑定: web.xml配置
    • 事件 : ServletContext域对象发生了创建、发生了销毁

05_二类监听器的基本使用

  • 分类
    • ServletRequestAttributeListener
      • 监听ServletRequest域对象中属性变更
    • HttpSessionAttributeListener
      • 监听HttpSession域对象中属性变更
    • ServletContextAttributeListener
      • 监听ServletContext域对象中属性变更
  • 代码实现
    • 监听器
public class MyServletContextAttributeListener implements ServletContextAttributeListener {

    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        //监听ServletContext域对象中属性添加
        System.out.println("ServletContext added");
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        //监听ServletContext域对象中属性值被替换
        System.out.println("ServletContext replaced");

    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        //监听ServletContext域对象中属性值移除
        System.out.println("ServletContext removed");

    }
}

web.xml(绑定)

<listener>
    <listener-class>com.qfedu.listener.MyServletContextAttributeListener</listener-class>
</listener>

03_三类监听器

  • HttpSessionBindingListener
    • 监听session域中的java对象的状态(绑定和解绑)
      • 绑定:将java对象存储到session域对象
      • 解绑:将java对象从session域对象移除
  • 监听器组成
    • 事件源:java对象
    • 监听器:HttpSessionBindingListener
    • 绑定:java对象实现HttpSessionBindingListener接口
    • 事件:java对象在session中状态发生改变
  • 代码实现
public class User implements HttpSessionBindingListener {


    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("User绑定");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("User解绑");
    }
    
    ......
    
}
  • 注意事项

    • HttpSessionBindingListener监听不需要在web.xml配置
      01_监听器的注解开发
  • @WebListener

    • 相当于在web.xml绑定了监听器
  • 代码实现

@WebListener
public class MyServletContextLIstener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext创建");
    }


    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext销毁");
    }
}

02_javaWeb综合案例之用户列表

  • 开发步骤
    • 获取用户列表放到首页完成
      • 登录状态才需要获取用户列表
  • 代码实现
    • UserDao
   @Override
    public List<User> selectUserList() throws Exception {
        return new QueryRunner(JDBCUtil.getDataSource())
                .query("select * from tb_user",
                        new BeanListHandler<User>(User.class));
    }

ShowIndexSerlvet

@WebServlet(name = "ShowIndexServlet" ,urlPatterns = "/showIndex")
public class ShowIndexServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        User existUser = (User) request.getSession().getAttribute("existUser");
        StringBuffer responseBody = new StringBuffer();
        if (null != existUser) {
            //已经在登录状态
            responseBody.append("欢迎回来~ " + existUser.getUsername());
            responseBody.append(" <a href='/day60/logout'>注销</a><br>");

            //获取用户列表
            UserDao userDao = new UserDaoImpl();
            try {
                List<User> userList = userDao.selectUserList();
                System.out.println(userList);
                responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");

                responseBody.append("<tr>");
                responseBody.append("<td>ID</td>");
                responseBody.append("<td>账户</td>");
                responseBody.append("<td>密码</td>");
                responseBody.append("</tr>");

                for (User user : userList) {
                    //遍历一个User对象,对应就应该有一个tr
                    responseBody.append("<tr>");
                    responseBody.append("<td>"+user.getId()+"</td>");
                    responseBody.append("<td>"+user.getUsername()+"</td>");
                    responseBody.append("<td>"+user.getPassword()+"</td>");
                    responseBody.append("</tr>");

                }

                responseBody.append("</table>");
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else {
            //不在登录状态
            responseBody.append("您还没有登录,<a href='/day60/login.html'>请登录</a><br>");
        }

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(responseBody.toString());
    }

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

03_javaWeb综合案例之删除用户

  • 开发步骤
    • 首页,给每一个记录后面添加一个删除按钮
    • 用户列表不要显示当前登录用户
  • 代码实现
    • UserDao
 @Override
    public void deleteUserById(Integer id) throws Exception {
        new QueryRunner(JDBCUtil.getDataSource())
                .update("delete from tb_user where id = ?",
                        id);
    }

ShowIndexServlet

responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");
responseBody.append("<tr>");
responseBody.append("<td>ID</td>");
responseBody.append("<td>账户</td>");
responseBody.append("<td>密码</td>");
responseBody.append("<td>操作</td>");
responseBody.append("</tr>");

for (User user : userList) {

    if ( user.getId() != existUser.getId()) {
        //遍历一个User对象,对应就应该有一个tr
        responseBody.append("<tr>");
        responseBody.append("<td>"+user.getId()+"</td>");
        responseBody.append("<td>"+user.getUsername()+"</td>");
        responseBody.append("<td>"+user.getPassword()+"</td>");
        responseBody.append("<td><a href='/day60/deleteUser?id="+user.getId()+"'>删除</a></td>");
        responseBody.append("</tr>");
    }
}

responseBody.append("</table>");

DeleteUserServlet

@WebServlet(name = "DeleteUserServlet" ,urlPatterns = "/deleteUser")
public class DeleteUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String idStr = request.getParameter("id");
        Integer id = Integer.parseInt(idStr);
        UserDao userDao = new UserDaoImpl();
        try {
            userDao.deleteUserById(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.sendRedirect("/day60/showIndex");
    }

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

04_javaWeb综合案例之批量删除

  • 开发流程
    • 在首页需要给每一个记录新加多选框
    • 当点击批量删除按钮之后,完成批量删除操作
  • 代码实现
    • UserDao
  public void deleteUsersByIds(List<Integer> idList) throws Exception {
        for (Integer id : idList) {
            deleteUserById(id);
        }
    }

ShowIndexServlet

responseBody.append("<form action='/day60/deleteUsers' method='post'>");
responseBody.append("<table border='1px' cellspaceing='0px' cellpadding='10px' width='500px' height='200px'>");
responseBody.append("<tr>");
responseBody.append("<td></td>");
responseBody.append("<td>ID</td>");
responseBody.append("<td>账户</td>");
responseBody.append("<td>密码</td>");
responseBody.append("<td>操作</td>");
responseBody.append("</tr>");

for (User user : userList) {
    if ( user.getId() != existUser.getId()) {
        //遍历一个User对象,对应就应该有一个tr
        responseBody.append("<tr>");
        responseBody.append("<td><input name='ids' type='checkbox' value='"+user.getId()+"'></td>");
		......
        responseBody.append("</tr>");
    }
}
responseBody.append("</table>");
responseBody.append("<button type='submit'>批量删除</button>");
responseBody.append("</form>");

05_javaWeb综合案例之添加用户

  • 开发步骤
    • 首页加入一个添加用户按钮
    • 点击添加用户按钮进入到登录页面
  • 代码实现
    • UserDao
 public void addUser(User inputUser) throws Exception {
        new QueryRunner(JDBCUtil.getDataSource())
                .update("insert into tb_user(username ,password) values(?,?)",
                        inputUser.getUsername(),
                        inputUser.getPassword());
    }

ShowIndexServlet

//已经在登录状态
responseBody.append("欢迎回来~ " + existUser.getUsername());
responseBody.append(" <a href='/day60/logout'>注销</a><br>");
responseBody.append("<a href='/day60/add.html'>添加用户</a><br>");

AddUserServlet

@WebServlet(name = "AddUserServlet" ,urlPatterns = "/addUser")
public class AddUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User inputUser = new User();
        inputUser.setUsername(username);
        inputUser.setPassword(password);
        //方式一:在添加之前,校验下用户名是否存在
        //方式二:让username字段有唯一约束!
        UserDao userDao = new UserDaoImpl();
        try {
            userDao.addUser(inputUser);
            //添加成功,跳转到首页
            response.sendRedirect("/day60/showIndex");

        } catch (Exception e) {
            e.printStackTrace();
            //添加失败,跳转到添加用户页面
            response.sendRedirect("/day60/add.html");
        }

    }

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

06_javaWeb综合案例之修改用户

  • 开发步骤
    • 首页加入修改按钮
  • 代码实现
    • UserDao
@Override
    public void updateUser(User user) throws Exception {
        new QueryRunner(JDBCUtil.getDataSource())
                .update("update tb_user set username = ? , password = ? where id = ?",
                        user.getUsername(),
                        user.getPassword(),
                        user.getId());
    }

ShowIndexServlet

for (User user : userList) {
    if ( user.getId() != existUser.getId()) {
        //遍历一个User对象,对应就应该有一个tr
        responseBody.append("<tr>");
        responseBody.append("<td><input name='ids' type='checkbox' value='"+user.getId()+"'></td>");
        responseBody.append("<td>"+user.getId()+"</td>");
        responseBody.append("<td>"+user.getUsername()+"</td>");
        responseBody.append("<td>"+user.getPassword()+"</td>");
        responseBody.append("<td>" +
                            "<a href='/day60/deleteUser?id="+user.getId()+"'>删除</a> " +
                            "<a href='/day60/showUpdateUser?id="+user.getId()+"'>修改</a>"+
                            "</td>");
        responseBody.append("</tr>");
    }
}

显示修改用户页面

@WebServlet(name = "ShowUpdateUserServlet" , urlPatterns = "/showUpdateUser")
public class ShowUpdateUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        //根据id查询用户
        UserDao userDao = new UserDaoImpl();
        StringBuffer responseBody = new StringBuffer();
        try {
            User user = userDao.selectUserById(id);
            System.out.println(user);
            responseBody.append("<form action='/day60/updateUser' method='post'>");
            responseBody.append("<input type='hidden' name='id' value='"+user.getId()+"'/>");
            responseBody.append("账户:<input type='text' name='username' value='"+user.getUsername()+"'/><br>");
            responseBody.append("密码:<input type='text' name='password' value='"+user.getPassword()+"'/><br>");
            responseBody.append("<button type='submit'>修改</button>");
            responseBody.append("</form>");


        } catch (Exception e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(responseBody.toString());

    }

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

修改用户

@WebServlet(name = "UpdateUserServlet" ,urlPatterns = "/updateUser")
public class UpdateUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username : " + username + ", password : " + password);
        //要修改的内容:username、password
        User user = new User(id,username,password);
        UserDao userDao = new UserDaoImpl();
        try {
            userDao.updateUser(user);
            //修改成功,跳转到首页
            response.sendRedirect("/day60/showIndex");
        } catch (Exception e) {
            e.printStackTrace();
            //修改失败,跳转到修改页面
            response.sendRedirect("/day60/showUpdateUser?id="+id);

        }
    }


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