Session会话
什么是Session会话
- Cookie保存在客户端;Session保存在服务器
如何创建 Session 和获取(id 号,是否为新)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Session</title>
<base href="http://localhost:8080/cookie/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" width="500" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="sessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li>
<li><a href="sessionServlet?action=setAttribute" target="target">Session域数据的存储</a></li>
<li><a href="sessionServlet?action=getAttribute" target="target">Session域数据的获取</a></li>
<li>Session的存活</li>
<li>
<ul>
<li><a href="sessionServlet?action=defaultLife" target="target">Session的默认超时及配置</a></li>
<li><a href="sessionServlet?action=life3" target="target">Session3秒超时销毁</a></li>
<li><a href="sessionServlet?action=deleteNow" target="target">Session马上销毁</a></li>
</ul>
</li>
<li><a href="" target="target">浏览器和Session绑定的原理</a></li>
</ul>
</div>
</body>
</html>
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionServlet extends BaseServlet{
protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建和获取session会话对象
HttpSession session = req.getSession();
// 判断当前session会话,是否是新创建出来的
boolean isNew = session.isNew();
// 获取session会话的唯一标识id
String id = session.getId();
resp.getWriter().write("得到的session的id是" + id + "<br>");
resp.getWriter().write("这个session是否是新创建出来的" + isNew + "<br>");
}
}
Session 域数据的存取
protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().setAttribute("key1", "value1");
resp.getWriter().write("已经往 Session 中保存了数据");
}
protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object attribute = req.getSession().getAttribute("key1");
resp.getWriter().write("从 Session 中获取出 key1 的数据是:" + attribute);
}
Session 生命周期控制
protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 先获取 Session 对象
HttpSession session = req.getSession();
// 设置当前 Session3 秒后超时
session.setMaxInactiveInterval(3);
resp.getWriter().write("当前 Session 已经设置为 3 秒后超时");
}
protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 先获取 Session 对象
HttpSession session = req.getSession();
// 让 Session 会话马上超时
session.invalidate();
resp.getWriter().write("Session 已经设置为超时(无效)");
}
浏览器和 Session 之间关联的技术内幕
- 这也解决了一个问题,为什么明明session还没有超时,而关闭了浏览器以后,它就超时了,再也找不到了;因为它创建的cookie存活时间是session,浏览器一关就不在了,那之后就会创建一个新的session
Filter 过滤器
什么是过滤器
Filter 的初体验
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>a.jsp</title>
</head>
<body>
<%
Object username = session.getAttribute("username");
if (username == null) {
request.getRequestDispatcher("/login.jsp").forward(request, response);
return;
}
%>
我是a.jsp文件
</body>
</html>
- 但这张做法显然是有个问题的,它有局限性,只能在jsp文件(可以写java代码)中应用,那如果是html文件呢?
package com.atguigu.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class AdminFilter implements Filter {
/**
* doFilter方法,专门用来拦截请求,就可以做权限检查了
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
Object username = session.getAttribute("username");
if (username == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest, servletResponse);
} else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Filter.super.init(filterConfig);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
<?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">
<!-- Filter标签用于配置一个Filter过滤器 -->
<filter>
<filter-name>AdminFilter</filter-name>
<filter-class>com.atguigu.filter.AdminFilter</filter-class>
</filter>
<!-- filter-mapping配置filter过滤器的拦截路径-->
<filter-mapping>
<!-- filter-name表示当前的拦截路径给哪个filter使用 -->
<filter-name>AdminFilter</filter-name>
<!-- url-pattern 配置拦截路径
/ 表示请求地址为: http://ip:port/工程路径 映射到 IDEA 的 web目录
/admin/* 表示 请求地址为: http://ip:port/工程路径/admin/*
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
</web-app>
完整的用户登录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
这是登陆界面。login.jsp页面
<form action="http://localhost:8080/filter/loginServlet" method="get">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
<input type="submit" value="">
</form>
</body>
</html>
package com.com.atguigu.servlet;
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 LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=UTF-8"); // 解决响应乱码
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("wzg168".equals(username) && "123456".equals(password)) {
req.getSession().setAttribute("username", username);
resp.getWriter().write("登陆成功!");
} else {
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
- 还没有登录的时候访问admin下面的文件就会直接跳转到登陆界面
- 如果输入错误的账号密码会重新返回到登陆界面
- 如果登陆成功以后就会进入loginServlet,然后再访问admin下面的a.jsp,session中取出来的数据就有值了,也就是非空,就会执行
filterChain.doFilter(servletRequest, servletResponse);
,让程序继续往下走,刚才我们访问的是a.jsp,因此,下一步就进入了a.jsp;如果没有这句代码,就算登陆成功以后,也无法访问用户的目标资源,进入admin/a.jsp这个页面显示的是一片空白
Filter 的生命周期
package com.atguigu.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class AdminFilter implements Filter {
public AdminFilter() {
System.out.println("1.Filter的构造器方法-AdminFilter()");
}
/**
* doFilter方法,专门用来拦截请求,就可以做权限检查了
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("3.Filter的doFilter()过滤方法");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
Object username = session.getAttribute("username");
if (username == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest, servletResponse);
} else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Filter.super.init(filterConfig);
System.out.println("2.Filter的初始化init()方法");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("4.Filter的destroy()销毁方法");
}
}
FilterConfig 类
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化");
// 1、获取 Filter 的名称 filter-name 的内容
System.out.println("filter-name 的值是:" + filterConfig.getFilterName());
// 2、获取在 web.xml 中配置的 init-param 初始化参数
System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));
System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));
// 3、获取 ServletContext 对象
System.out.println(filterConfig.getServletContext());
}
<!--filter 标签用于配置一个 Filter 过滤器-->
<filter>
<!--给 filter 起一个别名-->
<filter-name>AdminFilter</filter-name>
<!--配置 filter 的全类名-->
<filter-class>com.atguigu.filter.AdminFilter</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost3306/test</param-value>
</init-param>
</filter>
FilterChain 过滤器链
Filter 的拦截路径
- 后缀名匹配不能以斜杠打头
JSON
什么是 JSON
JSON 在 JavaScript 中的使用
json 的定义
var jsonObj = {
"key1":12,
"key2":"abc",
"key3":true,
"key4":[11,"arr",false],
"key5":{
"key5_1" : 551,
"key5_2" : "key5_2_value"
},
"key6":[{
"key6_1_1":6611,
"key6_1_2":"key6_1_2_value"
},{
"key6_2_1":6621,
"key6_2_2":"key6_2_2_value"
}]
};
json 的访问
alert(typeof(jsonObj));// object json 就是一个对象
alert(jsonObj.key1); //12
alert(jsonObj.key2); // abc
alert(jsonObj.key3); // true
alert(jsonObj.key4);// 得到数组[11,"arr",false]
// json 中 数组值的遍历
for(var i = 0; i < jsonObj.key4.length; i++) {
alert(jsonObj.key4[i]);
}
alert(jsonObj.key5.key5_1);//551
alert(jsonObj.key5.key5_2);//key5_2_value
alert( jsonObj.key6 );// 得到 json 数组
// 取出来每一个元素都是 json 对象
var jsonItem = jsonObj.key6[0];
// alert( jsonItem.key6_1_1 ); //6611
alert( jsonItem.key6_1_2 ); //key6_1_2_value
json 的两个常用方法
// 把 json 对象转换成为 json 字符串
var jsonObjString = JSON.stringify(jsonObj); // 特别像 Java 中对象的 toString
alert(jsonObjString)
// 把 json 字符串。转换成为 json 对象
var jsonObj2 = JSON.parse(jsonObjString);
alert(jsonObj2.key1);// 12
alert(jsonObj2.key2);// abc
JSON 在 java 中的使用
- JSON在java中使用需要先导JSON的jar包,然后 add as library
javaBean 和 json 的互转
- 导入这两个包后才可以
@Test
@Test
public void test1(){
Person person = new Person(1,"国哥好帅!");
// 创建 Gson 对象实例
Gson gson = new Gson();
// toJson 方法可以把 java 对象转换成为 json 字符串
String personJsonString = gson.toJson(person); System.out.println(personJsonString);
// fromJson 把 json 字符串转换回 Java 对象
// 第一个参数是 json 字符串
// 第二个参数是转换回去的 Java 对象类型
Person person1 = gson.fromJson(personJsonString, Person.class);
System.out.println(person1);
}
- 第一行是json字符串(花括号里面键值对之间用,分隔,键值对中键有“”包围
- 第二行是一个Java对象类型
List 和 json 的互转
@Test
public void test2() {
List<Person> personList = new ArrayList<>();
personList.add(new Person(1, "国哥"));
personList.add(new Person(2, "康师傅"));
Gson gson = new Gson();
// 把 List 转换为 json 字符串
String personListJsonString = gson.toJson(personList);
System.out.println(personListJsonString);
List<Person> list = gson.fromJson(personListJsonString, new PersonListType().getType());
System.out.println(list);
Person person = list.get(0);
System.out.println(person);
}
- 第一行,转化成了(由中括号[]包起来的是数组)一个数组,里面每一个元素都是json
map 和 json 的互转
上同,Class
是给javabean用的,如果是转回集合,必须用的是Type
这个Type一定要先创建一个类去继承官方给的TypeToken
- 但在这里,由json转回list和map时每次都要写一个类去继承TypeToken,会造成很多文件,因此,我们可以写成 匿名类 的形式,如下:
@Test
public void test3(){
Map<Integer,Person> personMap = new HashMap<>();
personMap.put(1, new Person(1, "国哥好帅"));
personMap.put(2, new Person(2, "康师傅也好帅"));
Gson gson = new Gson();
// 把 map 集合转换成为 json 字符串
String personMapJsonString = gson.toJson(personMap);
System.out.println(personMapJsonString);
// Map<Integer,Person> personMap2 = gson.fromJson(personMapJsonString, new PersonMapType().getType());
Map<Integer,Person> personMap2 = gson.fromJson(personMapJsonString, new TypeToken<HashMap<Integer,Person>>(){}.getType());
System.out.println(personMap2);
Person p = personMap2.get(1);
System.out.println(p);
}