新职课(chapter5-3)

会话跟踪

  • 常用的会话跟踪技术是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 {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("初始化filter");
        }
    
        @Override
        public 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");
        }
    
        @Override
        public 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设计模式,解耦代码
    1
  • 三层架构
    • 通常意义上的三层架构就是将整个业务应⽤划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)
    • 以BLL为核心,可以理解为是之前讲的xml路由映射和Servlet方法
  • 三层是基于业务逻辑来分的,⽽MVC是基于⻚⾯来分的
    • MVC把三层架构中的UI层再度进⾏了分化
    • 三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC作为表现模式是不存在上下关系的

model

  • 建立项目,结构如下,引入jar包
    2
  • 代码从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 set
    
        public 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 {
        @Override
        public 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();
        @Override
        public List<Student> getAll() {
            return studentDao.getStudents();
        }
    }
    
  • servlet调用service层的代码
    // 相当于 Controller 管理路由+限定请求方法+调用业务类+返回页面
    @WebServlet(urlPatterns = "/getstuall")
    public class StudentServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
        }
    
        @Override
        protected 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引擎),使⽤户请求与服务器响应异步

    6
    7
    • 普通的交互方式:发出请求,等待服务器回复
    • ajax交互方式:JavaScript发出请求,不必等待,可以继续发出请求
  • 并不是所有的⽤户请求都提交给服务器
    • —些数据验证和数据处理等都交给Ajax引擎⾃⼰来做(异步)
    • 确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求
  • 案例:验证用户名有效性
    <%--
      Created by IntelliJ IDEA.
      User: Windows10
      Date: 2021/12/31
      Time: 20:46
      To 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 {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    
        @Override
        protected 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 函数就会被执⾏,这个回调是异步的基础,可以了解一下
    1
    2
  • open(),第⼀个参数定义发送请求所使⽤的⽅法,第⼆个参数规定服务器端脚本的URL,第
    三个参数规定应当对请求进⾏异步地处理
  • send() ⽅法将请求送往服务器,(从前到后,open就是个准备,还需send执行)
    xmlHttp.open("GET", "/test?username="+username, true);
    xmlHttp.send(null);	// 如果是get
    
    xmlHttp.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?
    5
  • 异步还是同步
    6

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处理方法不变
      7
  • 拿捏住,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 -> json
            JSONObject jsonObject = JSONObject.fromObject(user);
            System.out.println(jsonObject);
    
            // json -> java
            String 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}
            
            // 集合也是类似的
        }
    }
    
    8
    • 更新页面只需要Update classes…,更改类需要Restart
  • 案例:json+ajax 实现输入用户id自动填充信息
    • 之前设置了jar包compile(需要provided),所以访问页面可能会找不到jar包
    • 可以直接放到tomcat的lib里,删除out重启;或者删除lib重新Modules
    • 后端返回后,还会涉及到一个eval("("rs")")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roy_Allen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值