HttpSession接口(一)
如果两个Servlet来自于同一个网站、并且为同一个浏览器/用户提供服务,
此时借助于HttpSession对象进行数据共享
开发人员习惯于将HttpSession接口修饰对象称为会话作用域对象
HttpSession与Cookie区别
1)存储位置
Cookie:存放在客户端计算机(浏览器内存/硬盘)
HttpSession:存放在服务端计算机内存
2)数据类型
Cookie对象存储共享数据类型只能是String,
HttpSession对象可以存储任意类型的共享数据Object
3)数据数量
一个Cookie只能存储一个共享数据
HttpSession使用Map集合存储共享数据,所以
可以存储任意数量共享数据
4)参照物
Cookie相当于客户在服务端【会员卡】
HttpSession相当于客户在服务端【私人保险柜】
package com.example.Myservlet.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession session = request.getSession();
//2.将数据添加到用户私人储物柜
session.setAttribute("userName","Jack");
session.setAttribute("password","123456");
session.setAttribute("address","安徽省合肥市");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.example.Myservlet.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession session = request.getSession();
//2.从会话作用域对象得到OneServlet提供的共享数据
String userName = (String)session.getAttribute("userName");
String password = (String)session.getAttribute("password");
String address = (String)session.getAttribute("address");
System.out.println("用户名:"+userName);
System.out.println("密码:"+password);
System.out.println("地址:"+address);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
HttpSession接口(二)
5.getsession()与getsession (false)
- getsession():如果当前用户在服务端已经拥有了自己的私人储物柜.
要求tomcat将这个私人储物柜进行返回
如果当前用户在服务端尚未拥有自己的私人储物柜要求tocmat为当前用户创建一个全新的私人储物柜
2)getsession (false):如果当前用户在服务端已经拥有了自已的私人储物柜.
要求tomcat将这个私人储物柜进行返回
如果当前用户在服务端尚未拥有自己的私人储物柜此时Tomcat将返回null
6. Httpsession销毁时机:
1.用户与Httpsession关联时使用的cookie只能存放在浏览器缓存中.2.在浏览器关闭时,意味着用户与他的Httpsession关系被切断
3.由于Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时并不会导致Tomcat将浏览器关联的Httpsession进行销毁
4.为了解决这个问题,Tomcat为每一个Httpsession对象设置【空闲时间】这个空闲时间默认30分钟,如果当前Httpsession对象空闲时间达到30分钟此时Tomcat认为用户已经放弃了自己的Ettpsession,此时Tomcat就会销毁掉这个Httpsession
手动设置空闲时间
<session-config>
<!--空闲时间1分钟-->
<session-timeout>1</session-timeout>
</session-config>
HttpServletRequest接口实现数据共享
在同一个网站中,如果两个servlet之间通过【请求转发】方式进行调用,
彼此之间共享同一个请求协议包。而一个请求协议包只对应一个请求对象因此servlet之间共享同一个请求对象,此时可以利用这个请求对象在两个servlet之间实现数据共享
在请求对象实现servlet之间数据共享功能时,开发人员将请求对象称为【请求作用域对象】
package com.example.Myservlet.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("userName","楠晗");
request.setAttribute("password","123456");
request.getRequestDispatcher("/two").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.example.Myservlet.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = (String)request.getAttribute("userName");
Object password = request.getAttribute("password");
System.out.println("用户名:"+userName);
System.out.println("密码:" +password);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
监听器接口
监听器接口需要由开发人员亲自实现,Http服务器提供jat包并没有对应的实现类。
接听器接口用于监控【作用域对象生命周期变化时刻】以及【作用域对象共享数据变化时刻】
作用域对象:
在servlet规范中,认为在服务端内存中,在某些条件下
可以为两个servlet提供数据共享方案的对象,被称为作用域对象
ServletContext:全局作用域对象
HttpSession:会话作用域对象
HttpServletRequest:请求作用域对象
监听器接口实现类开发规范:三步
1)根据监听的实际情况,选择对应监听器接口进行实现
2)重写监听器接口声明【监听事件处理方法】
3)在web.xml将监听器接口实现类注册到Http服务器
ServletContextListener接口:
通过这个接口合法的检测全局作用域对象被初始化时刻以及销毁时刻
public void contextInitlized();
public void contextDestroy();
package com.example.Myservlet.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class OneListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("全局作用域对象初始化......");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("全局作用域对象被销毁.....");
}
}
<!--将监听器接口实现类注册到Tomcat-->
<listener>
<listener-class>com.example.Myservlet.listener.OneListener</listener-class>
</listener>
ServletContextAttributeListener接口:
通过这个接口合法的检测全局作用域对象共享数据变化时刻
package com.example.Myservlet.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class TwoListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("新增共享数据");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println("删除共享数据");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println("修改共享数据");
}
}
xml文件注册
<listener>
<listener-class>com.example.Myservlet.listener.TwoListener</listener-class>
</listener>
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("武动乾坤","李洛");
servletContext.setAttribute("大主宰","牧尘");
servletContext.setAttribute("武动乾坤","林动");
servletContext.removeAttribute("武动乾坤");
过滤器接口
Filter接口实现由开发人员负责提供
Filter接口在Http服务器调用资源文件之前,对Http服务器进行拦截
作用:
拦截Http服务器,帮助Http服务器检测当前请求合法性
拦截Http服务器,对当前请求进行增强操作。
实现过滤器
监测请求合法性
package com.example.Myservlet.filter;
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class OneFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.通过拦截请求对象得到请求包参数信息
String age = servletRequest.getParameter("age");
//2.根据年龄,判断合法性
if(Integer.parseInt(age) < 70){
//将拦截请求对象和响应对象交还给Tomcat,由Tomcat继续调用资源文件
filterChain.doFilter(servletRequest,servletResponse);//放行
}else{
//过滤器代替Http服务器拒绝本次请求
servletResponse.setContentType("text/html;charset=utf-8");
PrintWriter out = servletResponse.getWriter();
out.println("<center><font style='color:red;font-size:40px'>拒绝本次访问</center>");
}
}
}
注册
<filter>
<filter-name>oneFilter</filter-name>
<filter-class>com.example.Myservlet.filter.OneFilter</filter-class>
</filter>
<!--通知tomcat调用何种资源文件时需要被当前过滤器拦截-->
<filter-mapping>
<filter-name>oneFilter</filter-name>
<url-pattern>/cat.jpg</url-pattern>
</filter-mapping>
进行增强操作
设置所有servlet的请求对象字符集为utf-8
package com.example.Myservlet.filter;
import javax.servlet.*;
import java.io.IOException;
public class TwoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
}
<filter>
<filter-name>twoFilter</filter-name>
<filter-class>com.example.Myservlet.filter.TwoFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>twoFilter</filter-name>
<url-pattern>/*</url-pattern><!--通知tomcat调用所有资源之前都要调用TwoFilter拦截-->
</filter-mapping>
拦截地址
拦截地址通知tomcat在调用何种资源之前需要调用OneFilter过滤进行拦截
要求Tomcat在调用某一个具体文件之前,来调用OneFilter拦截
<url-pattern>/img/cat.jpg</url-pattern>
要求Tomcat在调用某一个文件夹下所有的资源文件之前,来调用OneFilter拦截
<url-pattern>/img/*</url-pattern>
要求Tomcat在调用任意文件夹下某种资源文件之前,来调用OneFilter拦截
<url-pattern>*.jpg</url-pattern>
要求Tomcat在调用任意文件之前,来调用OneFilter拦截
<url-pattern>/*</url-pattern>
防止用户恶意登录行为
如何防止用户在地址栏输入http://localhost:8080/myWeb/index.html,而避过登录界面?
令牌
package com.example.servlet_05.controller;
import com.example.servlet_05.dao.UserDao;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String userName = request.getParameter("userName");
String password = request.getParameter("password");
UserDao userDao = new UserDao();
int flag = userDao.login(userName, password);
if(flag == 1){
//判定来访用户身份合法后,通过请求对象向Tomcat申请为当前用户申请一个私人储物柜
HttpSession session = request.getSession();
response.sendRedirect("/myWeb/index.html");
}else{
response.sendRedirect("/myWeb/login_error.html");
}
}
}
package com.example.servlet_05.controller;
import com.example.servlet_05.dao.UserDao;
import com.example.servlet_05.entity.Users;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
public class UserFindAllServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//索要当前用户在服务端HttpSession
HttpSession session = request.getSession(false);
if(session == null){
response.sendRedirect("/myWeb/login_error.html");
}else{
UserDao userDao = new UserDao();
List<Users> list = userDao.findAll();
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<table border='2' align='center'>");
out.println("<tr>");
out.println("<td>用户编号</td>");
out.println("<td>用户名</td>");
out.println("<td>密码</td>");
out.println("<td>性别</td>");
out.println("<td>邮箱</td>");
out.println("<td>操作</td>");
out.println("</tr>");
for (Users user : list) {
out.println("<tr>");
out.println("<td>"+user.getUserId()+"</td>");
out.println("<td>"+user.getUserName()+"</td>");
out.println("<td>"+user.getPassword()+"</td>");
out.println("<td>"+user.getSex()+"</td>");
out.println("<td>"+user.getEmail()+"</td>");
out.println("<td><a href='http://localhost:8080/myWeb/user/delete?id="+user.getUserId()+"'>删除</a></td>");
out.println("</tr>");
}
out.println("</table>");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
缺点:每一个动态资源文件都要判断用户的合法性,静态资源文件无法被保护。
防止用户恶意登录行为(二)
package com.example.servlet_05.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.http.HttpRequest;
public class OneFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession(false);
String requestURI = request.getRequestURI();
System.out.println("资源文件:"+requestURI);
boolean flag = requestURI.equals("/myWeb/") || requestURI.indexOf("login") != -1;
if(flag || session != null){
filterChain.doFilter(servletRequest,servletResponse);
}else{
response.sendRedirect("/myWeb/login_error.html");
}
}
}
<filter>
<filter-name>oneFilter</filter-name>
<filter-class>com.example.servlet_05.filter.OneFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>oneFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>