文章目录
- 会话跟踪
-
- cookie
- session
- filter
- listener
- MVC
-
- model
- controller
- 前后端分离
- AJAX
-
- 工作原理
- 属性和方法
- jQuery
- json
会话跟踪
- 常用的会话跟踪技术是cookie和session,保证用户在会话期间的数据管理
cookie
- cookie会在本地记录信息,不安全
- 设置cookie,在业务类中(因为路由先到这,再返回页面)
Cookie cookie = new Cookie("jieguo","true"); response.addCookie(cookie);
- 这个可以在浏览器查看到,属于客户端行为
- 服务端获取客户端携带的cookie,验证并返回页面
<%Cookie[] cookies = request.getCookies();if(cookies != null)for(Cookie c : cookies){ String name = c.getName();//获取Cookie名称if("jieguo".equals(name)){ String value = c.getValue();//获取Cookie的值bool = Boolean.valueOf(value);//将值转为Boolean类型}} %>
- 删除cookie
//1.创建?个name为username的Cookie Cookie cookie = new Cookie("username", "aaa"); //2.设置Cookie的有效时间为0 cookie.setMaxAge(0);//删除cookie的关键 //3.将cookie发送给浏览器,来替换同名Cookie response.addCookie(cookie);
- 注:以上演示都是在服务器,客户端(浏览器)有默认的保存cookie的行为
session
- session的内容会存在服务器,比较安全,但占用空间(session?的信息应该尽量精简)
- 一般登录成功后会在session存储用户名密码等,在同一个浏览器的不同请求都可以获取已登录状态
- 同样可以设置过期时间
HttpSession session = request.getSession(); // 获取Session对象 session.setAttribute("loginTime", new Date()); // 设置Session中的属性 out.println("登录时间为:" +(Date)session.getAttribute("loginTime")); // 获取Session属性// 过期时间 session.setMaxInactiveInterval(longinterval) // 分钟 // 也可以在web.xml设置 <session-config><session-timeout>30</session-timeout> </session-config>
- 设置失效
session.invalidate()
- cookie 一般保存的是
session ID
,通过ID确定session信息后即可保持登录状态、获取相关数据
filter
- 过滤器实际上就是对web资源进?拦截,做?些处理后再交给下?个过滤器或servlet处理
- 例如大部分页面都需要登录后访问,可以添加过滤器验证
// 新建util.FilterTest.java public class FilterTest implements Filter { @Overridepublic void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化filter");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("begin filter");filterChain.doFilter(servletRequest, servletResponse);System.out.println("end filter");}@Overridepublic void destroy() { System.out.println("destroy filter");} }
- web.xml中也要配置
<filter><filter-name>过滤器名称</filter-name><filter-class>过滤器所在的路径</filter-class> </filter> <filter-mapping><filter-name>过滤器名称</filter-name><url-pattern>/*</url-pattern> </filter-mapping>
- 如果有多个过滤器,都需要在xml配置,走完过滤器才会走servlet
- 如果路径表达式使用
/*
,所有请求都会走这个过滤器@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("begin filter");HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;// 限制登录String requestURI = request.getRequestURI();Object username = request.getSession().getAttribute("username");if (requestURI.endsWith("testfilter.jsp") && username==null) { response.sendRedirect("login.jsp");}filterChain.doFilter(servletRequest, servletResponse);System.out.println("end filter"); }
- request和response时的过滤器执行顺序是相反的
- 除了验证登录,还常用在
- .设置编码?式–统?设置编码
- 加密解密(密码的加密和解密)
- 下载资源的限制
listener
- 监听器会监听某个域对象的的状态的变化,我们一般监听session作用域
- 监听器的相关概念:
- 事件源:被监听的对象(三个域对象 request、session、servletContext)
- 监听器:监听事件源对象事件源对象的状态的变化都会触发监听器
- 注册监听器:将监听器与事件源进?绑定
- 响应?为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)
- 可以按照被监听的对象划分
- ServletRequest域、HttpSession域、ServletContext域
- 也可以按照监听的内容划分
- 对象的创建和销毁,属性的变化
- 自定义实现监听器
编写?个监听器类去实现监听器接? 覆盖监听器的?法 需要在web.xml中进?配置—注册
- 框架里很多自动化的操作都是通过监听器实现的
MVC
- 为了让后台杂乱无章的代码有迹可循,出现了MVC设计模式,解耦代码
- 三层架构
- 通常意义上的三层架构就是将整个业务应?划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)
- 以BLL为核心,可以理解为是之前讲的xml路由映射和Servlet方法
- 三层是基于业务逻辑来分的,?MVC是基于??来分的
- MVC把三层架构中的UI层再度进?了分化
- 三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC作为表现模式是不存在上下关系的
model
- 建立项目,结构如下,引入jar包
- 代码从bean开始写,执行从servlet开始
- 建表,建实体类(模型类)
DROP TABLE IF EXISTS `student`; CREATE TABLE `student` (`studentid` int(11) NOT NULL AUTO_INCREMENT,`studentno` varchar(20) DEFAULT NULL,`stuname` varchar(5) DEFAULT NULL,`stuage` int(11) DEFAULT NULL,`gradeid` int(11) DEFAULT NULL,PRIMARY KEY (`studentid`) ) ENGINE=InnoDB AUTO_INCREMENT=122 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('1', 's1101', '张三', '11', '1'); INSERT INTO `student` VALUES ('2', 's1102', '李四', '22', '1'); INSERT INTO `student` VALUES ('3', 's1103', '王五', '33', '1'); INSERT INTO `student` VALUES ('4', 's1104', '赵柳', '44', '2'); INSERT INTO `student` VALUES ('5', 's1105', '田七', '55', '2'); INSERT INTO `student` VALUES ('110', 's110', 'abc', '66', '2'); INSERT INTO `student` VALUES ('111', 's111', '谢大脚1', '77', '2'); INSERT INTO `student` VALUES ('112', 'sno110', '广坤', '88', '2'); INSERT INTO `student` VALUES ('113', 'sno11', '谢广坤', '99', '3'); INSERT INTO `student` VALUES ('114', 'sno001', '广坤1', '1', '3'); INSERT INTO `student` VALUES ('115', 's00111', '谢大脚2', '2', '3'); INSERT INTO `student` VALUES ('116', 's00113', '谢大脚3', '3', '3'); INSERT INTO `student` VALUES ('117', 's00114', '谢大脚4', '4', '3'); INSERT INTO `student` VALUES ('120', 'a1101', '张娜', '18', null); INSERT INTO `student` VALUES ('121', 'c101', '广坤', '50', null);
package xzk.bean;public class Student { private Integer studentid;private String studentno;private String stuname;private Integer stuage;private Integer gradeid;// 构造public Student() { }public Student(Integer studentid, String studentno, String stuname, Integer stuage, Integer gradeid) { this.studentid = studentid;this.studentno = studentno;this.stuname = stuname;this.stuage = stuage;this.gradeid = gradeid;}// get setpublic Integer getStudentid() { return studentid;}public void setStudentid(Integer studentid) { this.studentid = studentid;}public String getStudentno() { return studentno;}public void setStudentno(String studentno) { this.studentno = studentno;}public String getStuname() { return stuname;}public void setStuname(String stuname) { this.stuname = stuname;}public Integer getStuage() { return stuage;}public void setStuage(Integer stuage) { this.stuage = stuage;}public Integer getGradeid() { return gradeid;}public void setGradeid(Integer gradeid) { this.gradeid = gradeid;} }
- dao层定义操作数据库接口并实现
package xzk.dao;import xzk.bean.Student;import java.util.List;// 操作bean的接口 public interface StudentDao { public List<Student> getStudents(); }
public class StudentDaoImpl extends DruidUtil implements StudentDao { @Overridepublic List<Student> getStudents() { List list = new ArrayList();Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try { connection = getConnection();preparedStatement = connection.prepareStatement("select * from student");resultSet = preparedStatement.executeQuery();while (resultSet.next()) { Student student = new Student();student.setStudentid(resultSet.getInt("studentid"));student.setStudentno(resultSet.getString("studentno"));student.setStuname(resultSet.getString("stuname"));student.setStuage(resultSet.getInt("stuage"));student.setGradeid(resultSet.getInt("gradeid"));list.add(student);}return list;} catch (SQLException e) { e.printStackTrace();} finally { close(connection, preparedStatement, resultSet);}return null;} }
- 为此需要引入工具类Druid和配置文件
package xzk.util;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import javax.xml.transform.Result; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties;public class DruidUtil { private static DataSource ds;static{ try { Properties ppt = new Properties();ppt.load(DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties"));ds = DruidDataSourceFactory.createDataSource(ppt);} catch (Exception e) { e.printStackTrace();}}/*** 从连接池中取出一个连接给用户* @return*/public static Connection getConnection(){ try { return ds.getConnection();} catch (SQLException throwables) { throwables.printStackTrace();}return null;}public static void close(Connection conn, Statement state, ResultSet rs){ try { rs.close();} catch (Exception throwables) { throwables.printStackTrace();}try { state.close();} catch (Exception throwables) { throwables.printStackTrace();}try { conn.close();} catch (Exception throwables) { throwables.printStackTrace();}} }
// druid.properties url=jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=utf-8 username=root password=123456 driverClassName=com.mysql.cj.jdbc.Driver initialSize=5 maxActive=10 minIdle=5 maxWait=3000
controller
- service层定义业务逻辑,接口名称:bean+Service
// 定义业务逻辑 // 这里就是简单调用一下dao层的实现 public interface StudentService { public List<Student> getAll(); }public class StudentServiceImpl implements StudentService { private StudentDao studentDao = new StudentDaoImpl();@Overridepublic List<Student> getAll() { return studentDao.getStudents();} }
- servlet调用service层的代码
// 相当于 Controller 管理路由+限定请求方法+调用业务类+返回页面 @WebServlet(urlPatterns = "/getstuall") public class StudentServlet extends HttpServlet { @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { }@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1 接受请求参数// 2 调取service层方法StudentServiceImpl studentService = new StudentServiceImpl();List<Student> all = studentService.getAll();// 3 跳转页面req.setAttribute("slist", all);req.getRequestDispatcher("/show.jsp").forward(req, resp); // req存的值作用域是单次请求,只能dispatcher} }
- 可以启动了,注意Druid配置文件的路径,可能要改为相对路径
前后端分离
- 以公共接口为桥梁
AJAX
- AJAX = Asynchronous JavaScript and XML
- 在不重新加载整个??的情况下,AJAX 与服务器交换数据并更新部分??
- 是?种原有技术的结合体
- 使?CSS和XHTML来表示
- 使?DOM模型来交互和动态显示
- 使?XMLHttpRequest来和服务器进?异步通信
- 使?javascript来绑定和调?
- AJAX 的核?是
XMLHttpRequest
对象,发送异步请求
工作原理
- 相当于在?户和服务器之间加了—个中间层(AJAX引擎),使?户请求与服务器响应异步
化
- 普通的交互方式:发出请求,等待服务器回复
- ajax交互方式:JavaScript发出请求,不必等待,可以继续发出请求
- 并不是所有的?户请求都提交给服务器
- —些数据验证和数据处理等都交给Ajax引擎??来做(异步)
- 确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求
- 案例:验证用户名有效性
<%--Created by IntelliJ IDEA.User: Windows10Date: 2021/12/31Time: 20:46To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>ajax</title> </head> <script type="text/javascript">function test(){ // 发送异步请求// 1. 创建XMLHttpRequest对象var xmlhttp;if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest();}else if (window.ActiveXObject) { // IE浏览器xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")}// 2. 打开链接 (从前到后 servlet)var username = document.getElementById("uname").value;xmlhttp.open("get", "/test?username="+username, true);// 3. 指定回调函数 (从后到前)xmlhttp.onreadystatechange=function () { // 判断状态(会监听)if (xmlhttp.readyState == 4) { // 接受input输入的数据var response = xmlhttp.responseText;// 放到指定位置document.getElementById("rs").innerText=response;}}// 4. 发送数据 (展示)xmlhttp.send();}</script> <body> <h1>username test</h1> username: <input type="text" id="uname" onblur="test()"><span id="rs"></span> </body> </html>
@WebServlet(urlPatterns = "/test") public class TestServlet extends HttpServlet { @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 接收参数String username = req.getParameter("username");resp.setContentType("text/html;charset=UTF-8");PrintWriter writer = resp.getWriter();if ("admin".equals(username)) { writer.println("账户已被注册");}else { writer.println("账户名可用");}} }
- 只能新建项目,不能和上一节的xzk目录并行
- span里还是不显示中文,只有???
属性和方法
- 都是基于
XMLHttpRequest
- 主要介绍
readyState
,存有服务器响应的状态信息,每当 readyState 改变时,onreadystatechange
函数就会被执?,这个回调是异步的基础,可以了解一下
open()
,第?个参数定义发送请求所使?的?法,第?个参数规定服务器端脚本的URL,第
三个参数规定应当对请求进?异步地处理send()
?法将请求送往服务器,(从前到后,open就是个准备,还需send执行)xmlHttp.open("GET", "/test?username="+username, true); xmlHttp.send(null); // 如果是getxmlHttp.open("POST","test.php",true); var params = "userName=" + uname+ "&userPass=" +upass+ "&time=" +Math.random(); // 增加time随机参数,防?读取缓存 xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); // 向请求添加 HTTP 头,POST如果有数据?定加加!!!! xmlHttp.send(params);
- get 还是 post?
- 异步还是同步
jQuery
- jQuery实现AJAX
# jquery_ajax.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>jquery</title> </head> <script type="text/javascript" src="js/jquery-1.8.0.min.js"></script> <script type="text/javascript">$(function () { $("#uname").blur(function () { // 失去焦点// 获取前端输入框 value 值var uname = $(this).val();// 发送请求 (从前到后)$.ajax({ // 无需创建XMLHttpRequest对象url:"testjq",data:"username="+uname,type:"post",dataType:"text",success:function (rs) { // 自动判断状态 (从后到前,不需要responseText)$("#rs").html(rs);}})//个get请求的简单写法// $.get("/testjq", "uaername="+uname, function (rs) { // span id// $("#rs").html(rs)// })// post提交的简单写法// $.post("/testjq", "uaername="+uname, function (rs) { // span id// $("#rs").html(rs)// })})}) </script> <body><h1>jQuery ajax test</h1>username: <input type="text" id="uname" onblur="test()"><span id="rs"></span> </body> </html>
- 后端路由需要改一下,servlet处理方法不变
- 后端路由需要改一下,servlet处理方法不变
- 拿捏住,ajax 就是用已有组件、由前端发起的、在BS中间插了一杠子的异步请求方式
json
- 传数据呀,传字符串或者xml都过时了,还是要用json
- JSON (JavaScript Object Notation) 是?种轻量级的数据交换格式
- 大致看一下定义和取值
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>json</title> </head> <script type="text/javascript">var js = { "name":"roy", "age":18};alert(js.name);var ja = { "name":["roy","allen"]};alert(ja.name[0]); </script> <body></body> </html>
- 转换,依赖 json-lib-2.2.2-jdk15.jar,scope=compile即可
package tajax;public class User { private String name;private Integer age;public User() { }public User(String name, Integer age) { this.name = name;this.age = age;}public String getName() { return name;}public void setName(String name) { this.name = name;}public Integer getAge() { return age;}public void setAge(Integer age) { this.age = age;} }
public class UserTest { public static void main(String[] args) { User user = new User("roy", 11);// java -> jsonJSONObject jsonObject = JSONObject.fromObject(user);System.out.println(jsonObject);// json -> javaString str = "{\"age\":11,\"name\":\"roy\"}";JSONObject jsonObject1 = JSONObject.fromObject(str);Object bean = JSONObject.toBean(jsonObject1, User.class);System.out.println(bean); // User{name='roy', age=11}// 集合也是类似的} }
- 更新页面只需要Update classes…,更改类需要Restart
- 案例:json+ajax 实现输入用户id自动填充信息
- 之前设置了jar包compile(需要provided),所以访问页面可能会找不到jar包
- 可以直接放到tomcat的lib里,删除out重启;或者删除lib重新Modules
- 后端返回后,还会涉及到一个
eval("("rs")")