zoukankan      html  css  js  c++  java
  • springboot动吧项目 日志模块

    1 项目简介

    1.1 概述

    动吧旅游生态系统,应市场高端用户需求,公司决定开发这样的一套旅游系统,此系统包含旅游电商系统(广告子系统,推荐子系统,评价子系统,商品子系统,订单子系统,…),旅游分销系统(分销商的管理),旅游业务系统(产品研发,计调服务,系统管理,..),,。。。

    1.2 原型分析

    基于用户需求,进行原型设计(基于html+css+js进行静态页面实现)。例如系统登录页面:

     

    系统登录成功页面(例如starter.html)

     

    菜单展示页面

     

    2 技术架构

    2.1 项目分层架构

    本项目应用层基于MVC设计思想,进行分层架构设计,其核心目的是将复杂问题简单化,实现各司其职,各尽所能.然后基于“高内聚,低耦合”的设计思想,再实现各对象之间协同,从而提高系统的可维护性,可扩展性。

     

    其中:

    1.开放接口层:可直接封装 Service 方法暴露成 RPC (远程过程调用)接口;也可通过 Web 封装成 http 接口;同时也可进行网关安全控制、流量控制等。 

    2.终端显示层:负责各个端的模板渲染并显示。当前主要是 thymeleaf 渲染,JS 渲染,移动端展示等。 

    3.Web请求处理层:主要是对访问控制进行转发,请求参数校验,响应结果处理等

    4.Service 层:相对具体的业务逻辑服务层(核心业务,扩展业务)。  

    5.Manager 层:通用业务处理层,它有如下特征:    

    1) 对第三方平台封装的层,预处理返回结果及转化异常信息;    

    2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;    

    3) 与 DAO 层交互,对多个 DAO 的组合复用。

    6.DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase 等进行数据交互。

    7.外部接口或第三方平台:包括其它部门RPC开放接口,基础平台,其它公司的 HTTP 接口

    2.2 API应用架构

    整体API应用架构:

     

    3 技术整合

    3.1 环境准备

    3.1.1 数据库初始化

    3.1.2 IDE配置初始化(STS)

    3.2 创建项目

    3.2.1 添加项目依赖

     

    3.2.1 修改配置文件

    在application.yml文件中添加如下配置(server,datasource,mybatis,mvc)

    #spring datasource
    spring.datasource.url=jdbc:mysql:///dbsys?serverTimezone=GMT%2B8&characterEncoding=utf8
    spring.datasource.username=root
    spring.datasource.password=root
    #mybatis
    mybatis.mapper-locations=classpath:/mapper/*/*.xml
    #spring web
    spring.thymeleaf.prefix=classpath:/templates/pages/
    spring.thymeleaf.cache=false
    #Spring log
    logging.level.com.cy=debug

    3.3 首页初始化

    3.3.1 定义页面初始资源

    1. 将js、css、images相关资源拷贝到项目static目录

    2. 将pages页面拷贝到项目的templates目录

    3.3.2 创建页面Controller

    创建呈现首页页面的controller对象。

    package com.cy.pj.sys.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    @RequestMapping("/")
        @Controller
    public class PageController {
        @RequestMapping("doIndexUI")
        public String doIndexUI(){
            return "starter";
        }
    }

    3.3.3 启动项目进行测试

    启动tomcat,在地址栏输入http://localhost/doIndexUI(地址中的端口号要参考自己tomcat启动端口)地址进行访问,假如没有问题会呈现如下页面

     

     页面访问流程分析,如下图所示(了解):

      1. 业务设计说明

     本模块主要是实现对用户行为日志(例如谁在什么时间点执行了什么操作,访问了哪些方法,传递的什么参数,执行时长等)进行记录、查询、删除等操作。其表设计语句如下:

    CREATE TABLE `sys_logs` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `username` varchar(50) DEFAULT NULL COMMENT '登陆用户名',
      `operation` varchar(50) DEFAULT NULL COMMENT '用户操作',
      `method` varchar(200) DEFAULT NULL COMMENT '请求方法',
      `params` varchar(5000) DEFAULT NULL COMMENT '请求参数',
      `time` bigint(20) NOT NULL COMMENT '执行时长(毫秒)',
      `ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',
      `createdTime` datetime DEFAULT NULL COMMENT '日志记录时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='系统日志';
    1. 原型设计说明

    基于用户需求,实现静态页面(html/css/js),通过静态页面为用户呈现基本需求实现,如图-1所示。

     

    1. API设计说明

    日志业务后台API分层架构及调用关系如图-2所示:

     

    1. 日志管理列表页面呈现

      1. 业务时序分析

    当点击首页左侧的"日志管理"菜单时,其总体时序分析如图-3所示:

     

    1. 服务端实现

      1. Controller实现

    • 业务描述与设计实现

    基于日志管理的请求业务,在PageController中添加doLogUI方法,doPageUI方法分别用于返回日志列表页面,日志分页页面。

    • 关键代码设计与实现

    第一步:在PageController中定义返回日志列表的方法。代码如下:

    @RequestMapping("log/log_list")
    public String doLogUI() {
        return "sys/log_list";
    }

    第二步:在PageController中定义用于返回分页页面的方法。代码如下:

    @RequestMapping("doPageUI")

    public String doPageUI() {
        return "common/page";
    }
    1. 客户端实现

      1. 日志菜单事件处理

    • 业务描述与设计

    首先准备日志列表页面(/templates/pages/sys/log_list.html),然后在starter.html页面中点击日志管理菜单时异步加载日志列表页面。

    • 关键代码设计与实现

    找到项目中的starter.html 页面,页面加载完成以后,注册日志管理菜单项的点击事件,当点击日志管理时,执行事件处理函数。关键代码如下

    $(function(){
         doLoadUI("load-log-id","log/log_list")
    })
    function doLoadUI(id,url){
         $("#"+id).click(function(){
            $("#mainContentId").load(url);
        });
    }
    1. 日志列表页面事件处理

    • 业务描述与设计实现

    当日志列表页面加载完成以后异步加载分页页面(page.html)。

    • 关键代码设计与实现:

    在log_list.html页面中异步加载page页面,这样可以实现分页页面重用,哪里需要分页页面,哪里就进行页面加载即可。关键代码如下:

    $(function(){
        $("#pageId").load("doPageUI");
    });
    1. 日志管理列表数据呈现

      1. 数据架构分析

    日志查询服务端数据基本架构,如图-4所示。

     

    1. 服务端API架构及业务时序图分析

    服务端日志分页查询代码基本架构,如图-5所示:

     

    服务端日志列表数据查询时序图,如图-6所示:

     

    1. 服务端关键业务及代码实现

      1. Entity类实现

    • 业务描述及设计实现

    构建实体对象(POJO)封装从数据库查询到的记录,一行记录映射为内存中一个的这样的对象。对象属性定义时尽量与表中字段有一定的映射关系,并添加对应的set/get/toString等方法,便于对数据进行更好的操作。

    • 关键代码分析及实现

    package com.cy.pj.sys.entity;
    import java.io.Serializable;
    import java.util.Date;
     
    public class SysLog implements Serializable {
        private static final long serialVersionUID = 1L;
        private Integer id;
        //用户名
        private String username;
        //用户操作
        private String operation;
        //请求方法
        private String method;
        //请求参数
        private String params;
        //执行时长(毫秒)
        private Long time;
        //IP地址
        private String ip;
        //创建时间
        private Date createdTime;
     
        /**设置:*/
        public void setId(Integer id) {
            this.id = id;
        }
        /**获取:*/
        public Integer getId() {
            return id;
        }
        /**设置:用户名*/
        public void setUsername(String username) {
            this.username = username;
        }
        /** 获取:用户名*/
        public String getUsername() {
            return username;
        }
        /**设置:用户操作*/
        public void setOperation(String operation) {
            this.operation = operation;
        }
        /**获取:用户操作*/
        public String getOperation() {
            return operation;
        }
        /**设置:请求方法*/
        public void setMethod(String method) {
            this.method = method;
        }
        /**获取:请求方法*/
        public String getMethod() {
            return method;
        }
        /** 设置:请求参数*/
        public void setParams(String params) {
            this.params = params;
        }
        /** 获取:请求参数 */
        public String getParams() {
            return params;
        }
        /**设置:IP地址 */
        public void setIp(String ip) {
            this.ip = ip;
        }
        /** 获取:IP地址*/
        public String getIp() {
            return ip;
        }
        /** 设置:创建时间*/
        public void setCreateDate(Date createdTime) {
            this.createdTime = createdTime;
        }
        /** 获取:创建时间*/
        public Date getCreatedTime() {
            return createdTime;
        }
     
        public Long getTime() {
            return time;
        }
     
        public void setTime(Long time) {
            this.time = time;
        }

    说明:通过此对象除了可以封装从数据库查询的数据,还可以封装客户端请求数据,实现层与层之间数据的传递。

    思考:这个对象的set方法,get方法可能会在什么场景用到?

    1. Dao接口实现

    • 业务描述及设计实现

    通过数据层对象,基于业务层参数数据查询日志记录总数以及当前页要呈现的用户行为日志信息。 

    • 关键代码分析及实现:

    第一步:定义数据层接口对象,通过将此对象保证给业务层以提供日志数据访问。代码如下:

    @Mapper
    public interface SysLogDao {
    }
     

    第二步:在SysLogDao接口中添加getRowCount方法用于按条件统计记录总数。代码如下:

    /**
         * @param username 查询条件(例如查询哪个用户的日志信息)
         * @return 总记录数(基于这个结果可以计算总页数)
         */
        int getRowCount(@Param("username") String username);
        
    }

    第三步:在SysLogDao接口中添加findPageObjects方法,基于此方法实现当前页记录的数据查询操作。代码如下:

    /**
         * @param username  查询条件(例如查询哪个用户的日志信息)
         * @param startIndex 当前页的起始位置
         * @param pageSize 当前页的页面大小
         * @return 当前页的日志记录信息
         * 数据库中每条日志信息封装到一个SysLog对象中
         */
        List<SysLog> findPageObjects(
                      @Param("username")String  username,
                      @Param("startIndex")Integer startIndex,
                      @Param("pageSize")Integer pageSize);

    说明:

    1. 当DAO中方法参数多余一个时尽量使用@Param注解进行修饰并指定名字,然后在Mapper文件中便可以通过类似#{username}方式进行获取,否则只能通过#{arg0},#{arg1}或者#{param1},#{param2}等方式进行获取。

    2. 当DAO方法中的参数应用在动态SQL中时无论多少个参数,尽量使用@Param注解进行修饰并定义。

    1. Mapper文件实现

    • 业务描述及设计实现

    基于Dao接口创建映射文件,在此文件中通过相关元素(例如select)描述要执行的数据操作。

    • 关键代码设计及实现

    第一步:在映射文件的设计目录(mapper/sys)中添加SysLogMapper.xml映射文件,代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cy.pj.sys.dao.SysLogDao">
      
    </mapper>

    第二步:在映射文件中添加sql元素实现,SQL中的共性操作,代码如下:

    <sql id="queryWhereId">
             from sys_Logs
              <where>
                <if test="username!=null and username!=''">
                   username like concat("%",#{username},"%")
                </if>
              </where>
        </sql>

    第三步:在映射文件中添加id为getRowCount元素,按条件统计记录总数,

    代码如下:

     <select id="getRowCount"
                resultType="int">
              select count(*) 
              <include refid="queryWhereId"/>
        </select>

    第四步:在映射文件中添加id为findPageObjects元素,实现分页查询。代码如下:

     <select id="findPageObjects"
                resultType="com.cy.pj.sys.entity.SysLog">
             select *
             <include refid="queryWhereId"/>
    order by createdTime desc
             limit #{startIndex},#{pageSize}    
    </select>
     

     第五步:单元测试类SysLogDaoTests,对数据层方法进行测试。  

    package com.cy.pj.sys.dao;
     
    import java.util.List;
     
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
     
    import com.cy.pj.sys.entity.SysLog;
     
    @SpringBootTest
    public class SysLogDaoTests {
     
           @Autowired
           private SysLogDao sysLogDao;
           
           @Test
           public void testGetRowCount() {
               int rows=sysLogDao.getRowCount("admin");
               System.out.println("rows="+rows);
           }
           @Test
           public void testFindPageObjects() {
               List<SysLog> list=
               sysLogDao.findPageObjects("admin", 0, 3);
               for(SysLog log:list) {
                   System.out.println(log);
               }
           }
    }
    1. Service接口及实现类

    • 业务描述与设计实现

    业务层主要是实现模块中业务逻辑的处理。在日志分页查询中,业务层对象首先要通过业务方法中的参数接收控制层数据(例如username,pageCurrent)并校验。然后基于用户名进行总记录数的查询并校验,再基于起始位置及页面大小进行当前页记录的查询,最后对查询结果进行封装并返回。

    • 关键代码设计及实现

    业务值对象定义,基于此对象封装数据层返回的数据以及计算的分页信息,具体代码参考如下:

    package com.cy.pj.common.bo;
    public class PageObject<T> implements Serializable {
        private static final long serialVersionUID = 6780580291247550747L;//类泛型
        /**当前页的页码值*/
         private Integer pageCurrent=1;
        /**页面大小*/
        private Integer pageSize=3;
        /**总行数(通过查询获得)*/
        private Integer rowCount=0;
        /**总页数(通过计算获得)*/
        private Integer pageCount=0;
        /**当前页记录*/
        private List<T> records;
    public PageObject(){}
        public PageObject(Integer pageCurrent, Integer pageSize, Integer rowCount, List<T> records) {
            super();
            this.pageCurrent = pageCurrent;
            this.pageSize = pageSize;
            this.rowCount = rowCount;
            this.records = records;
    //        this.pageCount=rowCount/pageSize;
    //        if(rowCount%pageSize!=0) {
    //            pageCount++;
    //        }
            this.pageCount=(rowCount-1)/pageSize+1;
        }
        public Integer getPageCurrent() {
            return pageCurrent;
        }
        public void setPageCurrent(Integer pageCurrent) {
            this.pageCurrent = pageCurrent;
        }
        public Integer getPageSize() {
            return pageSize;
        }
        public void setPageSize(Integer pageSize) {
            this.pageSize = pageSize;
        }
        public Integer getRowCount() {
            return rowCount;
        }
        public void setRowCount(Integer rowCount) {
            this.rowCount = rowCount;
        }
        
        public Integer getPageCount() {
            return pageCount;
        }
        public void setPageCount(Integer pageCount) {
           this.pageCount = pageCount;
        }
        public List<T> getRecords() {
            return records;
        }
        public void setRecords(List<T> records) {
            this.records = records;
        } 
    }

    定义日志业务接口及方法,暴露外界对日志业务数据的访问,其代码参考如下:

    package com.cy.pj.sys.service;
    public interface SysLogService {
             /**
          * @param name 基于条件查询时的参数名
          * @param pageCurrent 当前的页码值
          * @return 当前页记录+分页信息
          */
         PageObject<SysLog> findPageObjects(
                 String username,
                 Integer pageCurrent);
    }

    日志业务接口及实现类,用于具体执行日志业务数据的分页查询操作,其代码如下:

    package com.cy.pj.sys.service.impl;
    @Service
    public class SysLogServiceImpl implements SysLogService{
          @Autowired
         private SysLogDao sysLogDao;
          @Override
          public PageObject<SysLog> findPageObjects(
                  String name, Integer pageCurrent) {
              //1.验证参数合法性
              //1.1验证pageCurrent的合法性,
              //不合法抛出IllegalArgumentException异常
              if(pageCurrent==null||pageCurrent<1)

     throw new IllegalArgumentException("当前页码不正确");

      //2.基于条件查询总记录数

      //2.1) 执行查询

      int rowCount=sysLogDao.getRowCount(name);

      //2.2) 验证查询结果,假如结果为0不再执行如下操作

      if(rowCount==0)

              throw new ServiceException("系统没有查到对应记录");

      //3.基于条件查询当前页记录(pageSize定义为2)

      //3.1)定义pageSize

      int pageSize=2;

      //3.2)计算startIndex

      int startIndex=(pageCurrent-1)*pageSize;

      //3.3)执行当前数据的查询操作

      List<SysLog> records=

      sysLogDao.findPageObjects(name, startIndex, pageSize);

      //4.对分页信息以及当前页记录进行封装

      //4.1)构建PageObject对象

      PageObject<SysLog> pageObject=new PageObject<>();

      //4.2)封装数据

      pageObject.setPageCurrent(pageCurrent);

      pageObject.setPageSize(pageSize);

      pageObject.setRowCount(rowCount);

      pageObject.setRecords(records);

               pageObject.setPageCount((rowCount-1)/pageSize+1);

      //5.返回封装结果。

      return pageObject;

      }

    }

    在当前方法中需要的ServiceException是一个自己定义的异常, 通过自定义异常可更好的实现对业务问题的描述,同时可以更好的提高用户体验。参考代码如下:

    ackage com.cy.pj.common.exception;
    public class ServiceException extends RuntimeException {
        private static final long serialVersionUID = 7793296502722655579L;
        public ServiceException() {
            super();
        }
        public ServiceException(String message) {
            super(message);
            // TODO Auto-generated constructor stub
        }
        public ServiceException(Throwable cause) {
            super(cause);
            // TODO Auto-generated constructor stub
        } 
    }

    说明:几乎在所有的框架中都提供了自定义异常,例如MyBatis中的BindingException等。

     

    定义Service对象的单元测试类,代码如下:

    package com.cy.pj.sys.service;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
     
    import com.cy.pj.common.vo.PageObject;
    import com.cy.pj.sys.entity.SysLog;
     
    @SpringBootTest
    public class SysLogServiceTests {
     
        @Autowired
        private SysLogService sysLogService;
        @Test
        public void testFindPageObjects() {
           PageObject<SysLog> pageObject=
           sysLogService.findPageObjects("admin", 1);
           System.out.println(pageObject);
           
        }
    }
    1. Controller类实现

    • 业务描述与设计实现

    控制层对象主要负责请求和响应数据的处理,例如,本模块首先要通过控制层对象处理请求参数,然后通过业务层对象执行业务逻辑,再通过VO对象封装响应结果(主要对业务层数据添加状态信息),最后将响应结果转换为JSON格式的字符串响应到客户端。

    • 关键代码设计与实现

    定义控制层值对象(VO),目的是基于此对象封装控制层响应结果(在此对象中主要是为业务层执行结果添加状态信息)。Spring MVC框架在响应时可以调用相关API(例如jackson)将其对象转换为JSON格式字符串。

    package com.cy.pj.common.vo;
    public class JsonResult implements Serializable {
        private static final long serialVersionUID = -856924038217431339L;//SysResult/Result/R
        /**状态码*/
        private int state=1;//1表示SUCCESS,0表示ERROR
        /**状态信息*/
        private String message="ok";
        /**正确数据*/
        private Object data;
        public JsonResult() {}
        public JsonResult(String message){
            this.message=message;
        }
        /**一般查询时调用,封装查询结果*/
        public JsonResult(Object data) {
            this.data=data;
        }
        /**出现异常时时调用*/
        public JsonResult(Throwable t){
            this.state=0;
            this.message=t.getMessage();
        }
        public int getState() {
            return state;
        }
        public void setState(int state) {
            this.state = state;
        }
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        public Object getData() {
            return data;
        }
        public void setData(Object data) {
            this.data = data;
        }
    }

    定义Controller类,并将此类对象使用Spring框架中的@Controller注解进行标识,表示此类对象要交给Spring管理。然后基于@RequestMapping注解为此类定义根路径映射。代码参考如下:

    package com.cy.pj.sys.controller;
    @Controller
    @RequestMapping("/log/")
    public class SysLogController {
        @Autowired
        private SysLogService sysLogService;
    }

    在Controller类中添加分页请求处理方法,代码参考如下:

    @RequestMapping("doFindPageObjects")
    @ResponseBody
    public JsonResult doFindPageObjects(String username,Integer pageCurrent){
     PageObject<SysLog> pageObject=
        sysLogService.findPageObjects(username,pageCurrent);
    return new JsonResult(pageObject);
    }

    定义全局异常处理类,对控制层可能出现的异常,进行统一异常处理,代码如下:

    package com.cy.pj.common.web;
    import java.util.logging.Logger;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.cy.pj.common.vo.JsonResult;
    @ControllerAdvice
    public class GlobalExceptionHandler {
        //JDK中的自带的日志API
        @ExceptionHandler(RuntimeException.class)
       @ResponseBody
        public JsonResult doHandleRuntimeException(
                RuntimeException e){
            e.printStackTrace();//也可以写日志
            异常信息
            return new JsonResult(e);//封装
       }
    }

    控制层响应数据处理分析,如图-7所示:

     

    1. 客户端关键业务及代码实现

      1. 客户端页面事件分析

    当用户点击首页日志管理时,其页面流转分析如图-8所示:

     

    1. 日志列表信息呈现

    • 业务描述与设计实现

    日志分页页面加载完成以后,向服务端发起异步请求加载日志信息,当日志信息加载完成需要将日志信息、分页信息呈现到列表页面上。

    • 关键代码设计与实现

    第一步:分页页面加载完成,向服务端发起异步请求,代码参考如下:

     $(function(){
           //为什么要将doGetObjects函数写到load函数对应的回调内部。
           $("#pageId").load("doPageUI",function(){
               doGetObjects();
           });
    }

    第二步:定义异步请求处理函数,代码参考如下:

     function doGetObjects(){
           //debugger;//断点调试
           //1.定义url和参数
           var url="log/doFindPageObjects"
           var params={"pageCurrent":1};//pageCurrent=2
           //2.发起异步请求
           //请问如下ajax请求的回调函数参数名可以是任意吗?//可以,必须符合标识符的规范
           $.getJSON(url,params,function(result){
               //请问result是一个字符串还是json格式的js对象?对象
                 doHandleQueryResponseResult(result);
             }
           );//特殊的ajax函数
       }

    result 结果对象分析,如图-9所示:

     

    第三步:定义回调函数,处理服务端的响应结果。代码如下:

    function doHandleQueryResponseResult (result){ //JsonResult
           if(result.state==1){//ok
            //更新table中tbody内部的数据
            doSetTableBodyRows(result.data.records);//将数据呈现在页面上 
            //更新页面page.html分页数据
            //doSetPagination(result.data); //此方法写到page.html中
            }else{
            alert(result.message);
            }  
     }

    第四步:将异步响应结果呈现在table的tbody位置。代码参考如下:

    function doSetTableBodyRows(records){
           //1.获取tbody对象,并清空对象
           var tBody=$("#tbodyId");
           tBody.empty();
           //2.迭代records记录,并将其内容追加到tbody
           for(var i in records){
               //2.1 构建tr对象
               var tr=$("<tr></tr>");
               //2.2 构建tds对象
               var tds=doCreateTds(records[i]);
               //2.3 将tds追加到tr中
               tr.append(tds);
               //2.4 将tr追加到tbody中
               tBody.append(tr);
           }
       }

    第五步:创建每行中的td元素,并填充具体业务数据。代码参考如下:

      function doCreateTds(data){
           var tds="<td><input type='checkbox' class='cBox' name='cItem' value='"+data.id+"'></td>"+
                 "<td>"+data.username+"</td>"+
                 "<td>"+data.operation+"</td>"+
                 "<td>"+data.method+"</td>"+
                 "<td>"+data.params+"</td>"+
                 "<td>"+data.ip+"</td>"+
                 "<td>"+data.time+"</td>";       
    return tds;
       }
    1. 分页数据信息呈现

    • 业务描述与设计实现

    日志信息列表初始化完成以后初始化分页数据(调用setPagination函数),然后再点击上一页,下一页等操作时,更新页码值,执行基于当前页码值的查询。

    • 关键代码设计与实现:

    第一步:在page.html页面中定义doSetPagination方法(实现分页数据初始化),代码如下:

       function doSetPagination(page){
            //1.始化数据
            $(".rowCount").html("总记录数("+page.rowCount+")");
            $(".pageCount").html("总页数("+page.pageCount+")");
            $(".pageCurrent").html("当前页("+page.pageCurrent+")");
            //2.绑定数据(为后续对此数据的使用提供服务)
            $("#pageId").data("pageCurrent",page.pageCurrent);
            $("#pageId").data("pageCount",page.pageCount);
        }

    第二步:分页页面page.html中注册点击事件。代码如下:

    $(function(){
            //事件注册
             $("#pageId").on("click",".first,.pre,.next,.last",doJumpToPage);
    })

    第三步:定义doJumpToPage方法(通过此方法实现当前数据查询)

     function doJumpToPage(){
            //1.获取点击对象的class值
            var cls=$(this).prop("class");//Property
            //2.基于点击的对象执行pageCurrent值的修改
            //2.1获取pageCurrent,pageCount的当前值
            var pageCurrent=$("#pageId").data("pageCurrent");
            var pageCount=$("#pageId").data("pageCount");
            //2.2修改pageCurrent的值
            if(cls=="first"){//首页
                pageCurrent=1;
            }else if(cls=="pre"&&pageCurrent>1){//上一页
                pageCurrent--;
            }else if(cls=="next"&&pageCurrent<pageCount){//下一页
                pageCurrent++;
            }else if(cls=="last"){//最后一页
                pageCurrent=pageCount;
            }else{
             return;
    }
            //3.对pageCurrent值进行重新绑定
            $("#pageId").data("pageCurrent",pageCurrent);
            //4.基于新的pageCurrent的值进行当前页数据查询
            doGetObjects();
        }

    修改分页查询方法:(看黄色底色部分)

    function doGetObjects(){
           //debugger;//断点调试
           //1.定义url和参数
           var url="log/doFindPageObjects"
           //? 请问data函数的含义是什么?(从指定元素上获取绑定的数据)
           //此数据会在何时进行绑定?(setPagination,doQueryObjects)
           var pageCurrent=$("#pageId").data("pageCurrent");
           //为什么要执行如下语句的判定,然后初始化pageCurrent的值为1
           //pageCurrent参数在没有赋值的情况下,默认初始值应该为1.
           if(!pageCurrent) pageCurrent=1;
           var params={"pageCurrent":pageCurrent};//pageCurrent=2
           //2.发起异步请求
           //请问如下ajax请求的回调函数参数名可以是任意吗?可以,必须符合标识符的规范
           $.getJSON(url,params,function(result){
               //请问result是一个字符串还是json格式的js对象?对象
                    doH
    andleResponseResult(result);
             }
           );//特殊的ajax函数 }
    1. 列表页面信息查询实现

    • 业务描述及设计

    当用户点击日志列表的查询按钮时,基于用户输入的用户名进行有条件的分页查询,并将查询结果呈现在页面。

    • 关键代码设计与实现:

    第一步:日志列表页面加载完成,在查询按钮上进行事件注册。代码如下:

    $(".input-group-btn").on("click",".btn-search",doQueryObjects)

    第二步:定义查询按钮对应的点击事件处理函数。代码如下:

     function doQueryObjects(){
           //为什么要在此位置初始化pageCurrent的值为1?
           //数据查询时页码的初始位置也应该是第一页
           $("#pageId").data("pageCurrent",1);
           //为什么要调用doGetObjects函数?
           //重用js代码,简化jS代码编写。
           doGetObjects();
       }

    第三步:在分页查询函数中追加name参数定义(看黄色底色部分),代码如下

    function doGetObjects(){
           //debugger;//断点调试
           //1.定义url和参数
           var url="log/doFindPageObjects"
           //? 请问data函数的含义是什么?(从指定元素上获取绑定的数据)
           //此数据会在何时进行绑定?(setPagination,doQueryObjects)
           var pageCurrent=$("#pageId").data("pageCurrent");
           //为什么要执行如下语句的判定,然后初始化pageCurrent的值为1
           //pageCurrent参数在没有赋值的情况下,默认初始值应该为1.
           if(!pageCurrent) pageCurrent=1;
           var params={"pageCurrent":pageCurrent};
           //为什么此位置要获取查询参数的值?
           //一种冗余的应用方法,目的时让此函数在查询时可以重用。
           var username=$("#searchNameId").val();
           //如下语句的含义是什么?动态在json格式的js对象中添加key/value,
           if(username) params.username=username;//查询时需要
           //2.发起异步请求
           //请问如下ajax请求的回调函数参数名可以是任意吗?可以,必须符合标识符的规范
           $.getJSON(url,params,function(result){
               //请问result是一个字符串还是json格式的js对象?对象
                    doHandleResponseResult(result);
             }
           );
       }
  • 相关阅读:
    关于findViewById返回空指针的错误
    android客户端向服务器发送图片和文字,类似于发微博。能用json格式发送吗?
    nodejs 学习资料大全
    篇章三:[AngularJS] 使用AngularCSS動態載入CSS
    篇章二:[AngularJS] 使用AngularAMD動態載入Service
    篇章一:[AngularJS] 使用AngularAMD動態載入Controller
    Angular 资料大集合
    js-音乐播放器,播放|暂停|滑块的功能
    JS-以鼠标位置为中心的滑轮放大功能demo1
    使用 Electron 构建桌面应用(拖动控制篇)
  • 原文地址:https://www.cnblogs.com/wangjincai/p/13288021.html
Copyright © 2011-2022 走看看