SpringBoot基础

1.介绍

SpringBoot是为了简化Spring应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性 让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的 搭建出一个 WEB 工程

未接触SpringBoot之前,搭建一个普通的WEB工程往往需要花费30分钟左右,如果遇到点奇葩的问题耽搁的 时间会更长一点,但自从用了SpringBoot后,真正体会到什么叫分分钟搭建一个WEB,让我拥有更多的时间 跟我的小伙伴们唠嗑了。使用SpringBoot后发现一切是如此的简单(还记得被JAR包,xml支配的恐惧吗,如 今都可以说 good bye) 在传统的一些框架中(SSH、SSM、Servlet/JSP) 虽然功能很强大但是配置起来太麻烦了,相比python或者 php ,Java就略显臃肿,主要问题集中在两点:

1. 复杂的配置文件: 项目之间各种配置文件铺天盖地,在开发的过程中占用了大量的时间,并且需要做这些配置文件进行维护, 整个项目感觉特别复杂,并且Java代码和配置文件之间的切换开发,给程序人员带来很大的负担。

1. 各种依赖比较混乱: 主要问题就是版本冲突,不同技术的版本需要我们知道哪些版本存在冲突问题,一旦使用错误就需要重新再 去下载库进行依赖。

而Spring Boot简化了基于Spring的应用开发,只需要一个”run”就创建了一个独立的、生产级别的Spring应 用,Spring boot为Spring平台及第三方提供了开箱即用的设置(默认设置的包就是启动器starter),这样我们 就可以简单的开始。Spring Boot主张,用最少的配置做更多的事。如果我们创建一个Java应用,并使用java -jar启动,就能得到一个生产级别的web工程。

特点:

创建独立的 Spring 应用程序

直接嵌入Tomcat、Jetty或Undertow(无需部署WAR文件)

提供自以为是的“入门”依赖项以简化您的构建配置

尽可能自动配置 Spring 和 3rd 方库

提供生产就绪功能,例如指标、运行状况检查和外部化配置

完全不需要代码生成,也不需要 XML 配置 SpringBoot = Spring+SpringMVC

2. 构建SpringBoot项目

 运行项目


前后台交互

自定义Banner

SpringBoot启动的时候我们可以看到如下内容,这一块其实是可以自定义的哦,而且在 2.X 版本中,它支持 的格式从文本扩展到**banner.txt、banner.jpg、banner.gif、banner.jpeg等等,只需要在resouces**目 录下添加指定命名的文件即可

查看SpringBoot默认提供的Bean

手动注入bean 

//注入一个bean

@Bean

public Student student(){ return new Student("张三"); }

关于starter

stater 参赛人、发令员

Spring Boot 中的starter 只是把我们某一模块,比如web 开发时所需要的所有JAR 包打包好给我们而已。不 过它的厉害之处在于,能自动把配置文件搞好,不用我们手动配置。

spring-boot-starter-web spring-boot-starter-parent 这是 Spring Boot 的父级依赖,这样当前的项目就是 Spring Boot 项目了。

spring-boot-starter-parent 是一 个特殊的 starter。

功能 1:默认依赖配置(绝对兼容) 它用来提供相关的 Maven 默认依赖。使用它之后,常用的包依赖可以省去 version 标签,当我们搭建web 应用的时候,

可以像下面这样添加spring-boot-starter-web依赖:

 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

 功能 2:默认环境配置(绝对兼容) 默认使用Java8,可添加以下配置修改版本 默认使用UTF-8编码,可添加以下配置修改编码 等...

<properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
    </properties>

 功能 3:资源过滤

识别默认配置文件

<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
</resource>

过滤打包内容(打包的时候把 src/main/resources 下所有文件都打包到包中)

<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>

3. YAML文件

1、什么是 YAML ?

  • YAML(YAML Ain't Markup Language),一种数据序列化格式。
  • 这种格式的配置文件近些年逐渐进入市场,并开始占据主导地位。

2、优点

  • 较 xml 类型和 properties 类型相比,更容易阅读,结构也更加的清晰。
  • 容易与脚本语言交互。
  • 以数据为核心,重数据轻格式,轻格式并不是说可以不遵守格式,只是格式更加随性一些。

3、扩展名

  • 扩展名有两种,无论是那个扩展名,都是 YAML 格式的配置文件,拥有 YAML 的属性。
    • .yml ,这种扩展名更加主流一些
    • yam.l

语法规则 

1. 大小写敏感

2. 使用缩进表示层级关系

3. 缩进时不允许使用Tab键,只允许使用空格。

4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

5. 可以使用 "-小写字母" 或 "_小写字母"来 代替 "大写字母",如 userName 与 user-name ,user_name 含 义是一样的

6. key: value 格式书写 key 后面跟着冒号,再后面跟着一个空格,然后是值 ${basedir}/src/main/resources true **/application*.yml **/application*.yaml **/application*.properties 1 2 3 4 5 6 7 8 9 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA 1 2 3 4 5 6 7 8

7. 注释使用#.

数据类型

YAML 支持的数据结构有三种

1. 普通的值(数字,字符串,布尔) 2. 对象、Map (属性和值) (键值对) 3. 数组 (List、Set)

4. SpringBoot日志配置

Spring Boot内部采用的是Commons Logging进行日志记录,但在底层为**Java Util Logging+Log4J2、 Logback**等日志框架提供了默认配置 。 Java 虽然有很多可用的日志框架,但请不要担心,一般来说,使用 SpringBoot 默认的 Logback 就可以了。

日志级别拓展log4j

log4j定义了很全的日志级别,分别是:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、ALL,一 共8个级别的log,它们的优先级顺序为:OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL。

但是除去一些不常用的日志级别(如OFF、FATAL、TRACE、ALL)。其实,我们一般经常使用ERROR、 WARN、INFO、DEBUG这四种级别。而Log4j也建议我们使用四个级别,优先级从高到低分别是ERROR、 WARN、INFO、DEBUG。通过在这里定义的级别,可以控制到应用程序中相应级别的日志信息的开关。比 如在这里定义了INFO级别, 则应用程序中所有DEBUG级别的日志信息将不被打印出来。而优先级高的将被打印出来。项目上生产环境时 候一定得把debug的日志级别重新调为warn或者更高,避免产生大量日志。

1. OFF:最高等级的,用于关闭所有日志记录。

2. FATAL:指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别 你可以直接停止程序了。

3. ERROR:指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出 太多的日志,可以使用这个级别。

4. WARN:表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示

。 5. INFO:消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这 个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。

6. DEBUG:指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信 息。

7. TRACE:跟踪日志,日志消息的粒度太细,很低的日志级别,一般不会使用。

8. ALL:最低等级的,用于打开所有日志记录

日志输出

SpringBoot默认为我们输出的日志级别为INFO、WARN、ERROR,如需要输出更多日志的时候,可以通过 以下方式开启

命令模式配置: java -jar app.jar --debug=true , 这种命令会被SpringBoot解析,且优先级最高

资源文件配置:application.yml配置debug=true即可。该配置只对 嵌入式容器、Spring、Hibernate生效, 我们自己的项目想要输出DEBUG需要额外配置(配置规则:logging.level.=)

logging:
  level:
        org.springframework: info
        com.xja: info #建议:info 或者 warn

文件保存

默认情况下,SpringBoot仅将日志输出到控制台,不会写入到日志文件中去。如果除了控制台输出之外还想 写日志文件,则需要在application.properties设置logging.file或logging.path属性。 logging: level: org.springframework: info com.xja: info

#建议:info 或者 warn 1 2 3 4 logging.file:将日志写入到指定的文件中,默认为相对路径,可以设置成绝对路径

logging.path:将名为spring.log写入到指定的文件夹中,如(/var/log)

日志文件在达到10MB时进行切割,产生一个新的日志文件(如:spring.1.log、spring.2.log),新的日志依 旧输出到spring.log中去,默认情况下会记录ERROR、WARN、INFO级别消息。 logging.file.max-size:限制日志文件大小

logging.file.max-history:限制日志保留天数

logging:
  level:
        org.springframework: info
        com.xja: info #建议:info 或者 warn
  file:
        #path: D://日志
        name: D://日志/boot2.txt
# 如果颜色消失,配置这个
spring:
    output:
        ansi:
        enabled: always

关于五颜六色的插件:Grep Console

5. 单元测试

添加依赖

添加spring-boot-starter-test测试依赖启动器 在项目的pom.xml文件中添加spring-boot-starter-test测试依赖启动器,示例代码如下。 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>

编写单元测试类

在项目中添加测试依赖启动器后,可以编写Spring Boot项目中相关方法对应的单元测试。 如果是使用Spring Initializr方式搭建的Spring Boot项目,会在src.test.java测试目录下自动创建与项目主程 序启动类对应的单元测试类。

package edu.xja;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class CargoApplicationTests {

    @Test
    void contextLoads() {
    }
@Test
    void c(){
    System.out.println("sss");
}
}

6. JdbcTemplate

关于SpringData介绍

Spring Framework对数据库的操作在JDBC上面做了深层次的封装,通过依赖注入功能,可以将 DataSource 注册到JdbcTemplate之中,使我们可以轻易的完成对象关系映射,并有助于规避常见的错误,在 SpringBoot中我们可以很轻松的使用它。

特点:

速度快,对比其它的ORM框架而言,JDBC的方式无异于是最快的

配置简单,Spring自家出品,几乎没有额外配置

学习成本低,毕竟JDBC是基础知识,JdbcTemplate更像是一个DBUtils

6.1 整合JdbcTemplate

在 pom.xml 中添加对 JdbcTemplate 的依赖

<dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
   </dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
</dependencies>

在 application.properties 中添加如下配置。值得注意的是,SpringBoot默认会自动配置 DataSource , 它将优先采用 HikariCP 连接池,如果没有该依赖的情况则选取 tomcat-jdbc ,如果前两者都不可用最后选 取 Commons DBCP2 。通过**spring.datasource.type属性可以指定其它种类的连接池**

# 数据源
spring:
    datasource:
        url: jdbc:mysql:///boot?useUnicode=true&characterEncoding=UTF-8
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password:

6.2 案例测试

实体类

package edu.xja.pojo;

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Category {
    private Integer id;


    private String name;
}

dao

package edu.xja.dao;


import edu.xja.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;


import java.util.List;

@Repository
public class CategoryDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    /**
     * Category表添加
     * @param category
     * @return
     */
    public int add02(Category category) {
        String sql="insert into category value(?,?)";
        int i=jdbcTemplate.update(sql,category.getId(),category.getName());
        return i;
    }
    /**
     * Category表删除
     * @param i
     * @return
     */
    public int del02(int i) {
        String sql="delete from category where id = ?";
        int i1=jdbcTemplate.update(sql,i);
        return i1;
    }
    /**
     * Category表修改
     * @param name
     * @param id
     * @return
     */
    public int update02(String name, int id) {
        String sql="update category set name=? where id=?";
        int i=jdbcTemplate.update(sql,name,id);
        return i;
    }
    /**
     * Category表查询所有
     * @return
     */
    public List<Category> queryCategory() {
        String sql="select * from category";
        List<Category> list=jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Category.class));
        return list;
    }


}

service

package edu.xja.service;

import edu.xja.pojo.Cargo;
import edu.xja.pojo.Category;

import java.util.Date;
import java.util.List;

public interface CargoService {
    /**
     *货物表增加
     * @param cargo
     * @return
     *
     */
    int insert(Cargo cargo);

    /**
     *货物表删除
     * @param i
     * @return
     *
     */
    int del(int i);

    /**
     *货物表修改
     * @param name
     * @param id
     * @return
     *
     */
    int update(String name, int id);

    /**
     *货物表查询
     * @return
     *
     */
    List<Cargo> query();

    /**
     * 根据name模糊查询
     * @param name
     * @return
     */
    List<Cargo> queryName(String name);

    /**
     * 根据时间模糊查询
     * @param date1
     * @return
     */
    List<Cargo> queryTime(Date date1);
}

test

package edu.xja;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sun.deploy.security.ruleset.RuleSetParser;
import edu.xja.pojo.Cargo;
import edu.xja.pojo.Category;
import edu.xja.service.CargoService;

import edu.xja.service.CategoryService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

@SpringBootTest
public class CargoTest {
    
    @Autowired
    private CategoryService categoryService;
   

    @Test
    /**
     * Category表添加
     * @param category
     * @return
     */
    public void add02() {
        Category category = new Category(4, "格力");
        int i = categoryService.add(category);
        System.out.println(i);
    }

    @Test
    /**
     * Category表删除
     * @param i
     * @return
     */
    public void del02() {
        int i = categoryService.del02(4);
        System.out.println(i);
    }

    @Test
    /**
     * Category表修改
     * @param name
     * @param id
     * @return
     */
    public void update02() {
        int i = categoryService.update02("金属", 4);
        System.out.println(i);
    }

    @Test
    /**
     * Category表查询所有
     * @return
     */
    public void queryCategory() {
        List<Category> list = categoryService.queryCategory();
        list.forEach(System.out::println);
    }
}

7. Thymeleaf模板

Thymeleaf是用来开发Web和独立环境项目的现代服务器端Java模板引擎。

Thymeleaf的主要目标是为您的开发工作流程带来优雅的自然模板 - HTML。可以在直接浏览器中正确显示, 并且可以作为静态原型,从而在开发团队中实现更强大的协作。

借助Spring Framework的模块,可以根据自己的喜好进行自由选择,可插拔功能组件,Thymeleaf是现代 HTML5 JVM Web开发的理想选择 - 尽管它可以做的更多。

Spring官方支持的服务的渲染模板中,并不包含jsp。而是Thymeleaf和Freemarker等,而Thymeleaf与 SpringMVC的视图技术,及SpringBoot的自动化配置集成非常完美,几乎没有任何成本,你只用关注 Thymeleaf的语法即可。

特点:

动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态 效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性, 所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静 态内容,使页面动态显示。

开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免 每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。

多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的 实现表单绑定、属性编辑器、国际化等功能。

·与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解 析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。

7.3.1 变量

我们先新建一个实体类:User

public class User {
String name;
int age;
User friend;// 对象类型属性
}

然后在模型中添加数据

@GetMapping("show2")
public String show2(Model model){
User user = new User();
user.setAge(21);
user.setName("Jack Chen");
user.setFriend(new User("李小龙", 30));
model.addAttribute("user", user);
return "show2";
}

语法说明: Thymeleaf通过 ${} 来获取model中的变量,注意这不是el表达式,而是ognl表达式,但是语法非常像。

示例: 我们在页面获取user数据:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户页面</title>
</head>
<body>
<div th:text="${user.name}"></div>
</body>
</html>

7.3.2 自定义变量

我们获取用户的所有信息,分别展示。

当数据量比较多的时候,频繁的写 user. 就会非常麻烦。 因此,Thymeleaf提供了自定义变量来解决:

示例:

<h2 th:object="${user}">
<p>Name: <span th:text="*{name}">Jack</span>.</p>
<p>Age: <span th:text="*{age}">21</span>.</p>
<p>friend: <span th:text="*{friend.name}">Rose</span>.</p>
</h2>

7.3.3 方法

 

7.3.4 字面值 

字符串字面值  使用一对 ' 引用的内容就是字符串字面值了:

数字字面值 数字不需要任何特殊语法, 写的什么就是什么,而且可以直接进行算术运算

布尔字面值 布尔类型的字面值是true或false:

7.3.5 拼接

字符串字面值需要用 '' ,拼接起来非常麻烦,Thymeleaf对此进行了简化,使用一对 | 即可:

<span th:text="|欢迎您:${user.name}|"></span>

7.3.6 运算

算术运算 支持的算术运算符: + - * / %

比较运算 支持的比较运算: > , < , >= and , < 不能直接使用,因为xml会解析为标签,要使用别名。 注意 == and != 不仅可以比较数值,类似于equals的功能。 可以使用的别名: gt (>), lt (=), le (<=), not (!). Also eq (==), neq/ne (!=).

条件运算 三元运算 三元运算符的三个部分:conditon ? then : else condition:条件 then:条件成立的结果 else:不成立的结果 其中的每一个部分都可以是Thymeleaf中的任意表达式。

默认值 有的时候,我们取一个值可能为空,这个时候需要做非空判断,可以使用 表达式 ?: 默认值 简 写:当前面的表达式值为null时,就会使用后面的默认值。 注意: ?: 之间没有空格。

7.3.7 循环

循环也是非常频繁使用的需求,我们使用 th:each 指令来完成: 假如有用户的集合:users在Context中

<tr th:each="user : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>

${users} 是要遍历的集合,

可以是以下类型: Iterable,实现了Iterable接口的类

Enumeration,枚举 Interator,

迭代器 Map,遍历得到的是Map.Entry Array

,数组及其它一切符合数组结果的对象,实现了Iterable接口的类 Enumeration,枚举 Interator,迭代器 Map,遍历得到的是Map.Entry Array,数组及其它一切符合数组结果的对象 在迭代的同时,我们也可以获取迭代的状态对象:

<tr th:each="user,stat : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>

stat对象包含以下属性:index,从0开始的角标 count,元素的个数,从1开始 size,总元素个数 current,当前遍历到的元素 even/odd,返回是否为奇偶,boolean值 first/last,返回是否为第一或最后,boolean值

7.3.8 逻辑判断

有了 if和else ,我们能实现一切功能^_^。 Thymeleaf中使用 th:if 或者 th:unless ,两者的意思恰好相反

如果表达式的值为true,则标签会渲染到页面,否则不进行渲染。 以下情况被认定为true:

表达式值为true 表达式值为非0数值 表达式值为非0字符 表达式值为字符串,但不是 "false" , "no" , "off" 表达式不是布尔、字符串、数字、字符中的任何一种

其它情况包括null都被认定为false

7.3.9 样式及脚本引入

<script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>
<script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>

8. 分页设计

package edu.xja.utils;

import lombok.Data;

import java.util.List;


@Data
public class PageInfo<T> {

    /* 当前页 */
    private int pageNum;

    /* 上一页 */
    private int prePage;

    /* 下一页 */
    private int nextPage;

    /* 总页数 */
    private int pages;

    /* 总条数 */
    private int total;

    /* 每页多少条 */
    private int pageSize;

    /* 查询的起始索引 */
    private int startIndex;

    private List<T> list;


    public PageInfo(int pageNum, int total, int pageSize) {

        this.pageNum = pageNum;
        this.total = total;
        this.pageSize = pageSize;

        this.prePage = this.pageNum  > 1 ? this.pageNum - 1 : 1;

        /* 总条数 / 每页多少条   */
        this.pages = (this.total / this.pageSize) + (this.total % this.pageSize != 0?1:0);

        /* 下一页 */
        this.nextPage = this.pageNum >= this.pages ? this.pages : this.pageNum + 1;

        /* 起始索引 (当前页 -1 ) * pageSize  */
        this.startIndex = (this.pageNum - 1) * pageSize;
    }
}

html

 <script>
        $(function () {
            $("#pageSize").change(function () {
                let v = $(this).val();
                location = "/cargo/list?pageSize="+ v;
            })
        })
    </script>
总条数:<span th:text="${pageInfo.total}"></span>,
    <span th:text="${pageInfo.pageNum}"></span>/<span th:text="${pageInfo.pages}"></span>
    <a href="/cargo/list?pageNum=1">首页</a>
    <a th:href="|/cargo/list?pageNum=${pageInfo.prePage}&pageSize=${pageInfo.pageSize}|">上一页</a>
    <a th:href="|/cargo/list?pageNum=${pageInfo.nextPage}&pageSize=${pageInfo.pageSize}|">下一页</a>
    <a th:href="|/cargo/list?pageNum=${pageInfo.pages}&pageSize=${pageInfo.pageSize}|">尾页</a>
    <select id="pageSize">
        <option value="2" th:selected="${pageInfo.pageSize}==2">2</option>
        <option value="5" th:selected="${pageInfo.pageSize}==5">5</option>
        <option value="10" th:selected="${pageInfo.pageSize}==10">10</option>
        <option value="20" th:selected="${pageInfo.pageSize}==20">20</option>
    </select>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值