前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Listener与Filter监听器基础使用

Listener与Filter监听器基础使用

作者头像
全栈工程师修炼指南
发布2020-10-23 15:36:37
5770
发布2020-10-23 15:36:37
举报

[TOC]

1.Listener
1) 基础介绍

Q:Listener是什么?有什么用? 答:Listener监听器,用于监听某一个事件的发生。

Q:监听器的内部机制是什么? 答:实就是接口回调,事件源->监听器;

需求:> A在执行循环当循环到5的时候通知B进行执行

事先先把一个对象传递给 A ,当A 执行到5的时候通过这个对象来调用B中的方法;但是注意不是直接传递B的实例,而是传递一个接口的实例过去。

基础实例(监听器内部机制):

A 和 B 两者中间接住去联系上,所以一开始在执行A的Print方法,先把一个接口的实现类传递给A,然后A在根据这个对象调用B的方法; 这样处理的好处在定义该方法的时候,不用考虑以后开发B类或者C类还是D类,只要预定义一种接口,并且方未来缩写的那些类实现这个借口,然后这个方法参数写接口类型即可;

/**A.java
 * @desc A类入口Test传入接口方法,假设也是2018缩写
 * @author WeiyiGeek
 */
public class A {
    public void Test(MessageListener msg) {
        for (int i = 0; i < 10; i++) {
           System.out.println("2018年A方法,当前Index:"+i);
           if( i == 5) {
               System.out.println("2018年A方法,已经到"+i+"正在通知B进行方法执行!");
               msg.print();
           }
        }
    }
}

/* MessageListener.java
 * @Desc 监听器接口假设在2018所缩写
 */
public interface MessageListener {
   void print();
}

/* B.java
 * @Desc B类实现MessageListener监听器接口,2020年所写
 */
public class B implements MessageListener {
    @Override
    public void print() {
        // TODO Auto-generated method stub
        System.out.println("我是2020年B类方法我正在执行......");
    }
}


//程序入口:/Web/src/top/weiyigeek/listener/Test.java
public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        A demo = new A();
        demo.Test(new B());  //多态的体现,此处将B实例类传递给Test方法中MessageListener接口参数,实际上是父类引用指向子类方法;
    }
}

执行结果:

2018年A方法,当前Index:0
2018年A方法,当前Index:1
2018年A方法,当前Index:2
2018年A方法,当前Index:3
2018年A方法,当前Index:4
2018年A方法,当前Index:5
2018年A方法,已经到5正在通知B进行方法执行!
我是2020年B类方法我正在执行......
2018年A方法,当前Index:6
2018年A方法,当前Index:7
2018年A方法,当前Index:8
2018年A方法,当前Index:9
``` 

---

##### 1) Listener分类
描述: Web 监听器之Listener监听器的分类,总共有8个划分成三种类型;
- (1) application(作用域) -> ServletContext(类) -> `监听器: ServletContextListener`
  - 该监听器作用:初始化项目加载基础资源,任务调度(`比如执行某一个定时任务Timer`),以及开发者想完成自己初始化工作的方法
- (2) request -> HttpServletRequest -> `监听器: ServletRequestListener`
- (3) session -> HttpSession -> `监听器: HttpSessionListener`
   - 该监听器作用: 根据创建的session来统计在线人数;

<br>

##### 2) 生命周期
_类型1.监听三个作用域创建和销毁说明_
```bash
#ServletContextListener 监听器生命周期
#context创建:启动服务器的时候;  
public void contextInitialized(ServletContextEvent sce) {...} 
#context销毁:关闭服务器,从服务器移除项目;
public void contextDestroyed(ServletContextEvent sce) {...} 


#ServletRequestListener 监听器生命周期
#request创建:访问服务器上的任意资源都会有请求出现,触发情况访问 html、 jsp、 servlet进行触发;
public void requestInitialized(ServletRequestEvent sre) {} 
#request销毁:服务器已经对这次请求作出了响应。 
public void requestDestroyed(ServletRequestEvent sre) {}


#HttpSessionListener 监听器生命周期
#session创建:首次访问页面就就会调用getSession,但是需要注意可以触发的jsp / Servlet 而 html不会进行触发
public void sessionCreated(HttpSessionEvent se) {} 
- html:不会 
- jsp:会 getSession();
- servlet:会
#session销毁,条件超时30分钟以及非正常关闭销毁
public void sessionDestroyed(HttpSessionEvent se) {}

补充:监听器的创建于注册流程定义一个类实现*Listener接口,其次在/Web/WebContent/WEB-INF/web.xml注册配置监听器

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Web</display-name>
   <listener>
  	<listener-class>监听器类路径</listener-class>
  </listener>
</web-app>

基础实例1:

//ServletContextListener 监听器
package top.weiyigeek.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContentListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext: 初始化 .....");
    }
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext: 销毁了 .....");
    }
}


//ServletRequestListener 监听器
public class MyRequestListener implements ServletRequestListener {
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("servletRequest : 初始化....." + sre);
    }
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("servletRequest : 销毁了....." + sre);
    }
}


//HttpsessionListener 监听器
public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("HttpSession: 创建session了.....");
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("HttpSession: 销毁session了.....");
    }
}
WeiyiGeek.三种作用域监听器初始化和销毁
WeiyiGeek.三种作用域监听器初始化和销毁

WeiyiGeek.三种作用域监听器初始化和销毁

类型2.监听三个作用域属性状态变更 描述:三种作用域属性监听器的方法名称大致差不多只是方法参数Event事件不同,他们可以监听在作用域中值 添加 | 替换 | 移除 的动作,在实际开发中作用没上一类作用大。

#ServletContext -> ServletContextAttributeListener 属性监听器
#向servlet上下文添加/删除/替换新属性的通知
void attributeAdded(ServletContextAttributeEvent scab)  
void attributeRemoved(ServletContextAttributeEvent scab)
void attributeReplaced(ServletContextAttributeEvent scab)

#HttpServletRequest -> ServletRequestAttributeListener 属性监听器
void attributeAdded(ServletRequestAttributeEvent srae)
void attributeRemoved(ServletRequestAttributeEvent srae)
void attributeReplaced(ServletRequestAttributeEvent srae)

#HttpSession -> HttpSessionAttributeListener 属性监听器
void attributeAdded(HttpSessionBindingEvent se)
void attributeRemoved(HttpSessionBindingEvent se)
void attributeReplaced(HttpSessionBindingEvent se)

基础示例(此处采用HttpSessionAttributeListener为例):

/**
/Web/src/top/weiyigeek/listener/MyHttpSessionAttributeListener.java
 * @Desc 属性更改|替换|添加事件触发
 * @author WeiyiGeek
 */
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    public void attributeAdded(HttpSessionBindingEvent hsbe) {
        System.out.println("1.属性添加......");
    }
    public void attributeRemoved(HttpSessionBindingEvent hsbe) {
        System.out.println("2.属性移除......");
    }
    public void attributeReplaced(HttpSessionBindingEvent hsbe) {
        System.out.println("3.属性替换......");
    }
}


///Web/WebContent/Demo1/TestAttribute.jsp
<body>
<h1> TestAttribute.jsp 测试 监听器属性</h1>
<%
  //(1)session 作用域属性设置
  session.setAttribute("name", "WeiyiGeek");
  
  //(2)属性替换
  session.setAttribute("name", "TestWeiyi");
  //(3)移除属性
  session.removeAttribute("name");
%>
</body>

执行结果:

#以此可以大概了解各个监听器的生命周期
ServletContext: 初始化 .....
servletRequest : 初始化.....javax.servlet.ServletRequestEvent[source[email protected]]
HttpSession: 创建session了.....
1.属性添加......
3.属性替换......
2.属性移除......
servletRequest : 销毁了.....javax.servlet.ServletRequestEvent[source[email protected]]
ServletContext: 销毁了 .....

注意事项:

  • 第一类与第二类监听器在Web.xml中监听器才能在应用中正常使用;

类型3.监听httpSession里面存值的状态变更 描述:该类监听器不用在web.xml进行注册了,但是必须在您的Bean类中进行实现该类监听器的接口便可正常使用;

  • (1) HttpSessionBindingListener:监听对象与session 绑定和解除绑定 的动作#基础方法 public void valueBound(HttpSessionBindingEvent event) {...} public void valueUnbound(HttpSessionBindingEvent event) {...}

基础实例:

///Web/src/top/weiyigeek/main/BeanListener.java
/**
 * @Desc 第三类HttpSessionBindingListener监听器的实现,监听Session传值的状态改变;
 * @author WeiyiGeek
 */
public class BeanListener implements HttpSessionBindingListener {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    //由于 HttpSessionBindingListener 不用在Web.xml中进行注册,所以在使用中必须在Bean类中进行实现该接口
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("HttpSessionBinding:对象值 被 绑定....");
    }
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("HttpSessionBinding:对象值被 解除 绑定....");
    }
}

///Web/WebContent/Demo1/TestAttribute.jsp
<h1> TestAttribute.jsp 测试 监听器属性</h1>
<%
  //(1)session 作用域属性设置
  session.setAttribute("name", "WeiyiGeek");
  
  //(2)属性替换
  session.setAttribute("name", "TestWeiyi");
  
  //(3)移除属性
  session.removeAttribute("name");
%>
</body>

执行结果:

bashservletRequest : 初始化.....javax.servlet.ServletRequestEvent[source[email protected]]
HttpSession: 创建session了.....
HttpSessionBinding:对象值 被 绑定....
1.属性添加......
3.属性替换......
HttpSessionBinding:对象值被 解除 绑定....
2.属性移除......
servletRequest : 销毁了.....javax.servlet.ServletRequestEvent[source[email protected]]
#30分钟后
HttpSession:销毁session了.....
  • (2) HttpSessionActivationListener: 用于监听现在session的值 是 钝化 (序列化)还是活化 (反序列化)的动作 什么是钝化(序列化) ? 答:把内存中的数据存储到硬盘上。

什么是活化 (反序列化)? 答:把硬盘中的数据读取到内存中。

session的钝化活化的用意何在? 答:session中的值可能会很多, 并且我们有很长一段时间不使用这个内存中的值, 那么可以考虑把session的值可以存储到硬盘上【钝化】,等下一次在使用的时候,在从硬盘上提取出来。 【活化】

补充上述钝化后存储在E:\Development\apache-tomcat-9.0.31\work\Catalina\localhost\您的项目名称\SESSIONS.ser之中

基础示例:

///Web/src/top/weiyigeek/main/BeanActivation.java   #这里少不了Seariable他是用于序列化域反序列化;
public class BeanActivation implements HttpSessionActivationListener,Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    //钝化
    public void sessionWillPassivate(HttpSessionEvent hse) {
        System.out.println("- HttpSessionActivation(被钝化) , Session 值 =  " + hse.getSession().getId());
    }
    //活化
    public void sessionDidActivate(HttpSessionEvent hse) {
        System.out.println("- HttpSessionActivation(被活化) , Session 值 =  " + hse.getSession().getId());
    }
}


///Web/WebContent/Demo1/TestActivation.jsp
<H1>TestActivation.jsp | 该页面设置session作用域的值 (钝化)</H1>
<%
  //Session 钝化与活化
  BeanActivation bl = new BeanActivation();
  bl.setName("WeiyiGeek");
  
  //session.值获取
  session.setAttribute("bean", bl);
%>
</body>

///Web/WebContent/Demo1/TestActivation1.jsp
<H1>TestActivation1.jsp | 该页面获取session作用域的值(活化) </H1>
<%
  session.getAttribute("bean");
%>
session 作用域活化后的值:   ${bean.name}
</body>

执行结果(以首次访问的结果为例):

ServletContext: 初始化 .....
#TestActivation.jsp请求时候
servletRequest : 初始化.....javax.servlet.ServletRequestEvent[source[email protected]]
HttpSession: 创建session了.....
1.属性添加......
servletRequest : 销毁了.....javax.servlet.ServletRequestEvent[source[email protected]]

#Server Stop
- HttpSessionActivation(被钝化) , Session 值 =  7BA6BBF40A180E2BF0CBFC8B51F1F422
ServletContext: 销毁了 .....

#Server Start
ServletContext: 初始化 .....
- HttpSessionActivation(被活化) , Session 值 =  7BA6BBF40A180E2BF0CBFC8B51F1F422

#TestActivation1.jsp请求时候
servletRequest : 初始化.....javax.servlet.ServletRequestEvent[source[email protected]]
servletRequest : 销毁了.....javax.servlet.ServletRequestEvent[source[email protected]]
WeiyiGeek.
WeiyiGeek.

WeiyiGeek.

Q:如何让session的在一定时间内钝化? 答:在Tomcat容器配置文件中进行配置,可以从下面三处进行相应的配置;

  1. 在tomcat里面 conf/context.xml 里面配置,该配置对所有的运行在这个服务器的项目生效
  2. 在conf/Catalina/localhost/context.xml 配置,该配置只对 localhost 生效即localhost:8080
  3. 在自己的web工程项目中的 META-INF/context.xml, 只对当前的工程生效下面实践采用这样的方式。
<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="WeiyiGeek"/>
    </Manager>
</Context>

<!-- 
maxIdleSwap :1分钟不用就钝化
directory :钝化后的那个文件存放的目录位置。 
E:\Development\apache-tomcat-9.0.31\work\Catalina\localhost\项目名称\WeiyiGeek
产生文件:961977FE4FB87B89AD384C9DBC83A7EA.session
-->
WeiyiGeek.
WeiyiGeek.

WeiyiGeek.

2.Filter

Q:什么是Filter?他有什么作用? A:翻译过来是过滤器的意思, 主要是起到的是拦截作用 , 用于在客户端请求服务器资源的时候,执行过滤(拦截)

  • 如果过滤器放行,那么这个请求才能到达服务器
  • 如果过滤器拒绝放行,那么服务器就不会收到这个请求

应用场景比如: 1.对一些敏感词进行过滤替换; 2.设置统一的编码格式; 3.实现自动登录;

1) 基础使用

如何使用过滤器?其使用流程是什么? 1.定义一个类实现Filter接口,在doFilter方法之中进行过滤然后转发请求;

WeiyiGeek.
WeiyiGeek.

WeiyiGeek.

2.过滤器要想生效还必须在web.xml中进行配置,创建Filter实现类成功时你会在web.xml看到它注册了与Servlet进行比较发现只有两处名字不同:

<filter>
    <display-name>FilterDemo1</display-name>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>top.weiyigeek.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/*</url-pattern> <!-- 过滤所有的Request请求 -->
</filter-mapping>

基础示例:

/**
 * /Web/src/top/weiyigeek/filter/FilterDemo1.java
 * Servlet Filter implementation class FilterDemo1
 */
public class FilterDemo1 implements Filter {
    static int count = 0;
    //自动生成:构造方法
    public FilterDemo1() {}
  /*** @see Filter#destroy()*/
  public void destroy() {}
  //Filter过滤的入口方法
  /*** @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      //此处统一对用户请求的数据进行编码
      request.setCharacterEncoding("UTF-8");
      System.out.println((++count) + ".Filter(过滤器) - doFilter : 已获取用户请求正在做一些列的处理.....");
    // pass the request along the filter chain 链请求转发;
    chain.doFilter(request, response);
  }
  /*** @see Filter#init(FilterConfig) */
  public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
  }
}


///Web/src/top/weiyigeek/servlet/ServletFilter.java
//HttpServlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("ServletFilter - doGet() : 服务端已经接受到用户的请求 ");
    response.getWriter().append("Served at: ").append(request.getContextPath());
}
2) 生命周期

描述:Filter生命周期按照下述顺序进行;

  1. 创建:public void init(FilterConfig fConfig),服务器启动即创建过滤器实例,
  2. 过滤:public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain),在过滤器创建完成之后在接受到用户请求的时候经过URL-Pattern匹配成功则进行响应的处理
  3. 销毁:public void destroy(),服务器关闭即销毁过滤器实例,前提在服务器端被正常Stop时候触发执行;
3) 过滤器执行顺序

描述:如果项目中有多个过滤且多个Filter匹配路径都为全路径,那此时过滤器执行顺序如何? 答:过滤器拦截执行顺序与多个Filter过滤器在Web.xml注册的映射顺序有关(即按照此顺序来进行过滤执行);客户端向Servlet发起请求的时候必须先经过Filter如果Filter放行才能正在的访问Servlet;

基础示例:

///Web/src/top/weiyigeek/filter/FilterDemo2.java

/**
 * Servlet Filter implementation class FilterDemo2
 */
public class FilterDemo2 implements Filter {
    public FilterDemo2() {
        // TODO Auto-generated constructor stub
    }
  /**
	 * @see Filter#destroy()
	 */
  public void destroy() {
    System.out.println("FilterDemo2 : 过滤器被销毁......");
  }
  /**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("-请求进入 FilterDemo2 过滤器 .... Before Chain.doFilter");
    chain.doFilter(request, response);
      System.out.println("-响应进入 FilterDemo2 过滤器 .... Recevice");
  }
  /**
	 * @see Filter#init(FilterConfig)
	 */
  public void init(FilterConfig fConfig) throws ServletException {
     System.out.println("FilterDemo2 : 初始化创建过滤器......"+ fConfig.getFilterName());
  }
}

Web.xml 注册顺序:

<filter>
    <display-name>FilterDemo1</display-name>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>top.weiyigeek.filter.FilterDemo1</filter-class>
</filter>
<filter>
    <display-name>FilterDemo2</display-name>
    <filter-name>FilterDemo2</filter-name>
    <filter-class>top.weiyigeek.filter.FilterDemo2</filter-class>
</filter>

<!-- 注意点1.映射顺序 -->
<filter-mapping>
    <filter-name>FilterDemo2</filter-name>
    <!-- 注意点2.URL匹配 -->
    <url-pattern>/ServletFilter</url-pattern>
    <!-- 注意点3.请求类型过滤-->
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

执行结果:

url:http://localhost:8080/Web/ServletFilter

#信息: 正在启动 Servlet 引擎:[Apache Tomcat/9.0.31]
FilterDemo2 : 初始化创建过滤器 ..... FilterDemo2

-请求进入 FilterDemo2 过滤器 .... Before Chain.doFilter
-请求进入 FilterDemo1过滤器 .... Before Chain.doFilter
ServletFilter - doGet() : 服务端已经接受到用户的请求 
-响应进入 FilterDemo1 过滤器 .... Recevice
-响应进入 FilterDemo2 过滤器 .... Recevice

#信息: 正在停止服务[Catalina]
FilterDemo2 : 过滤器被销毁......

补充说明:

  • 0.init方法的参数FilterConfig可以用于获取filter在注册的名字以及初始化参数。其实这里的设计的初衷与ServletConfig是一样的,所以非必须的情况下我们不对齐进行操作;
  • 1.如果想放行请求那么必须在doFilter方法里面操作,使用chain.doFilter(request, response); 放行, 让请求到达下一个目标;
  • 2.Web.xml注册映射的Filter <url-pattern>/*</url-pattern> 写法格式有三种(此处算是复习)#全路径匹配 以 / 开始 : /LoginServlet #以目录匹配 以 / 开始 以 * 结束: /demo01/* #以后缀名匹配 以 * 开始 以后缀名结束 : *.jsp *.html *.do ****
  • 3.除了以上的配置,还可以在web.xml使用<dispatcher>元素来对当前的请求类型进行过滤:
    • REQUEST:默认过滤器只会拦截请求缺省
    • FORWARD:过滤器拦截转发
    • INCLUDE:过滤器拦截包含
    • ERROR:过滤器拦截全局错误页面的跳转。
4.基础实例

需求分析:实现自动登陆以及注册功能;

WeiyiGeek.
WeiyiGeek.

WeiyiGeek.

依赖的jar包:

  • /Web/WebContent/WEB-INF/lib/commons-beanutils-1.8.3.jar
  • /Web/WebContent/WEB-INF/lib/commons-logging-1.2.jar

beanutils 包常用方法:

#注册自己的日期转换器然后在BeanUtils中使用
ConvertUtils.register(new MyDateConverter(), Date.class);

#请求转化数据
Map map = request.getParameterMap();
UserBean bean = new UserBean();
#转化map中的数据放置到bean对象身上
BeanUtils.populate(bean, map);

基础实例: 首页:/Web/WebContent/default.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h3> WeiyiGeek blog  </h3>
<c:if test="${not empty user}">
<p> 欢迎您, ${user.sname} 用户</p>
</c:if>
<c:if test="${empty user}">
<p> 您好, <a href="./Login.jsp">请登陆</a></p>
</c:if>
</body>
</html>

登陆和注册页:

  • /Web/WebContent/Login.jsp
<div class="login" style="border: 1px black solid">
   <form action="LoginServlet" method="POST">
  用户: <input type="text" name="username"> <br/>
  密码: <input type="text" name="password"> <br/>
  <input type="checkbox" name="autoLogin"> 自动登陆   <br/>
   	<input type="submit" value="登陆">
   	<input type="button" value="注册" onclick="location.href='./Register.jsp'"> 
   </form>
</div>
  • /Web/WebContent/Register.jsp
<script>
	//## (2)JQuery实现Ajax异步请求(文档加载完毕时候进行)
	$("document").ready(function(){
	   $("#username").blur(function(){
	      var user = $(this).val();
	      console.log(user);
	      $.post("CheckUserServlet",{checkuser:user},function(data,status){
	          if (status == "success"){
	              //Jquery 直接解析 json 
		      		if(data.status){
					  $("#msg").html("<font color='green'>姓名可用!</font>");
		      		}else{
		      		  $("#msg").html("<font color='red'>姓名已存在!</font>");
		      		}
	          }
	      });
	   });
	});
	
</script>

<script>
function submit_check(){
    var pass1 = document.getElementById('password1').value;
    var pass2 = document.getElementById('password2').value;
    if ( pass1 != pass2 ){
        alert("两次输入的密码不一致!");
        return false;
    }
	if (confirm("您是否进行添加提交?") ) {
		return true;
	}else{
		return false;
	}
}
</script>
<div class="register" style="border: 1px black solid">

<form action="RegisterServlet" method="POST" onsubmit="return submit_check()">
   <label for="username">姓名:</label>
   <input type="text" name="username" id="username" onblur="checkUser()"/> &nbsp; <span id="msg"></span>
   <br>
    <label for="password">密码:</label>
    <input type="text" name="password" id="password1"/>
   <br>
    <label for="password2">密码确认:</label>
    <input type="text" id="password2"/>
   <br>
   <label for="gender">性别:</label>
   <input type="radio" name="gender" value="男">男
   <input type="radio" name="gender" value="女">女
   <br>
   
   <label for="telephone">电话号码:</label>
   <input type="tel" name="telephone" id="telephone"/>
   <br>
   
   <label for="job">工作职位:</label>
   <input type="checkbox" name="job" value="安全">安全
   <input type="checkbox" name="job" value="运维">运维
   <input type="checkbox" name="job" value="开发">开发
   <input type="checkbox" name="job" value="测试">测试
   <input type="checkbox" name="job" value="主管">主管
   <br>
   
     <label for="jointime">加入时间:</label>
   <input type="date" name="jointime"/>
   <br>
   
     <label for="info">备注:</label>
     <textarea rows="5" cols="30" name="info" id="info"></textarea>
   <br>
   <input type="submit" value="注册">
   <input type="reset" value="重置">
</form>
</div> 		  

登陆注册Servlet:

// /Web/src/top/weiyigeek/servlet/LoginServlet.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        request.setCharacterEncoding("UTF-8");
        //1.接收经过过滤器转发的数据
        Map map = request.getParameterMap();
        LoginBean lb = new LoginBean();
        BeanUtils.populate(lb, map);
        
        //2.调用dao进行数据库查询
        User user = new UserLoginImpl();
        Person result = user.userlogin(lb);
        
        //3.判断用户是否登录成功以及后面是进行自动登陆
        if(result != null) {
            if("on".equals(lb.getAutoLogin())) {
                //发送Cookies给客户端(实际开发中一定不要这么做不安全的-可以将session值传入redis+钝化)
                Cookie cookie = new Cookie("autoLogin",lb.getUsername()+"-"+lb.getPassword());
                cookie.setMaxAge(60*60*24*7);
                cookie.setPath("/");
                response.addCookie(cookie);
                System.out.println("ok");
            }
            
            //4.通过session作用域进行传值
            request.getSession().setAttribute("login", "true");
            request.getSession().setAttribute("user", result);
            response.sendRedirect("default.jsp");
            
        }else {
            //5.失败则跳转到登陆界面
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html; charset=UTF-8");
            response.getWriter().write("<script> alert('账号或者密码错误!,请验证后登陆!');location.href='Login.jsp';</script>");
            //request.getRequestDispatcher("Login.jsp").forward(request, response);
        }
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

// /Web/src/top/weiyigeek/servlet/RegisterServlet.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        //1.注册自己的日期转化器
        request.setCharacterEncoding("UTF-8");
        ConvertUtils.register(new MyDateConverter(), Date.class);
        
        //2.请求的数据转化
        Map map = request.getParameterMap();
        registerBean bean = new registerBean();
        BeanUtils.populate(bean, map);
        System.out.println(bean.toString());

        //3.调用Dao插入数据
        User uu = new UserLoginImpl();
        int flag = uu.userregister(bean);
        
        //4.根据注册情况进行跳转;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");

        if (flag > 0) {
            response.getWriter().write("<script>alert('注册成功');window.location.href='./Login.jsp'</script>");
        } else {
            response.getWriter().write("<script>alert('注册失败');window.location.href='./Register.jsp'</script>");
        }             
    } catch (IllegalAccessException | InvocationTargetException | SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
}

过滤器Filter:/Web/src/top/weiyigeek/filter/AutoLogin.java

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    //1.过滤器创建ServletRequest作用域;
      HttpServletRequest req = (HttpServletRequest) request;
      Object login = req.getSession().getAttribute("login");
      Person ps = (Person)req.getSession().getAttribute("user");
      
      //2.判断用户session是否有效
      if (login != null && ps != null) {
          System.out.println("#用户一已登录并且有效!");
           //有效则直接放行
          chain.doFilter(request, response);
      }else {
          //3.如果session失效则看Cookies中是否有自动登陆字段;
          Cookie[] cookies = req.getCookies();
          Cookie c = CookieUtil.findCookie(cookies, "autoLogin");
          if( c == null ) {
              //4.如果没有设置自动登陆则放行
              System.out.println("#用户未登陆或者未设置身份自动登陆....");
                chain.doFilter(request, response);
          }else {
              System.out.println("#Session失效,用户设置自动登陆-正在进行自动登陆!");
              //5.登陆字符串分隔
              String loginStr = c.getValue();
              String username = loginStr.split("-")[0];
              String password = loginStr.split("-")[1];
              LoginBean lb = new LoginBean(username,password,"on");
              System.out.println(lb.toString());
              
              //6.完成登陆对象的封装后直接调用Dao接口进行验证
              User uu = new UserLoginImpl();
              try {
                    ps = uu.userlogin(lb);
                    //7.使用session存这个值到域中,方便下一次未过期前还可以用。
                    req.getSession().setAttribute("user", ps);
                    chain.doFilter(request, response);
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    request.getRequestDispatcher("Login.jsp").forward(request, response);;
                } 
          } 
      } 
  }

Dao 数据库接口实现:

public class UserLoginImpl implements User {
    @Override
    public Person userlogin(LoginBean user) throws SQLException {
        QueryRunner qr = new QueryRunner(DB.getConn());
        Person res = qr.query("SELECT sid,sname,gender,telephone,job,info,jointime FROM person WHERE sname = ? and spass = ?", new BeanHandler<Person>(Person.class) , user.getUsername() , user.getPassword());
        return res;
    }

    @Override
    public int userregister(registerBean user) throws SQLException {
        QueryRunner runner = new QueryRunner(DB.getConn());
        int flag = runner.update("INSERT INTO person VALUES (NULL,?,?,?,?,?,?,?)",user.getUsername(),user.getPassword(),user.getGender(),user.getTelephone(),user.getJob(),user.getInfo(),user.getJointime());
        if(flag > 0) {
            System.out.println("#插入成功");
        }else {
            System.out.println("#添加失败");
        }
        return flag;
    }
}

工具类:/Web/src/top/weiyigeek/utils/MyDateConverter.java

/**
 * 自定义 java.util.Date日期转换器*/
public class MyDateConverter implements Converter {
  @Override
  // 将value 转换 c 对应类型
  // 存在Class参数目的编写通用转换器,如果转换目标类型是确定的,可以不使用c 参数
  public Object convert(Class c, Object value) {
    String strVal = (String) value;
    // 将String转换为Date --- 需要使用日期格式化
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    try {
      Date date = dateFormat.parse(strVal);
      return date;
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return null;
  }
}

执行结果:

WeiyiGeek.
WeiyiGeek.

WeiyiGeek.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Listener
    • 1) 基础介绍
    • 2.Filter
      • 1) 基础使用
        • 2) 生命周期
          • 3) 过滤器执行顺序
            • 4.基础实例
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档