4.springboot视图渲染技术

简介: 4.springboot视图渲染技术

1.Freemarker简介及入门


1.1.学习网址

http://freemarker.foofun.cn/

1.2.创建模块spboot04

1.3.application.yml中添加内容

mybatis:
  mapper-locations: classpath:mappers/**/*.xml
  type-aliases-package: com.zjzaki.spboot04.entity
logging:
  level:
    com.zjzaki.spboot04: debug
server:
  port: 8080
spring:
  application:
    name: spboot04
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    name: defaultDataSource
    url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
  freemarker:
    cache: false
    charset: utf-8
    expose-request-attributes: true
    expose-session-attributes: true
    suffix: .ftl
    template-loader-path: classpath:/templates/
resources:
    static-locations: classpath:/static/**

1.4.添加ftl文件模板

1.5.在templates下新建index.ftl

index.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
  这是一个测试页面
</body>
</html>

1.6.在controller包下面新建IndexController

package com.zjzaki.spboot04.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.controller
 * @Date 2023-08-09 18:42:29
 */
@Controller
public class IndexController {

    @GetMapping("/")
    public String index(){
        return "index";
    }
}

1.7.启动项目

访问页面, 成功访问

2.Freemarker语法


2.1.templates下创建common.ftl

<#assign ctx>
    ${springMacroRequestContext.contextPath}
</#assign>
<#global ctx2>
    ${springMacroRequestContext.contextPath}
</#global>

2.2.修改index.ftl中的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>1.取值</h1>
    <h2>1.1. 提供默认值</h2>
        <#--报错-->
        <#--${uname}    -->
        <#--不报错,但是页面无内容-->
        <#--${uname !}-->
        <#--给值设置一个默认值-->
        ${uname! '无名'}

    <h2>1.2. 对null值先进行判断</h2>
    <p>1)exists用在逻辑判断;</p>
    <#if uname?exists>
        ${uname}
    </#if>
    <br>
    <p>2)??是判断对象是否为空</p>
    <#if uname??>
        ${uname}
    </#if>
    <br>
    <p>3)if_exists用来打印东西</p>
    ${uname?if_exists}
    <br>

    <h1>2.条件</h1>
    <#if sex=='nv'>
    <#elseif sex='nan'>
    <#else>
        未知
    </#if>
    <br>

    <h1>3.循环</h1>
    <p>1)取出数组中的元素</p>
    <#list arr as a>
        ${a}==
    </#list>
    <br>
    <p>2)取出集合中的对象(注:访问的类要被public所修饰)</p>
    <#list lst as item>
        ${item.id} : ${item.name}    <br>
    </#list>

    <h1>4 include</h1>
    <#include "/common.ftl" >

    <h2>5 局部变量(assign)/全局变量(global)</h2>
    ${ctx}:${ctx2}
</body>
</html>

2.3.新建entity包,并创建User实体类

package com.zjzaki.spboot04.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.entity
 * @Date 2023-08-09 18:54:34
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    /**
     * 用户编号
     */
    private Integer id;

    /**
     * 用户姓名
     */
    private String name;
}

2.4.IndexController中添加内容

package com.zjzaki.spboot04.controller;

import com.zjzaki.spboot04.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.controller
 * @Date 2023-08-09 18:42:29
 */
@Controller
public class IndexController {

    @GetMapping("/")
    public String index(Model model){

        System.out.println("come in............");
        model.addAttribute("uname", "小刘");
        model.addAttribute("sex", "girl");
        List<User> lst = new ArrayList<>();
        lst.add(new User(1, "zs"));
        lst.add(new User(2, "ls"));
        lst.add(new User(3, "ww"));

        model.addAttribute("lst",lst);
        model.addAttribute("arr", new Integer[]{5, 6, 7, 8, 9});
        return "index";
    }
}

2.5.重启项目

效果

3.Freemarker综合案例


3.1.创建表

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for t_struts_class
-- ----------------------------
DROP TABLE IF EXISTS `t_struts_class`;
CREATE TABLE `t_struts_class` (
  `cid` int(11) NOT NULL,
  `cname` varchar(255) DEFAULT NULL,
  `cteacher` varchar(255) DEFAULT NULL,
  `pic` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for t_struts_student
-- ----------------------------
DROP TABLE IF EXISTS `t_struts_student`;
CREATE TABLE `t_struts_student` (
  `sid` int(11) NOT NULL,
  `cid` int(11) NOT NULL,
  `sname` varchar(255) NOT NULL,
  `spin` varchar(255) DEFAULT NULL,
  `sex` varchar(4) DEFAULT NULL,
  `mark` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records 
-- ----------------------------
INSERT INTO `t_struts_class` VALUES ('1', 't211', '晓', '/upload/1.png');
INSERT INTO `t_struts_class` VALUES ('2', 't212', '晓1', '/upload/9.png');
INSERT INTO `t_struts_class` VALUES ('3', 't216', '晓', '/upload/3.png');
INSERT INTO `t_struts_class` VALUES ('4', 't207', '宇7', '/upload/4.png');
INSERT INTO `t_struts_class` VALUES ('5', 't209', '宇', '/upload/7.png');
INSERT INTO `t_struts_student` VALUES ('1', '1', '尹超', 'yinchao', '1', '1,3');
INSERT INTO `t_struts_student` VALUES ('4', '2', '老邓头', 'laodengtou', '2', '1,2,3');
INSERT INTO `t_struts_student` VALUES ('5', '2', '测试', 'ceshi', '2', 'mark');
INSERT INTO `t_struts_student` VALUES ('7', '1', '桃子23', 'TZ23', '女', '23');
INSERT INTO `t_struts_student` VALUES ('8', '1', '桃子21', 'TZ21', '女', '21');
INSERT INTO `t_struts_student` VALUES ('11', '1', '超', 'C', '女', '34');
INSERT INTO `t_struts_student` VALUES ('12', '2', '12', '12', '男', '12');

3.2.pom.xml中添加内容

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
    
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency> 

3.3.application.yml中添加内容

pagehelper:
  reasonable: true
  supportMethodsArguments: true
  page-size-zero: true
  helper-dialect: mysql

3.4.entity中添加Clazz实体类

package com.zjzaki.spboot04.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.entity
 * @Date 2023-08-09 19:11:55
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Clazz {

    private Integer cid;

    private String cname;

    private String cteacher;

    private String pic;
}

3.5.mapper包中添加ClazzMapper

package com.zjzaki.spboot04.mapper;

import com.zjzaki.spboot04.entity.Clazz;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.mapper
 * @Date 2023-08-09 19:14:14
 */
@Repository
public interface ClazzMapper {

    int deleteByPrimaryKey(Integer cid);

    int insert(Clazz record);

    int insertSelective(Clazz record);

    Clazz selectByPrimaryKey(Integer cid);

    List<Clazz> listPager(Clazz clazz);

    List<Map> listMapPager(Clazz clazz);

    int updateByPrimaryKeySelective(Clazz record);

    int updateByPrimaryKey(Clazz record);
}

3.6.在resources中的mappers添加ClazzMapper.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.zjzaki.spboot04.mapper.ClazzMapper" >
    <resultMap id="BaseResultMap" type="com.zjzaki.spboot04.entity.Clazz" >
        <constructor >
            <idArg column="cid" jdbcType="INTEGER" javaType="java.lang.Integer" />
            <arg column="cname" jdbcType="VARCHAR" javaType="java.lang.String" />
            <arg column="cteacher" jdbcType="VARCHAR" javaType="java.lang.String" />
            <arg column="pic" jdbcType="VARCHAR" javaType="java.lang.String" />
        </constructor>
    </resultMap>
    <sql id="Base_Column_List" >
        cid, cname, cteacher, pic
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
        select
        <include refid="Base_Column_List" />
        from t_struts_class
        where cid = #{cid,jdbcType=INTEGER}
    </select>

    <select id="listMapPager" resultType="java.util.Map" parameterType="com.zjzaki.spboot04.entity.Clazz" >
        select
        <include refid="Base_Column_List" />
        from t_struts_class
        <where>
            <if test="cname != null and cname != ''">
                and cname like CONCAT('%',#{cname},'%')
            </if>
            <if test="cid != null and cid != ''">
                and cid = #{cid}
            </if>
        </where>
    </select>

    <select id="listPager" resultType="Clazz" parameterType="Clazz" >
        select
        <include refid="Base_Column_List" />
        from t_struts_class
        <where>
            <if test="cname != null and cname != ''">
                and cname like CONCAT('%',#{cname},'%')
            </if>
            <if test="cid != null and cid != ''">
                and cid = #{cid}
            </if>
        </where>
    </select>

    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
        delete from t_struts_class
        where cid = #{cid,jdbcType=INTEGER}
    </delete>
    <insert id="insert" parameterType="Clazz" >
        insert into t_struts_class (cid, cname, cteacher,
                                    pic)
        values (#{cid,jdbcType=INTEGER}, #{cname,jdbcType=VARCHAR}, #{cteacher,jdbcType=VARCHAR},
                #{pic,jdbcType=VARCHAR})
    </insert>
    <insert id="insertSelective" parameterType="Clazz" >
        insert into t_struts_class
        <trim prefix="(" suffix=")" suffixOverrides="," >
            <if test="cid != null" >
                cid,
            </if>
            <if test="cname != null" >
                cname,
            </if>
            <if test="cteacher != null" >
                cteacher,
            </if>
            <if test="pic != null" >
                pic,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
            <if test="cid != null" >
                #{cid,jdbcType=INTEGER},
            </if>
            <if test="cname != null" >
                #{cname,jdbcType=VARCHAR},
            </if>
            <if test="cteacher != null" >
                #{cteacher,jdbcType=VARCHAR},
            </if>
            <if test="pic != null" >
                #{pic,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="Clazz" >
        update t_struts_class
        <set >
            <if test="cname != null" >
                cname = #{cname,jdbcType=VARCHAR},
            </if>
            <if test="cteacher != null" >
                cteacher = #{cteacher,jdbcType=VARCHAR},
            </if>
            <if test="pic != null" >
                pic = #{pic,jdbcType=VARCHAR},
            </if>
        </set>
        where cid = #{cid,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="Clazz" >
        update t_struts_class
        set cname = #{cname,jdbcType=VARCHAR},
            cteacher = #{cteacher,jdbcType=VARCHAR},
            pic = #{pic,jdbcType=VARCHAR}
        where cid = #{cid,jdbcType=INTEGER}
    </update>
</mapper>

3.6.新建utils包, 添加PageBean和StringUtils

pageBean

package com.zjzaki.spboot04.utils;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

/**
 * 分页工具类
 *
 */
public class PageBean {

  private int page = 1;// 页码

  private int rows = 10;// 页大小

  private int total = 0;// 总记录数

  private boolean pagination = true;// 是否分页
  
  private String url; //保存上一次请求的URL
  
  private Map<String,String[]> paramMap = new HashMap<>();// 保存上一次请求的参数
  
  /**
   * 初始化pagebean的,保存上一次请求的重要参数
   * @param req
   */
  public void setRequest(HttpServletRequest req) {
//    1.1 需要保存上一次请求的URL
    this.setUrl(req.getRequestURL().toString());
//    1.2 需要保存上一次请求的参数  bname、price
    this.setParamMap(req.getParameterMap());
//    1.3 需要保存上一次请求的分页设置  pagination
    this.setPagination(req.getParameter("pagination"));
//    1.4 需要保存上一次请求的展示条目数
    this.setRows(req.getParameter("rows"));
//    1.5  初始化请求的页码 page
    this.setPage(req.getParameter("page"));
  }
  
  public void setPage(String page) {
    if(StringUtils.isNotBlank(page))
      this.setPage(Integer.valueOf(page));
  }

  public void setRows(String rows) {
    if(StringUtils.isNotBlank(rows))
      this.setRows(Integer.valueOf(rows));
  }

  public void setPagination(String pagination) {
//    只有在前台jsp填写了pagination=false,才代表不分页
    if(StringUtils.isNotBlank(pagination))
      this.setPagination(!"false".equals(pagination));
  }


  public String getUrl() {
    return url;
  }

  public void setUrl(String url) {
    this.url = url;
  }

  public Map<String, String[]> getParamMap() {
    return paramMap;
  }

  public void setParamMap(Map<String, String[]> paramMap) {
    this.paramMap = paramMap;
  }



  public PageBean() {
    super();
  }

  public int getPage() {
    return page;
  }

  public void setPage(int page) {
    this.page = page;
  }

  public int getRows() {
    return rows;
  }

  public void setRows(int rows) {
    this.rows = rows;
  }

  public int getTotal() {
    return total;
  }

  public void setTotal(int total) {
    this.total = total;
  }

  public void setTotal(String total) {
    this.total = Integer.parseInt(total);
  }

  public boolean isPagination() {
    return pagination;
  }

  public void setPagination(boolean pagination) {
    this.pagination = pagination;
  }

  /**
   * 获得起始记录的下标
   * 
   * @return
   */
  public int getStartIndex() {
    return (this.page - 1) * this.rows;
  }
  
  /**
   * 最大页
   * @return
   */
  public int maxPage() {
//    total % rows == 0 ? total / rows : total / rows +1
    return this.total % this.rows == 0 ? this.total / this.rows : this.total / this.rows + 1;
  }
  
  /**
   * 下一页
   * @return
   */
  public int nextPage() {
//    如果当前页小于最大页,那就下一页为当前页+1;如果不小于,说明当前页就是最大页,那就无需+1
    return this.page < this.maxPage() ? this.page + 1 : this.page;
  }
  
  /**
   * 上一页
   * @return
   */
  public int previousPage() {
    return this.page > 1 ? this.page - 1 : this.page;
  }

  @Override
  public String toString() {
    return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
  }

}

StringUtils

package com.zjzaki.spboot04.utils;

public class StringUtils {
  // 私有的构造方法,保护此类不能在外部实例化
  private StringUtils() {
  }

  /**
   * 如果字符串等于null或去空格后等于"",则返回true,否则返回false
   * 
   * @param s
   * @return
   */
  public static boolean isBlank(String s) {
    boolean b = false;
    if (null == s || s.trim().equals("")) {
      b = true;
    }
    return b;
  }
  
  /**
   * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
   * 
   * @param s
   * @return
   */
  public static boolean isNotBlank(String s) {
    return !isBlank(s);
  }

}

3.7.biz包下新建ClazzBiz接口

package com.zjzaki.spboot04.biz;

import com.zjzaki.spboot04.entity.Clazz;
import com.zjzaki.spboot04.utils.PageBean;

import java.util.List;
import java.util.Map;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.biz
 * @Date 2023-08-09 19:22:35
 */
public interface ClazzBiz {
    int deleteByPrimaryKey(Integer cid);

    int insert(Clazz record);

    int insertSelective(Clazz record);

    Clazz selectByPrimaryKey(Integer cid);

    int updateByPrimaryKeySelective(Clazz record);

    int updateByPrimaryKey(Clazz record);

    List<Clazz> listPager(Clazz clazz, PageBean pageBean);
    List<Map> listMapPager(Clazz clazz, PageBean pageBean);
}

3.8.biz包下新建impl包,创建ClazzBizImpl

package com.zjzaki.spboot04.biz.impl;

import com.zjzaki.spboot04.biz.ClazzBiz;
import com.zjzaki.spboot04.entity.Clazz;
import com.zjzaki.spboot04.mapper.ClazzMapper;
import com.zjzaki.spboot04.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.biz.impl
 * @Date 2023-08-09 19:25:55
 */
@Service
public class ClazzBizImpl implements ClazzBiz {
    @Autowired
    private ClazzMapper clazzMapper;

    @Override
    public int deleteByPrimaryKey(Integer cid) {
        System.out.println("不做任何操作...");
        return clazzMapper.deleteByPrimaryKey(cid);
    }

    @Override
    public int insert(Clazz record) {
        return clazzMapper.insert(record);
    }

    @Override
    public int insertSelective(Clazz record) {
        return clazzMapper.insertSelective(record);
    }

    @Override
    public Clazz selectByPrimaryKey(Integer cid) {
        return clazzMapper.selectByPrimaryKey(cid);
    }

    @Override
    public int updateByPrimaryKeySelective(Clazz record) {
        return clazzMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(Clazz record) {
        return clazzMapper.updateByPrimaryKey(record);
    }

    @Override
    public List<Clazz> listPager(Clazz clazz, PageBean pageBean) {
        return clazzMapper.listPager(clazz);
    }

    @Override
    public List<Map> listMapPager(Clazz clazz, PageBean pageBean) {
        if (true)
            throw new RuntimeException("查询班级信息异常,异常存在于ClazzBizImpl.list。。。。");
        return clazzMapper.listMapPager(clazz);
    }
}

3.9.controller包中添加ClazzController

package com.zjzaki.spboot04.controller;

import com.zjzaki.spboot04.biz.ClazzBiz;
import com.zjzaki.spboot04.entity.Clazz;
import com.zjzaki.spboot04.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.controller
 * @Date 2023-08-09 19:28:09
 */
@Controller
@RequestMapping("/clz")
public class ClazzController {

    @Autowired
    private ClazzBiz clazzBiz;

    @RequestMapping("/list")
    public String list(Clazz clazz, HttpServletRequest request) {
        System.out.println("我添加了 新的代码,终于不重启了....");
        PageBean pageBean = new PageBean();
        pageBean.setRequest(request);
        List<Clazz> lst = this.clazzBiz.listPager(clazz, pageBean);

        String pagestr = PageFreemarker.toHTML(pageBean);
        request.setAttribute("lst", lst);
        request.setAttribute("pageBean", pageBean);
        request.setAttribute("pagestr", pagestr);
        return "clz/clzList";
    }

    @RequestMapping("/toEdit")
    public String toEdit(Clazz clazz, HttpServletRequest request) {
        Integer cid = clazz.getCid();
        //传递的id代表了修改,没传代表新增
        if (cid != null) {
            List<Clazz> lst = this.clazzBiz.listPager(clazz, null);
            request.setAttribute("b", lst.get(0));
        }
        return "clz/clzEdit";
    }

    @RequestMapping("/add")
    public String add(Clazz clazz) {
        this.clazzBiz.insertSelective(clazz);
        return "redirect:/clz/list";
    }

    @RequestMapping("/edit")
    public String edit(Clazz clazz) {
        this.clazzBiz.updateByPrimaryKeySelective(clazz);
        return "redirect:/clz/list";
    }

    @RequestMapping("/del")
    public String del(Clazz clazz) {
        this.clazzBiz.deleteByPrimaryKey(clazz.getCid());
        return "redirect:/clz/list";
    }
}

3.10.utils中添加PageFreemarker

package com.zjzaki.spboot04.utils;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.utils
 * @Date 2023-08-09 19:29:45
 */
public class PageFreemarker {

    public static String toHTML(PageBean pageBean) {
        StringBuffer sb = new StringBuffer();
        //隐藏的form表单---这个就是上一次请求下次重新发的奥义所在
        //上一次请求的URL
        sb.append("<form action='" + pageBean.getUrl() + "' id='pageBeanForm' method='post'>");
        sb.append(" <input type='hidden' name='page'>");
        //上一次请求的参数
        Map<String, String[]> paramMap = pageBean.getParamMap();
        if (paramMap != null && paramMap.size() > 0) {
            Set<Entry<String, String[]>> entrySet = paramMap.entrySet();
            for (Entry<String, String[]> entry : entrySet) {
                //参数名
                String key = entry.getKey();
                //参数值
                for (String value : entry.getValue()) {
                    //上一次请求的参数,再一次组装成了新的Form表单
                    //注意:page参数每次都会提交,我们需要避免
                    if (!"page".equals(key)) {
                        sb.append(" <input type='hidden' name='" + key + "' value='" + value + "' >");
                    }
                }
            }
        }
        sb.append("</form>");

        //分页条
        sb.append("<ul class='pagination justify-content-center'>");
        sb.append(" <li class='page-item " + (pageBean.getPage() == 1 ? "disabled" : "") + "'><a class='page-link'");
        sb.append(" href='javascript:gotoPage(1)'>首页</a></li>");
        sb.append(" <li class='page-item " + (pageBean.getPage() == 1 ? "disabled" : "") + "'><a class='page-link'");
        sb.append(" href='javascript:gotoPage(" + pageBean.previousPage() + ")'>&lt;</a></li>");// less than 小于号
        //sb.append(" <li class='page-item'><a class='page-link' href='#'>1</a></li>");
        //sb.append(" <li class='page-item'><a class='page-link' href='#'>2</a></li>");
        sb.append(" <li class='page-item active'><a class='page-link' href='#'>" + pageBean.getPage() + "</a></li>");
        sb.append(" <li class='page-item " + (pageBean.getPage() == pageBean.maxPage() ? "disabled" : "") + "'><a class='page-link' href='javascript:gotoPage(" + pageBean.nextPage() + ")'>&gt;</a></li>");
        sb.append(" <li class='page-item " + (pageBean.getPage() == pageBean.maxPage() ? "disabled" : "") + "'><a class='page-link' href='javascript:gotoPage(" + pageBean.maxPage() + ")'>尾页</a></li>");
        sb.append(" <li class='page-item go-input'><b>到第</b><input class='page-link'");
        sb.append(" type='text' id='skipPage' name='' /><b>页</b></li>");
        sb.append(" <li class='page-item go'><a class='page-link'");
        sb.append(" href='javascript:skipPage()'>确定</a></li>");
        sb.append(" <li class='page-item'><b>共" + pageBean.getTotal() + "条</b></li>");
        sb.append("</ul>");

        //分页执行的JS代码
        sb.append("<script type='text/javascript'>");
        sb.append(" function gotoPage(page) {");
        sb.append("   document.getElementById('pageBeanForm').page.value = page;");
        sb.append("   document.getElementById('pageBeanForm').submit();");
        sb.append(" }");
        sb.append(" function skipPage() {");
        sb.append("   var page = document.getElementById('skipPage').value;");
        sb.append("   if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > " + pageBean.maxPage() + ") {");
        sb.append("     alert('请输入1~" + pageBean.maxPage() + "的数字');");
        sb.append("     return;");
        sb.append("   }");
        sb.append("   gotoPage(page);");
        sb.append(" }");
        sb.append("</script>");

        return sb.toString();
    }
}

3.11.新建aspect包,在aspect包下添加PagerAspect

package com.zjzaki.spboot04.aspect;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zjzaki.spboot04.utils.PageBean;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Author zjzaki
 * @Package com.zjzaki.spboot04.aspect
 * @Date 2023-08-09 19:34:53
 */
@Component
@Aspect
public class PagerAspect {
    /**
     * *:返回值类型
     * *..:无限包
     * *Service:以Service结尾接口名
     * *Pager:以Pager方法
     * 只要同时匹配上诉四个条件,就会被列为目标对象
     * 上述配置要生效,代理注解<aop:aspectj-autoproxy/>不能少
     *
     * @param args
     * @return
     * @throws Throwable
     */
    @Around("execution(* *..*Biz.*Pager(..))")
    public Object invoke(ProceedingJoinPoint args) throws Throwable {
        Object[] params = args.getArgs();
        PageBean pageBean = null;
        for (Object param : params) {
            if (param instanceof PageBean) {
                pageBean = (PageBean) param;
                break;
            }
        }

        if (pageBean != null && pageBean.isPaginatio())
            PageHelper.startPage(pageBean.getPage(), pageBean.getRows());

        //执行目标方法
        Object list = args.proceed(params);

        if (null != pageBean && pageBean.isPagination()) {
            PageInfo pageInfo = new PageInfo((List) list);
            pageBean.setTotal(pageInfo.getTotal() + "");
        }
        return list;
    }
}

3.12.templates中添加clz目录,并添加clzList.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link
            href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"
            rel="stylesheet">
    <script
            src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
    <title>班级列表</title>
    <style type="text/css">
        .page-item input {
            padding: 0;
            width: 40px;
            height: 100%;
            text-align: center;
            margin: 0 6px;
        }

        .page-item input, .page-item b {
            line-height: 38px;
            float: left;
            font-weight: 400;
        }

        .page-item.go-input {
            margin: 0 10px;
        }
    </style>
</head>
<body>
<#include "/common.ftl">
<form class="form-inline"
      action="${ctx }/clz/list" method="post">
    <div class="form-group mb-2">
        <input type="text" class="form-control-plaintext" name="cname"
               placeholder="请输入班级名称">
    </div>
    <button type="submit" class="btn btn-primary mb-2">查询</button>
    <a class="btn btn-primary mb-2" href="${ctx }/clz/toEdit">新增</a>
</form>

<table class="table table-striped bg-success">
    <thead>
    <tr>
        <th scope="col">ID</th>
        <th scope="col">班级名称</th>
        <th scope="col">指导老师</th>
        <th scope="col">操作</th>
    </tr>
    </thead>
    <tbody>
    <#list lst as b>
        <tr>
            <td>${b.cid }</td>
            <td>${b.cname !}</td>
            <td>${b.cteacher !}</td>
            <td>
                <a href="${ctx }/clz/toEdit?cid=${b.cid}">修改</a>
                <a href="${ctx }/clz/del?cid=${b.cid}">删除</a>
            </td>
        </tr>
    </#list>
    </tbody>
</table>
<#--jsp是借助助手类,而这里是Freemarker,没有jsp相关依赖-->
${pagestr !}
</body>
</html>

3.13.添加clzEdit.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>班级的编辑界面</title>
</head>
<body>
<#include "/common.ftl">
<#if b??>
    <form action="${ctx }/clz/edit" method="post">
        cid:<input type="text" name="cid" value="${b.cid !}"><br>
        cname:<input type="text" name="cname" value="${b.cname !}"><br>
        cteacher:<input type="text" name="cteacher" value="${b.cteacher !}"><br>
        <input type="submit">
    </form>
<#else>
    <form action="${ctx }/clz/add" method="post">
        cid:<input type="text" name="cid" value=""><br>
        cname:<input type="text" name="cname" value=""><br>
        cteacher:<input type="text" name="cteacher" value=""><br>
        <input type="submit">
    </form>
</#if>
</body>
</html>

3.14.application.xml

#新增内容
server:
  port: 8080
  servlet:
    context-path: /spboot04

3.15.修改Spboot04Application

package com.zjzaki.spboot04;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.zjzaki.spboot04.mapper")
@SpringBootApplication
public class Spboot04Application {

    public static void main(String[] args) {
        SpringApplication.run(Spboot04Application.class, args);
    }
}

3.16.重启项目—测试

目录
相关文章
|
2月前
|
开发框架 负载均衡 Java
当热门技术负载均衡遇上 Spring Boot,开发者的梦想与挑战在此碰撞,你准备好了吗?
【8月更文挑战第29天】在互联网应用开发中,负载均衡至关重要,可避免单服务器过载导致性能下降或崩溃。Spring Boot 作为流行框架,提供了强大的负载均衡支持,通过合理分配请求至多台服务器,提升系统可用性与可靠性,优化资源利用。本文通过示例展示了如何在 Spring Boot 中配置负载均衡,包括添加依赖、创建负载均衡的 `RestTemplate` 实例及服务接口调用等步骤,帮助开发者构建高效、稳定的应用。随着业务扩展,掌握负载均衡技术将愈发关键。
48 6
|
6天前
|
存储 缓存 Java
在Spring Boot中使用缓存的技术解析
通过利用Spring Boot中的缓存支持,开发者可以轻松地实现高效和可扩展的缓存策略,进而提升应用的性能和用户体验。Spring Boot的声明式缓存抽象和对多种缓存技术的支持,使得集成和使用缓存变得前所未有的简单。无论是在开发新应用还是优化现有应用,合理地使用缓存都是提高性能的有效手段。
13 1
|
2月前
|
缓存 NoSQL Java
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
Spring Cache 是 Spring 提供的简易缓存方案,支持本地与 Redis 缓存。通过添加 `spring-boot-starter-data-redis` 和 `spring-boot-starter-cache` 依赖,并使用 `@EnableCaching` 开启缓存功能。JetCache 由阿里开源,功能更丰富,支持多级缓存和异步 API,通过引入 `jetcache-starter-redis` 依赖并配置 YAML 文件启用。Layering Cache 则提供分层缓存机制,需引入 `layering-cache-starter` 依赖并使用特定注解实现缓存逻辑。
349 1
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
|
2月前
|
NoSQL JavaScript 前端开发
SpringBoot+Vue实现校园二手系统。前后端分离技术【完整功能介绍+实现详情+源码】
文章介绍了如何使用SpringBoot和Vue实现一个校园二手系统,采用前后端分离技术。系统具备完整的功能,包括客户端和管理员端的界面设计、个人信息管理、商品浏览和交易、订单处理、公告发布等。技术栈包括Vue框架、ElementUI、SpringBoot、Mybatis-plus和Redis。文章还提供了部分源代码,展示了前后端的请求接口和Redis验证码功能实现,以及系统重构和模块化设计的一些思考。
SpringBoot+Vue实现校园二手系统。前后端分离技术【完整功能介绍+实现详情+源码】
|
2月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
66 0
|
2月前
|
Java 前端开发 Spring
技术融合新潮流!Vaadin携手Spring Boot、React、Angular,引领Web开发变革,你准备好了吗?
【8月更文挑战第31天】本文探讨了Vaadin与Spring Boot、React及Angular等主流技术栈的最佳融合实践。Vaadin作为现代Java Web框架,与其他技术栈结合能更好地满足复杂应用需求。文中通过示例代码展示了如何在Spring Boot项目中集成Vaadin,以及如何在Vaadin项目中使用React和Angular组件,充分发挥各技术栈的优势,提升开发效率和用户体验。开发者可根据具体需求选择合适的技术组合。
35 0
|
2月前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
34 0
|
2月前
|
XML Java 决策智能
拥抱智能决策新纪元!Spring Boot携手LiteFlow规则引擎,让复杂业务处理如丝般顺滑,引领技术潮流!
【8月更文挑战第29天】LiteFlow是一款专为Java应用设计的轻量级规则引擎,支持条件、循环、分支等多种规则类型,具有组件化设计和高度可扩展性。通过自定义规则和事件监听,它可以显著提升代码的可维护性和可重用性。本文将详细介绍如何在Spring Boot项目中整合LiteFlow,并通过实际案例演示其强大功能。主要步骤包括:添加依赖、配置参数、定义组件及流程,并通过API触发执行。借助LiteFlow,复杂业务逻辑处理变得更加灵活高效。
54 0
|
2月前
|
Java BI API
SpringBoot + POI-TL:高效生成Word报表的技术盛宴
【8月更文挑战第22天】在日常的工作与学习中,文档处理特别是Word报表的自动生成,是许多项目中不可或缺的一环。传统的手工编辑Word文档不仅效率低下,还容易出错,特别是在需要批量生成包含动态数据的报告时,更是令人头疼不已。幸运的是,结合Spring Boot的简洁高效与POI-TL的强大功能,我们能够轻松实现Word报表的快速生成,既提升了工作效率,又保证了数据的准确性和报表的美观性。
175 0
|
2月前
|
存储 Java API
SpringBoot + MinIO 实现文件切片极速上传技术
【8月更文挑战第19天】在现代互联网应用中,文件上传是一个常见且重要的功能。然而,随着文件体积的增大,传统的文件上传方式往往面临效率低下、耗时过长等问题。为了提升大文件上传的速度和效率,我们可以采用文件切片上传技术,并结合SpringBoot和MinIO来实现这一功能。
151 0
下一篇
无影云桌面