系列文章
JavaWeb 开发 01 —— 基本概念、Web服务器、HTTP、Maven
JavaWeb 开发 02 —— ServletContext、读取资源、下载文件、重定向和请求转发
JavaWeb 开发 03 —— Cookie 和 Session
JavaWeb 开发 04 —— JSP(原理、语法、指令、内置对象、JSP标签、JSTP标签)、JavaBean、MVC
10、过滤器
过滤器用于过滤网站的数据,处理中文乱码、登录验证…
Filter 实现中文乱码解决
Filter开发步骤:
-
导包
复制下面的,也可以去仓库找 https://mvnrepository.com/
<!-- Servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- JSP依赖 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- JSTL表达式依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- standard标签库 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- 连接数据库 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
-
新建一个类,实现过滤器接口。(注意是Servlet包下的Filter接口)
-
编写代码,重写方法。这里通过过滤器解决中文乱码问题!当我们访问Servlet时,如果没有处理(设置编码为UTF-8)就会出现乱码,但每一个Servlet都处理一次比较麻烦,所以可以在过滤器中预先处理,使每一个请求Servlet前,先经过过滤器处理好乱码。
CharacterEncodingFilter.java
package com.zcy.filter;
import javax.servlet.*;
import java.io.IOException;
//过滤器可以有多个
public class CharacterEncodingFilter implements Filter {
//初始化:Tomcat服务器启动时调用
@Override
public void init(FilterConfig filterConfig) throws ServletException{
System.out.println("过滤器初始化!");
}
@Override
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("-------过滤器执行前--------");
//这行代码是让过滤通过,并传给下一个过滤器(如果有的话),如果没写,程序运行到这就结束了。
chain.doFilter(request, response);
System.out.println("-------过滤器执行后--------");
}
//销毁:Tomcat服务器关闭时调用
@Override
public void destroy() {
System.out.println("过滤器销毁!");
}
}
FilterServlet.java
public class FilterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().print("这一段如果没有过滤,将会是乱码");
}
}
- 编写web.xml(也可以用注解的方式)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>FilterServlet</servlet-name>
<servlet-class>com.zcy.servlet.FilterServlet</servlet-class>
</servlet>
<!-- 同一个Servlet映射两个位置 -->
<servlet-mapping>
<servlet-name>FilterServlet</servlet-name>
<url-pattern>/filter</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>FilterServlet</servlet-name>
<url-pattern>/servlet/filter</url-pattern>
</servlet-mapping>
<!-- 过滤器只过滤/servlet包下的Servlet -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.zcy.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
没有过滤:
过滤后:
Filter 实现权限拦截
描述:只有用户成功登录后,才能进入主页。登录过一次,可以直接将主页URL放入浏览器打开。一旦注销,用户再输入主页URL是无法进入主页的。
-
用户登录之后,向Session中放入用户数据
-
跳转到主页的时候过滤器先判断用户是否已经登录,若没有登录则跳转到错误页面,若已经登录,则跳转到主页。
注意:login.jsp是在webapp的login目录下;
error.jsp是在webapp的error目录下;
success.jsp是在webapp的sys目录下;
LoginServlet2.java和LogoutServlet2.java是在java的com.zcy.servlet目录下; LoginFilter.java是在java的com.zcy.filter目录下。
login.jsp 登录界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录界面</title> </head> <body> <h1>登录界面</h1> <form action="/myWeb/login" method="post"> <input type="text" name="username"/><input type="submit" value="提交"/> </form> </body> </html>
success.jsp 成功登录后的主页
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登录成功!</h1> <h2>这是主页</h2> <h3><a href="/myWeb/logout">注销,并返回登录界面</a><h3> </body> </html>
error.jsp 登录失败的错误页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登录失败</h1> <h2>权限不够或者密码错误...</h2> <h3><a href="/myWeb/login/login.jsp">返回登录界面</a></h3> </body> </html>
LoginServlet2.java
package com.zcy.servlet; import com.zcy.util.Constant; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginServlet2 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String userName = req.getParameter("username"); if (userName.equals("admin")){ //登录成功,将数据放到Session中,随便放什么,这里放Session ID req.getSession().setAttribute(Constant.USER_SESSION, req.getSession().getId()); //成功则重定向到成功页面,这里因为将数据放到session中,所以其他页面也能用该数据 resp.sendRedirect("/myWeb/sys/success.jsp"); } else resp.sendRedirect("/myWeb/error/error.jsp");//失败则跳转到失败页面 } }
LogoutServlet2.java
package com.zcy.servlet; import com.zcy.util.Constant; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LogoutServlet2 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //移除Session中的数据,也可以直接手动销毁session(但后面session再自动创建会浪费资源) //只有已经登录了才能注销 if (req.getSession().getAttribute(Constant.USER_SESSION) != null) req.getSession().removeAttribute(Constant.USER_SESSION); //注销后,最终都会回到登陆界面 resp.sendRedirect("/myWeb/logi/login.jsp"); } }
LoginFilter.java
package com.zcy.filter; import com.zcy.util.Constant; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginFilter implements Filter { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse resp = (HttpServletResponse)response; if (req.getSession().getAttribute(Constant.USER_SESSION) == null) resp.sendRedirect("/myWeb/error/error.jsp"); chain.doFilter(request, response); } }
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>LoginServlet2</servlet-name> <servlet-class>com.zcy.servlet.LoginServlet2</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet2</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> <servlet> <servlet-name>LogoutServlet2</servlet-name> <servlet-class>com.zcy.servlet.LogoutServlet2</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet2</servlet-name> <url-pattern>/logout</url-pattern> </servlet-mapping> <!-- 过滤:访问sys目录下的所有文件都需要先访问LoginFilter.java --> <filter> <filter-name>LoginFilter</filter-name> <filter-class>com.zcy.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/sys/*</url-pattern> </filter-mapping> </web-app>
结果:
11、监听器
监听器有很多,它们使用方法都相同。这里举个例子,统计网站在线人数。
OnlineCountListener.java
package com.zcy.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 通过监听Session,统计网站在线人数
* 一个session代表一个用户,tomcat启动项目时默认会有三个session,重新发布tomcat后清零。
* session销毁两种方式:1. 手动:se.getSession().invalidate();
* 2.自动 去web.xml配置session-config和session-timeout
*/
public class OnlineCountListener implements HttpSessionListener {
//创建一个session时会调用该方法,创建session即一个浏览器打开网页。一个浏览器只能代表一个session
@Override
public void sessionCreated(HttpSessionEvent se) {
//ServletContext代表Servlet上下文,也就是JSP中的application对象,作用域是整个服务器
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("onLineCount");
//之前没人则人数为1(当前一个用户),有人则人数加一
if (onlineCount == null)
onlineCount = new Integer(1);
else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
//更新人数
servletContext.setAttribute("onLineCount", onlineCount);
}
//销毁一个session时会调用该方法,
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//ServletContext代表Servlet上下文,也就是JSP中的application对象,作用域是整个服务器
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("onLineCount");
if (onlineCount == null)
onlineCount = new Integer(0);
else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
//更新人数
servletContext.setAttribute("onLineCount", onlineCount);
}
}
linsten.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>当前在线人数:<%=this.getServletConfig().getServletContext().getAttribute("onLineCount")%></h1>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册监听器 -->
<listener>
<listener-class>com.zcy.listener.OnlineCountListener</listener-class>
</listener>
</web-app>
结果:启动项目后,先重新发布,因为tomcat本身会有一个session。
一个浏览器即便打开多个网页也只算一个用户,因为session是按浏览器创建的。
用IE再进入这个网页,人数显示2,关闭IE后刷新谷歌浏览器,人数保持是2,因为session即便浏览器关闭也不会被销毁。
12、JDBC
详细可看我另一篇博客:数据库 —— Java操作MySQL