当前位置: 代码迷 >> 综合 >> 新职课(chapter5-3)
  详细解决方案

新职课(chapter5-3)

热度:24   发布时间:2023-12-20 12:57:51.0

文章目录

  • 会话跟踪
    • 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设计模式,解耦代码
    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 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引擎),使?户请求与服务器响应异步

    6
    7
    • 普通的交互方式:发出请求,等待服务器回复
    • 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 函数就会被执?,这个回调是异步的基础,可以了解一下
    1
    2
  • 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?
    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 -> 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}// 集合也是类似的}
    }
    
    8
    • 更新页面只需要Update classes…,更改类需要Restart
  • 案例:json+ajax 实现输入用户id自动填充信息
    • 之前设置了jar包compile(需要provided),所以访问页面可能会找不到jar包
    • 可以直接放到tomcat的lib里,删除out重启;或者删除lib重新Modules
    • 后端返回后,还会涉及到一个eval("("rs")")