接上一遍Filter基础知识,本文在两个应用场景下使用FIlter过滤器,加深理解应用。

本文目录

  • Filter案例
    • 一.案例1_登录验证
      • 1.0 正常的登录流程
      • 1.1 需求
      • 1.2 代码实现
        • 1.2.1 目录结构
        • 1.2.2 数据库准备
        • 1.2.3 页面login.jsp和index.jsp
        • 1.2.4 dao层
        • 1.2.5 domain层
        • 1.2.6 util层
        • 1.2.7 web层
      • 1.3 测试
    • 二.案例2_敏感词汇过滤
      • 2.1 需求分析
      • 2.2 代码实现
        • 2.2.1 目录结构
        • 2.2.2 核心代码

Filter案例

练习场景下使用过滤器,利用过滤器完成一些通用的操作。

一.案例1_登录验证

我们先正常的将登录流程走一遍,再对案例进行分析、实现。

1.0 正常的登录流程

用户登录界面:


登录成功:


比较简单的逻辑:

1.1 需求

  1. 访问用户登录后的资源。验证其是否登录
  2. 如果登录了,则直接放行。
  3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。

案例分析


过滤器核心代码:LoginFilter.java

需要注意的是:

  • 拦截请求过程中需要判断用户请求是否包含访问登录相关资源路径,要注意排除掉 css/js/图片/验证码等其它资源,否则请求这些资源也会被拦截掉,页面的样式就会丢失。
/*** 登录验证的过滤器*/
@WebFilter("/*")
public class LoginFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {//0.强制转换,因为ServletRequest接口的子接口HttpServletRequest才有获取请求路径的方法HttpServletRequest request = (HttpServletRequest) req;//1.获取资源请求路径String uri = request.getRequestURI();//2.判断是否包含登录相关资源路径,要注意排除掉 css/js/图片/验证码等资源if("/login.jsp".contains(uri) || "/LoginServlet".contains(uri) || "/css/".contains(uri) || "/js/".contains(uri) || "/fonts/".contains(uri) ){//包含,用户就是想登录。放行chain.doFilter(req, resp);}else{//不包含,需要验证用户是否登录//3.从获取session中获取userObject user = request.getSession().getAttribute("user");if(user != null){//登录了。放行chain.doFilter(req, resp);}else{//没有登录。跳转登录页面request.setAttribute("login_msg","您尚未登录,请登录!");request.getRequestDispatcher("/login.jsp").forward(request,resp);}}}public void init(FilterConfig config) throws ServletException {}public void destroy() {}
}

1.2 代码实现

1.2.1 目录结构


登录案例可以参考另一篇博文:【JavaWeb】综合案例:用户登录.

1.2.2 数据库准备

1.2.3 页面login.jsp和index.jsp

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>用户登录</title>
</head>
<body>
<form action="/LoginServlet" method="post">用户账号:<input type="text" placeholder="请输入账号" name="username"><br>用户密码:<input type="text" placeholder="请输入密码" name="password"><br><input type="submit" value="登录">
</form>
<!--提示信息-->
<p>${login_msg}</p>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>用户主页</title><!--导入css文件--><link rel="stylesheet" type="text/css" href="css/style.css" /></head>
<body>
<p>登录成功,用户名${user.username}欢迎您!</p><form action="/UpdateServlet" method="post"><input type="hidden" name="id" value="${user.id}"><label for="introduce">自我介绍:</label><input type="text" name="introduce" id="introduce" value="${user.introduce}"><input type="submit" value="修改自我介绍">
</form>
</body>
</html>

style.css

label{color: red;
}
1.2.4 dao层

UserDao.java

/*** 操作数据库的类*/
public class UserDao {//声明JDBCTemplate对象共用private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());/*** 登录方法** @param loginUser* @return user包含用户全部数据,没有查询到,放回null*/public User login(User loginUser) {try {//1.编写sql语句String sql = "select * from info where username=? and password=?";//2.调用JDBCTemplate对象的查询方法User user = jdbcTemplate.queryForObject(sql //sql语句, new BeanPropertyRowMapper<User>(User.class) //RowMapper接口实现类,将数据自动封装成指定对象, loginUser.getUsername() //sql参数, loginUser.getPassword()); // sql参数return user;} catch (Exception e) {e.printStackTrace();//以后会将异常记录到日志文件中return null;}}/*** 修改用户自我介绍** @param updateUser* @return*/public User update(User updateUser) {//1.编写sql语句String sql = "update info set introduce = ? where id = ? ";//2.调用JDBCTemplate对象的方法jdbcTemplate.update(sql,updateUser.getIntroduce(),updateUser.getId());//3.再次查询return jdbcTemplate.queryForObject("select * from info where id = ?" //sql语句, new BeanPropertyRowMapper<User>(User.class) //RowMapper接口实现类,将数据自动封装成指定对象, updateUser.getId()); // sql参数}
}
1.2.5 domain层

User.java

/*** 用户实体类*/
public class User implements Serializable {private int id;private String username;private String password;private String introduce;public int getId() {return id;}public void setId(int 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;}public String getIntroduce() {return introduce;}public void setIntroduce(String introduce) {this.introduce = introduce;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", introduce='" + introduce + '\'' +'}';}
}
1.2.6 util层

JDBCUtils.java

/*** JDBC工具类,使用Druid连接池*/
public class JDBCUtils {private static DataSource ds;static {try {//1.加载配置文件Properties prop = new Properties();InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");prop.load(is);//2.初始化数据库连接池对象ds = DruidDataSourceFactory.createDataSource(prop);} catch (Exception e) {e.printStackTrace();}}/*** 获取连接池对象** @return*/public static DataSource getDataSource() {return ds;}/*** 获取数据库连接对象** @return*/public static Connection getConnection() throws SQLException {return ds.getConnection();}
}
1.2.7 web层

过滤器LoginFilter.java

Servlet资源

LoginServlet.java

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req, resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.设置解码格式req.setCharacterEncoding("utf-8");//2.获取请求体参数username和passwordString username = req.getParameter("username");String password = req.getParameter("password");//3.将username和password封装成User对象User loginuser = new User();loginuser.setUsername(username);loginuser.setPassword(password);//4.调用UserDao的login方法UserDao dao = new UserDao();User user = dao.login(loginuser);//5.判断user是否为nullif (user==null){//登录失败跳转到登录页面req.setAttribute("login_msg","登录失败!用户名或密码错误。");req.getRequestDispatcher("/login.jsp").forward(req,resp);}else {//登录成功,将用户信息存在Session中,跳转index.jspHttpSession session = req.getSession();session.setAttribute("user",user);resp.sendRedirect("/index.jsp");}}
}

UpdateServlet.java

@WebServlet(name = "UpdateServlet", urlPatterns = "/UpdateServlet")
public class UpdateServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//1.设置解码格式request.setCharacterEncoding("utf-8");//2.获取请求体参数username和passwordString id = request.getParameter("id");String introduce = request.getParameter("introduce");//3.将id和introduce封装成User对象User Update_user = new User();Update_user.setId(Integer.parseInt(id));Update_user.setIntroduce(introduce);//4.调用UserDao的update方法UserDao dao = new UserDao();User user = dao.update(Update_user);//5.显示修改后用户的自我介绍request.setAttribute("user", user);request.getRequestDispatcher("/index.jsp").forward(request, response);}
}

1.3 测试

1.用户未登录,直接访问index.jsp:将会跳转到登录界面login.jsp,并给出提示信息


未登录,直接访问LoginServlet、updateSerlvet资源同样如此。

2.当前用户已经登录,即session域中存在user的键值对,再直接访问index.jsp、LoginServlet、updateSerlvet资源就无须执行登录业务逻辑了:

登录成功,此时重开一个新的标签页,直接访问index.jsp:


通过F12查看浏览器控制台,网络抓包,可以看到直接进入了用户主页,不会再访问LoginServlet资源。

二.案例2_敏感词汇过滤

使用上面登录案例,来实现敏感词汇的过滤。用户修改自我介绍的时候,如果包含了《敏感词汇.txt》里面的敏感词汇,则会将词汇替换为 ***

敏感词汇.txt

笨蛋
坏蛋

先来看下效果:


修改自我介绍:


点击修改自我介绍,将会回显用户修改后的自我介绍:


比较简单的例子,旨在能理解明白过滤器进行敏感词汇过滤的逻辑,下面就来实现这个效果。

2.1 需求分析

需求:

  • 1.对【用户登录案例】修改的自我介绍数据进行敏感词汇过滤
  • 2.敏感词汇参考《敏感词汇.txt》
  • 3.如果是敏感词汇,替换为 ***

过滤分析图


难点分析

  1. 对req对象进行增强。使用动态代理,增强获取参数相关方法,对请求参数中敏感词汇进行过滤;
  2. 放行。传递代理对象

代码模式不熟悉的小伙伴,可以先阅读下另一篇的博文:代理模式:动态代理、静态代理.

2.2 代码实现

2.2.1 目录结构

大部分代码与上面登录案例一致。

2.2.2 核心代码

核心代码就是:敏感词汇过滤器SensitiveWordsFilter.java

  • 使用缓冲字符输入流获取 《敏感词汇.txt》的词汇内容
  • 增强方法逻辑中,使用 “***” 替换掉请求参数里面的敏感词汇,并返回替换后的值
/*** 敏感词汇过滤器*/
@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {//敏感词汇集合private List<String> list = new ArrayList<String>();public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {//1.创建代理对象,增强getParameter方法ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//增强getParameter方法//判断是否是getParameter方法if(method.getName().equals("getParameter")){//增强返回值//获取返回值String value = (String) method.invoke(req,args);if(value != null){for (String str : list) {if(value.contains(str)){value = value.replaceAll(str,"***");}}}return  value;}//考虑到可能使用其它获取请求参数的方法,那就都需要进行增强,思路是一样的,这里不展开了。//判断方法名是否是 getParameterMap//判断方法名是否是 getParameterValuereturn method.invoke(req,args);}});//2.放行chain.doFilter(proxy_req, resp);}public void init(FilterConfig config) throws ServletException {try{//1.获取文件真实路径ServletContext servletContext = config.getServletContext();String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");//2.读取文件BufferedReader br = new BufferedReader(new FileReader(realPath));//3.将文件的每一行数据添加到list中String line = null;while((line = br.readLine())!=null){list.add(line);}//释放流br.close();System.out.println(list);}catch (Exception e){e.printStackTrace();}}public void destroy() {}
}

测试与前面演示效果一致,不赘述了。

到这两个过滤器的小案例就完成了,理解为主,当前还可以进行更多过滤器的延伸,相信小伙伴们都可以信手拈来~


【JavaWeb】Filter案例:登录验证、敏感词汇过滤相关推荐

  1. 【Filter过滤器案例】登录验证+敏感词过滤

    登录验证 >>> 思路: >>> 先假设拦截所有资源(Servlet, jsp...均不让访问),判断资源是否与登录有关: >>> 1.与登录相关 ...

  2. Java基于Socket实现聊天、群聊、敏感词汇过滤功能

    首先的话,这个代码主要是我很久以前写的,然后当时还有很多地方没有理解,现在再来看看这份代码,实在是觉得丑陋不堪,想改,但是是真的改都不好改了- 所以,写代码,规范真的很重要. 实现的功能: 用户私聊 ...

  3. 动态代理的分析以及利用动态代理模式进行敏感词汇过滤

    动态代理 增强对象的功能: 设计模式:一些通用的解决固定问题的方式 代理模式 概念: (1). 真实对象:被代理的对象 (2). 代理对象: (3). 代理模式:代理对象代理真实对象,达到增强真实对象 ...

  4. 优秀博客 --敏感词汇过滤

    2019独角兽企业重金招聘Python工程师标准>>> 敏感词汇过滤 http://www.cnblogs.com/chenssy/p/3751221.html#2966041 树上 ...

  5. 【敏感词汇过滤算法】基于DFA-前缀树的敏感词汇过滤算法(项目实用)

    在敏感词汇过滤这块,不同的算法所造成的性能差异是非常大的,选择一个合适的算法非常重要.因为以前做算法的时候做过类似前缀树的字符串匹配之类的算法,所以一开始就打算用前缀树做的,后面了解了一下DFA的相关 ...

  6. PHP敏感词汇过滤SDK(树形结构遍历命中违禁词)

    先介绍一下匹配敏感词原理吧,因为没有工具,画的很糙,有疑问直接联系我.(绿色箭头代表命中敏感词,灰色:未命中) base 确定有穷自动机(DFA)算法 比如说"可以"是敏感词,那么 ...

  7. Filter - 通过拦截器与动态代理实现敏感词汇过滤

    需求:将敏感词汇.txt文件中的词语过滤为 -> "***" 分析: 首先加载文档,将文档中的词汇纳入集合中备用,方便后期比对使用. 使用Proxy动态代理将request对 ...

  8. python敏感字替换_教学案例_Python处理敏感词汇方法

    社区都会对发布的信息进行检查,并过滤一些非法的敏感词.在python中可以用关键字in来检测内容中是否存在敏感词汇.①检测信息中是否存在非法的敏感词汇,代码如下: ②将待检测信息中的敏感词汇替换为3个 ...

  9. [MVC学习笔记]5.使用Controller来代替Filter完成登录验证(Session校验)

    之前的学习中,在对Session校验完成登录验证时,通常使用Filter来处理,方法类似与前文的错误日志过滤,即新建Filter类继承ActionFilterAttribute类,重写OnAction ...

  10. Filter进行登录验证时循环重定向的解决方法

    Filter也称之为过滤器,它是Servlet2.3以上新增加的一个功能,其技术是非常强大的.通过Filter技术可以对WEB服务器的文件进行拦截过滤,从而实现一些特殊的功能.在JSP开发应用中也是必 ...

最新文章

  1. VS 2019要来了,是时候了解一下C# 8.0新功能
  2. 【C 语言】结构体 ( 指针运算与指针内存操作 | 结构体成员偏移量计算 )
  3. python爬虫qq音乐教学视频_爬取QQ音乐(讲解爬虫思路)
  4. ThreadLocal 是什么?有哪些使用场景?——Spring系列学习笔记
  5. war部署到tomcat
  6. 前端开发中游览器的兼容问题总结
  7. 使用C语言--编写人机猜数游戏
  8. mysql口令更换周期_MySQL密码过期策略介绍
  9. 请简述一下RS485通讯连接方式及其应用?
  10. 关于EMS,邮政快递包裹,邮政标准快递,邮政小包,EMS经济快递
  11. 百度统计:页面代码安装状态:代码未生效
  12. 华为HCNA实验操作之常用操作命令32-40
  13. 苹果支付返回html,苹果应用内支付,服务器端的实现
  14. 关于TKK失败问题(亲测有用 超详细)
  15. 小米2023届秋招校招内推
  16. [转]金属加工工艺基础知识
  17. HBase-11-HBase Coprocessor HBase协处理器
  18. 【摘录】Ubuntu 10.10编译Android froyo可能需要注意的几个地方
  19. 在竞争激烈的情况下,ReentrantLock与CAS的性能比较
  20. 汇编学习实战修改win32扫雷

热门文章

  1. R语言数据接口(下载、读取、写入)
  2. 大数据生态与Spark简介
  3. 为什么图片保存类型360 se html document,360安全浏览器为什么图片不显示保存
  4. 在线.class文件转换.java_支持200+文件格式的免费在线转换工具
  5. 搜索文件夹中word文档中的关键字
  6. DDoS攻击的工具介绍
  7. 射频识别技术漫谈(26)——Felica的文件系统
  8. 多文档文本编辑器(Qt)
  9. 最简单的电脑上截长图的方法
  10. Go语言实战-golang操作MySQL