会话技术
什么是会话技术?
所谓的会话就是一次会话中包含多次请求和响应;
一次会话就是浏览器第一次给服务器资源发送请求然后建立会话知道有一方断开为止
有什么功能?;可以共享数据
方式就分为了两种:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie
Cookie的概念就是将数据保存到客户端
可以在Servlet中创建一个Cookie对象;然后绑定数据
Cookie cookie = new Cookie("msg", "hello");
通过response对象发送cookie对象
response.addCookie(cookie); //发送cookie对象
可以通过request对象获取Cookie对象
Cookie[] cookies = request.getCookies(); //获取到的是一个Cookie数组
if (cookies != null) { //对数组进行遍历
for (Cookie c :
cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name + ":" + value);
}
}
关于Cookie的细节
- Cookie可以创建多个Cookie对象;使用response调用多次addCookie方法发送cookie即可
- cookie在默认情况下当浏览器关闭后Cookie数据就会被销毁;但是可以通过设置使其持久化储存
默认的参数为负数;零代表删除cookie信息
cookie.setMaxAge(30); //30秒后删除cookie文件
- Tomcat8之后cookie支持中文数据;但是有些特殊符号还是不支持的;建议是使用URL编码来存储
String string = "hello hi";
String encode = URLEncoder.encode(string, "utf-8"); //使用URL编码
Cookie cookie = new Cookie("msg", encode);
- 假如下tomcat服务器中部署了多个web项目;那么默认情况下cookie是不能共享的;但是可以通过设置使其共享
cookie.setPath("/");
Cookie的特点和作用
特点
- cookie存储数据在客户端浏览器中;
- 浏览器对于单个cookie的大小限制为4kb;对同一个域名下的总cookie数量限制为20个
作用
- 一般用于存储少量的不敏感数据
- 在不登录的情况下可以完成服务器对客户端的身份识别
案例
访问一个Servlet;如果是第一次访问就提示:欢迎你首次访问;如果不是一次登录则显示上一次的访问时间
代码分析:
package cookie; //创建的一个包
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/cookieTest")
public class cookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8"); //设置编码
Cookie[] cookies = request.getCookies(); //获取所有的cookie
boolean flag = false; //创建一个布尔值来判断是否第一次
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : //遍历所有cookie
cookies) {
String name = cookie.getName();
if (name.equals("lastTime")) { //如果有一个名叫lastTime的cookie的话
flag = true;
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = simpleDateFormat.format(date);
format = URLEncoder.encode(format, "utf-8"); //使用URL编码
cookie.setValue(format); //存放时间
//设置存活时间
cookie.setMaxAge(60 * 60 * 24 * 30); //一个月
response.addCookie(cookie); //重新添加cookie
String value = cookie.getValue();
value = URLDecoder.decode(value, "utf-8"); //解码
response.getWriter().write("<h1>欢迎回来,你上次访问时间为:" + value + "</h1>");
break;
}
}
}
if (cookies == null || cookies.length == 0 || flag == false) {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = simpleDateFormat.format(date);
format = URLEncoder.encode(format, "utf-8");
Cookie cookie = new Cookie("lastTime", format);
cookie.setValue(format);
cookie.setMaxAge(60 * 60 * 24 * 30); //一个月
response.addCookie(cookie);
response.getWriter().write("<h1>欢迎你首次访问!</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Session
Session的概念就是服务器会话技术;在一次会话的多次请求间共享数据;将数据保存在是服务器的对象中
HttpSession
获取HttpSession对象:
HttpSession session = request.getSession();
使用HttpSession对象:
session.setAttribute("msg","hello"); //存储数据
session.removeAttribute("msg"); //移除数据
Session的实现原理是依赖于Cookie的
关于Session的细节
- 当客户端关闭后;服务器不关闭;两次获取session默认情况下不是同一个;如果需要相同则可以进行如下操作
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60); //设置最大存活时间
response.addCookie(c);
- 当客户端不关闭;服务器关闭;两次获取session也不是同一个;但是要确保数据的不丢失Tomcat会自动进行Seeion的钝化和活化的操作;所谓的钝化就是服务器正常关闭后将session对象序列化到硬盘上;活化就是服务器启动后将session文件为内存中的session对象;而idea是不具有该操作的
- session在服务器关闭的时候就会被销毁;通过session对象调用invalidate()也被销毁;默认失效时间是30分钟
Session的特点
- session可以用与存储一次会话的多次请求的数据;存在服务器端
- session可以存储任意类型;任意大小的数据
Session和Cookie的区别
- session是将数据存储在服务器端的;而cookie是存在客户端的
- session没有数据大小的限制;而cookie有限制(4kb)
- session数据安全;cookie相对于不安全
验证码案例部分代码:
package servlet;
import dao.UserDao; //操作数据库的类
import domain.User; //封装用户名和密码的类
import org.apache.commons.beanutils.BeanUtils; //用于简易将数据封装成对象的工具类
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); //设置编码
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
HttpSession session = request.getSession(); //创建一个session对象
String code = (String) session.getAttribute("checkCode"); //获取存在服务器的数据
session.removeAttribute("checkCode"); //为了下一次的验证码不重复;删除验证码
if (code != null && code.equalsIgnoreCase(checkCode)) { //忽略大小写比较,防止空指针
Map<String, String[]> parameterMap = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
UserDao userDao = new UserDao();
User login = userDao.login(user);
if (login.getUsername().equals(username) && login.getPassword().equals(password)) {
session.setAttribute("user", username);
response.sendRedirect(request.getContextPath() + "/success.jsp"); //重定向;需要虚拟目录
} else {
request.setAttribute("login_error", "用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response); //服务器转发
}
} else {
request.setAttribute("cc_error", "验证码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response); //服务器转发
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
JSP
JSP:Java Server Pages
;java服务器端页面
可以理解为一个特殊的页面;它既可以定义html标签也可以定义Java代码;就是用于简化书写
其实JSP本质上就是一个Servlet
JSP定义Java代码的方式称为脚本;有三种
-
<% 代码 %>
:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。 -
<%! 代码 %>
:定义的java代码,在jsp转换后的java类的成员位置。 -
<%= 代码 %>
:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
JSP内置对象:
在JSP页面中不需要获取创建可以直接使用的对象;一共有9个
先介绍三个:
request
response
out
:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
response.getWriter()和out.write()的区别:
- 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
- response.getWriter()数据输出永远在out.write()之前