同过滤器
过滤器是在服务器启动时就会创建的,只会创建一个实例,常驻内存,也就是说服务器一启动就会执行Filter的
init(FilterConfig config)
方法.当Filter被移除或服务器正常关闭时,会执行destroy方法。
<%--
Created by IntelliJ IDEA.
User: PitYk
Date: 2020/7/11
Time: 11:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
当前有
<%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>
人在线
$END$
因为监听器获取当前Session的id情况,每个浏览器是一种Session,所以不用设计请求。
public class OnlineCountListener implements HttpSessionListener {
//创建session监听: 看你的一举一动
//一旦创建Session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听
//一旦销毁Session就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1. 手动销毁 getSession().invalidate();
2. 自动销毁
*/
}
<listener>
<listener-class>com.pit.listener.OnlineCountListenerlistener-class>
listener>
<session-config>
<session-timeout>1session-timeout>
session-config>
如果出现第一次打开浏览器,在线人数过多的情况,你只需要重启服务器。
因为我的电脑打开了3个浏览器,所以会有3个Session的id存在
参考博客:Java Web之过滤器(Filter)https://blog.csdn.net/yuzhiqiang_1993/article/details/81288912
过滤器是在服务器启动时就会创建的,只会创建一个实例,常驻内存,也就是说服务器一启动就会执行Filter的init(FilterConfig config)
方法.
当Filter被移除或服务器正常关闭时,会执行destroy方法。
在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。
如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下
过滤器设计
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain : 链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续同行
chain.doFilter(request,response);
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
web.xml过滤器配置
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/servlet/*url-pattern>
filter-mapping>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录
<%--此处action路径==web.xml内urlpattern设计!!!请求响应到LoginServlet--%>
注意!登录页面Login.jsp
登录采用的是post方式提交,所以LoginServlet
中后端设计也在doPost
方法内。
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端请求的参数
String username = req.getParameter("username");
if (username.equals("admin")){ //登录成功
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
}else { //登录失败
resp.sendRedirect("/error.jsp");
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
/*
* 上述引入了Constant类,目的在于设计“常量”思想,避免程序文件复杂时的频繁修改参数问题!
* 此外,还可设计多VIP区分!
*/
在util
包下,新增该类!
package com.kuang.util;
public class Constant {
public final static String USER_SESSION = "USER_SESSION";
}
/*
User
id
name
level 等级
VIP1
VIP2
VIP3
VIP4
*/
右键新增LoginServlet
后,自动跳转到web.xml
进行Servlet
映射
<servlet>
<servlet-name>LoginServletservlet-name>
<servlet-class>com.pit.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>LoginServletservlet-name>
<url-pattern>/servlet/loginurl-pattern>
servlet-mapping>
web
包下新增sys文件夹,登陆成功页面:success.jsp
目的在于方便后面过滤器的设计,将过滤sys文件下所有的Servlet请求!!!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
主页
登陆失败页面设计:error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
错误
没有权限,用户名错误
返回登录页面
登录成功,进入主页;点击注销,返回登录界面;登陆失败,返回登录界面!
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
if (user_session!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/Login.jsp");
}else {
resp.sendRedirect("/Login.jsp");
}
}
}
Logout请求获取Session
的Constant.USER_SESSION
属性,
根据该属性值进行跳转!==null
,已经注销过了,直接跳转到login;!=null
,移除Session的USER_SESSION属性。
注意编辑tomcat的布置路径为"/"即可!
登录、注销页面均运行良好,但是会出现一个问题:在首次登录成功后,注销,然后再网页的url内直接输入succes.jsp也可以直接跳转到首页显示。
分析:因为虽说在logout的servlet请求内,注销操作remove了Session属性,但是网页url页面跳转 success.jsp 是直接显示,并没有获取判断该属性是否还存在。
解决方法:
引入过滤器对 success.jsp 页面跳转条件 进行 判断拦截!
在filter包新增 SysFilter.jsp
过滤器:
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// ServletRequest HttpServletRequest
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(request,response);
}
public void destroy() {
}
}
在web.xml
内注册该过滤器
<filter>
<filter-name>SysFilterfilter-name>
<filter-class>com.pit.filter.SysFilterfilter-class>
filter>
<filter-mapping>
<filter-name>SysFilterfilter-name>
<url-pattern>/sys/*url-pattern>
filter-mapping>
ss.jsp 页面跳转条件 进行 判断拦截!
在filter包新增 SysFilter.jsp
过滤器:
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// ServletRequest HttpServletRequest
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(request,response);
}
public void destroy() {
}
}
在web.xml
内注册该过滤器
<filter>
<filter-name>SysFilterfilter-name>
<filter-class>com.pit.filter.SysFilterfilter-class>
filter>
<filter-mapping>
<filter-name>SysFilterfilter-name>
<url-pattern>/sys/*url-pattern>
filter-mapping>