目标
- 过滤器实现后台管理的权限控制
- 监听器 - 实现统计当前在线人数
- Ajax -1 原生JS实现
1.回顾
- 会话-session - 客户端浏览器与服务端的一次连接[多次的请求与响应]过程
- 会话跟踪 - 会话的过程中可以保持数据共享的状态这样一种技术 - 解决HTTP协议的无状态性
- Cookie
- 创建Cookie new Cookie(name,value); --key-value[字符串]
- 设置cookie存活期 setMaxAge(秒) - 0立即删除cookie, -1 [关闭浏览器时删除]
- 发送至浏览器 response.addCookie(ck);
- 在页面读取请求对象中的cookie 数据Cookie[] cks= request.getCookies()-- EL表达式 {{cookie.name.value}
- HttpSession - getId() ,创建时间,isNew(),非活动时间间隔setInactiveInterval(), invalidate()
- 会话如何产生: request.getSession(),request.getSession(true|false)
- 会话失效有三种方式: 会话对象.invalidate(); 非活动时间超时; 关闭浏览器
2.过滤器
- Java Web 服务端三大组件
- Servlet 、过滤器Filter、监听器Listener
- web.xml 进行配置运行
- @WebServlet
- @WebFilter
- @WebListener
2-1 过滤器简介
- 驻留在服务端,针对客户端与服务端之前的请求与响应信息进行过滤
- 主要两个作用:
设置请求的字符集编码
权限控制—必须登录的用户才能访问后台
- 过滤器入门示例
step1: 创建过滤器类 MyFilter实现接口javax.servlet.Filter;
step2: 重写接口中的方法
public class MyFilter implements Filter{
//执行过滤处理
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
System.out.println("1.请求到达MyFilter....");
}
}
step3: 配置过滤器
web.xml:
<!-- Filter -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.woniu.web.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/hello</url-pattern>
</filter-mapping>
-----------------------------------------
<!-- Filter -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.woniu.web.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<!-- /hello 斜杠必须加 *.jsp *.html *.css *.* 则不能加/ -->
</filter-mapping>
step4:请求目标资源servlet,请求会被过滤器拦截
当然,同Servlet一样,我们也可以使用注解来配置Filter
@WebFilter("/*")
public class MyFilter implements Filter{
}
2-2 过滤器应用-1
- 将请求的中的字符集编码进行统一处理
- 这样就不需要在每个 Servlet中处理请求字符集编码
package com.woniu.mall.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
/**
* 所有请求执行字符集编码过滤
*/
@WebFilter(urlPatterns = "/*",initParams = @WebInitParam(name = "charset",value = "UTF-8"))
public class EncodingFilter implements Filter {
private FilterConfig filterConfig;
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
/**
* 执行过滤处理
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//System.out.println("EncodingFilter...");
//获取初始化配置参数charset
String charSet = filterConfig.getInitParameter("charset");
request.setCharacterEncoding(charSet);
// 放行
chain.doFilter(request, response);
}
}
2-3 过滤器应用-2
- 对项目后台进行权限控制 - 没有登录的情况下,对后台管理的任何操作都会执行过滤处理,将请求不做放行
实现步骤:
step1: 添加过滤器,将所有后台管理的请求路径设置为过滤器执行的路径模式
/**
* 过滤
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//获取当前请求相关联的session对象
HttpServletRequest req = (HttpServletRequest)request; //类型转换
HttpSession ses = req.getSession();
//获取session作用域中登录的管理员
Admin loginAdmin = (Admin)ses.getAttribute("loginAdmin");
if(loginAdmin == null) {
request.setAttribute("msg", "对不起,没有登录的管理员无权执行该操作!");
request.getRequestDispatcher("/manage/login.jsp").forward(request, response);
}else {
//放行
chain.doFilter(request, response);
}
}
step2:解决例外情况
/**
* 过滤
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request; //类型转换
//例外情况 - 管理员登录
//获取请求的uri
String uri= req.getRequestURI();
//String url = req.getRequestURL().toString();
System.out.println("uri:"+uri);
//System.out.println("url:"+url);
//如果是登录的请求,则放行
if(uri.endsWith("/manage/admin") && req.getParameter("opr").equals("login")) {
System.out.println("当前请求为登录的请求,将被放行....");
chain.doFilter(request, response);
return;
}
HttpSession ses = req.getSession();
//获取session作用域中登录的管理员
Admin loginAdmin = (Admin)ses.getAttribute("loginAdmin");
if(loginAdmin == null) {
request.setAttribute("msg", "对不起,没有登录的管理员无权执行该操作!");
request.getRequestDispatcher("/manage/login.jsp").forward(request, response);
}else {
//放行
chain.doFilter(request, response);
}
}
step3:进入登录页面直接转发
//进入登录页面
if(uri.endsWith("/manage/login.jsp") || uri.endsWith("/manage") ||
uri.endsWith("/manage/")) {
request.getRequestDispatcher("/manage/login.jsp").forward(request, response);
return;
}
3.监听器
- Web服务端三大组件之一
- 监视web服务端某一个事件发生,自动的调用处理方法
- 监听器根据所监听事件进行分类:
- 监听作用域 ,三个
- 监听ServletContext,HttpSession,HttpServletRequest对象的生命周期的监听器
- 监听器入门示例:
- 监听ServletContext对象创建与销毁
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("MyListener监听器初始化....");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("MyListener监听执行Destroyed....");
}
}
web.xml:
<listener>
<listener-class>com.woniu.mall.listener.MyListener</listener-class>
</listener>
也可以使用注解替代xml配置:
@WebListener
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("MyListener监听器初始化....");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("MyListener监听执行Destroyed....");
}
}
- 监听器应用
- 统计当前系统中的在线人数 - 当前系统中的会话数量
(1) 定义监听器- HttpSessionListener
/**
* 用于统计在线人数的监听器
*
*/
@WebListener
public class OnlineNumListener implements HttpSessionListener {
/**
* 当有客户端与服务器连接时,创建一个会话时,执行此方法
*/
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
//获取全局作用域中的人数
Integer num = (Integer)ctx.getAttribute("num");
if(num == null) {
//第一个会话
num = 1;
}else {
num++;
}
//将num存入全局作用域
ctx.setAttribute("num", num);
}
/**
* 会话失效-销毁时 invalidate(), 超时,关闭浏览器
*/
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println("会话销毁.....................");
//获取全局作用域中的人数
Integer num = (Integer)ctx.getAttribute("num");
if(num>0) {
num--;
}
//将num存入全局作用域
ctx.setAttribute("num", num);
}
}
(2) 在页面中访问在线人数
当前在线人数:<span style="color:red;">{{applicationScope.num}</span>
4.Ajax异步请求
4-1 Ajax概述
Ajax - Asynchornous javascript and xml [JSON]
|-异步的js和xml
[无刷新页面技术,局部更新页面技术]
不是一种编程语言,而是多种技术的综合而成
Google 谷歌公司推广 [2004~2005] 提升用户体验
同步(Synchronous)和异步(Asynchronous)的概念
|-同步请求 代表着你必须等待这次请求结束并且刷新整个界面之后,你才能进行下一步操作
异步请求则可以不刷新界面,它会立即返回,进行局部更新,界面也可以继续执行其它的操作
可以说,AJax改变了Web开发的格局
4-2 原生Ajax示例
- 实现根据code异步加载对应的省份与城市数据
(1)创建 XMLHttpRequest 对象的语法: -- ajax的核心对象
variable=new XMLHttpRequest();
(2) 建立与服务器连接
xmlhttp.open("GET","test1.txt",true);
method:请求的类型;GET 或 POST
•url:文件在服务器上的位置
•async:true(异步)或 false(同步)
(3) 设置回调
req.onreadystatechange = function(){}
(4) 发送请求
req.send(null)
(5) 在回调函数中接受响应的文本内容
req.responseText属性
<script>
//步骤1: 创建XMLHttpRequest Javascript对象 --也称为ajax的引擎对象
//所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
let req = new XMLHttpRequest();
function getResult(){
if(req){ //创建XHR对象成功
//步骤2: 与服务建立连接
let url = "load?code="+document.getElementById("code").value;
req.open("GET",url,true);
//步骤3:设置回调CallBack -- 当异步请求执行后,收到了服务器响应的数据,此时调用页面的函数
req.onreadystatechange = loadData; //只写函数名称
//步骤4: 发送ajax异步请求
req.send(null);
}
}
//回调
function loadData(){
//alert("ajax引擎对象的状态码:"+req.readyState);
if(req.readyState==4 && req.status==200){ //服务器处理完成,并没有发生错误
//接收服务端的异步响应的消息内容
let result = req.responseText;
let arr = result.split(",");
document.getElementById("province").value=arr[0];
document.getElementById("city").value=arr[1];
}
}
</script>
</head>
<body>
邮编:<input type="text" name="code" id="code" onblur="getResult()" /><br/>
省份:<input type="text" name="province" id="province"/><br/>
城市:<input type="text" name="city" id="city"/>
<marquee>我是滚动的文本</marquee>
</body>
LoadServlet:
@WebServlet("/load")
public class LoadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求到达LoadServlet....");
String code = request.getParameter("code");
//查询数据库
String province = "";
String city = "";
if(code.equals("430000")) {
province="湖北省";
city="武汉市";
}else if(code.equals("420000")) {
province="湖南省";
city="长沙市";
}else {
province="其他";
city="其他";
}
//输出到客户端 注:异步的请求不能执行服务器跳转 [无效]
//request.getRequestDispatcher("/index.jsp").forward(request, response);
//输出响应的消息内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println(province+","+city);
out.flush();
out.close();
}
}