Spring Boot框架入门(四)

Spring Boot简介

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。


代码实现

开发一个Spring Boot应用可以从官网提供的地址http://start.spring.io/下载基本框架导入IDE进行开发或者在IDE中下载插件后直接新建项目即可。下面的Demo采用第二种方法。

在eclipse的商店下载Spring插件STS(Spring Tool Suite)后新建Spring Starter Project。

使Spring Boot支持JSP视图

Springboot的默认视图支持是Thymeleaf,要让它支持JSP视图,需做少许修改

pom.xml

    <dependencies>
        <!-- 包含mvc、aop等jar资源 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
         <!-- 内置Tomcat服务器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>  
        </dependency>
        <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>3.8.1</version>
              <scope>test</scope>
        </dependency>
         <!-- jstl表达式支持 -->
        <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>jstl</artifactId>
         </dependency>
        <!-- tomcat支持解析jsp视图.-->
        <dependency>
               <groupId>org.apache.tomcat.embed</groupId>
               <artifactId>tomcat-embed-jasper</artifactId>   
        </dependency>     
    </dependencies>

application.properties

#视图重定向jsp文件的位置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

HelloController.java

@Controller
public class HelloController {
  
    //URL映射
    @RequestMapping("/hello")
    public String hello(Model m) {
        //属性绑定
        m.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));
        //定向视图文件
        return "hello";
    }
}

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
Hi JSP. 现在时间是  ${now}

这样一个简单的Spring Boot应用就完成了,但是每次修改代码之后又得重新运行才能生效,非常不利于开发调试,为了解决这个问题,需加入热部署功能。

只需在pom.xml中加入以下依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
        </dependency>

错误处理

当有异常发生时,我们需要做一些逻辑处理,以不影响用户体验,比如定向到一个固定页面,下面模仿一个异常。

修改HelloController.java

@Controller
public class HelloController {
  
    @RequestMapping("/hello")
    public String hello(Model m) throws Exception {
        m.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));
        //抛出异常
        if(true){
            throw new Exception("some exception");
        }
        return "hello";
    }
     
}

新建GlobalExceptionHandler.java类捕捉异常

@ControllerAdvice  //  定义全局异常处理类
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class) // 声明异常处理方法
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("errorPage");
        return mav;
    }
 
}

errorPage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<div style="width:500px;border:1px solid lightgray;margin:200px auto;padding:80px">
 
系统 出现了异常,异常原因是:
    ${exception}
    <br><br>
    出现异常的地址是:
    ${url}
    </div>

修改端口与上下文路径

application.properties

server.port=8888
server.context-path=/test

多配置文件

根据不同的环境使用 不同的配置文件

3个配置文件:

核心配置文件:application.properties

开发环境用的配置文件:application-dev.properties

生产环境用的配置文件:application-pro.properties

这样就可以通过application.properties里的spring.profiles.active 灵活地来切换使用哪个环境了

application.properties

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.profiles.active=pro

application-dev.properties

server.port=8080
server.context-path=/test

application-pro.properties

server.port=80
server.context-path=/

另一种配置文件

Spring Boot除了支持properties格式的文件,还支持yml格式的文件

application.properties(properties式写法)

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

application.yml(yml式写法)

spring:
    mvc:
        view:
            prefix: /WEB-INF/jsp
            suffix: .jsp

在application.yml 文件书写注意:

1. 不同“等级” 用冒号隔开

2. 次等级的前面是空格,不能使用制表符(tab)

3. 冒号之后如果有值,那么冒号和值之间至少有一个空格,不能紧贴着

JPA支持

JPA(Java Persistence API)是Sun官方提出的Java持久化规范,用来方便大家操作数据库。

真正干活的可能是Hibernate,TopLink等等实现了JPA规范的不同厂商,默认是Hibernate。

创建数据库、表,添加数据

create database springboot;
use springboot;
CREATE TABLE category_ (
  id int(11) NOT NULL AUTO_INCREMENT,
  name varchar(30),
  PRIMARY KEY (id)
) DEFAULT CHARSET=UTF8;
insert into category_ values(null,'category 1');
insert into category_ values(null,'category 2');
insert into category_ values(null,'category 3');
insert into category_ values(null,'category 4');

application.properties

添加数据库信息

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update

pom.xml

添加对mysql和jpa的支持

        <!-- mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
 
        <!-- jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency> 

新建Category.java实体类

@Entity
@Table(name = "category_")
public class Category {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id") 
    private int id;
     
    @Column(name = "name")
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     
}

新建CategoryDAO.java接口类

JpaRepository 这个父接口提供了CRUD,,分页等等一系列的操作方法。

继承了JpaRepository,并且提供泛型<Category,Integer>表示这个是针对Category类的DAO,Integer表示主键是Integer类型。

public interface CategoryDAO extends JpaRepository<Category,Integer>{
 
}

新建CategoryController.java类

@Controller
public class CategoryController {
    @Autowired CategoryDAO categoryDAO;
     
    @RequestMapping("/listCategory")
    public String listCategory(Model m) throws Exception {
        List<Category> cs=categoryDAO.findAll();
         
        m.addAttribute("cs", cs);
         
        return "listCategory";
    }
     
}

listCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
   
<table align='center' border='1' cellspacing='0'>
    <tr>
        <td>id</td>
        <td>name</td>
    </tr>
    <c:forEach items="${cs}" var="c" varStatus="st">
        <tr>
            <td>${c.id}</td>
            <td>${c.name}</td>
                
        </tr>
    </c:forEach>
</table>
JPA分页

修改CategoryController.java类

@Controller
public class CategoryController {
    @Autowired CategoryDAO categoryDAO;
     
    //查询与分页,参数start(当前页数),参数size(每页条数)
    @RequestMapping("/listCategory")
    public String listCategory(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
        start = start<0?0:start;
         
        //根据id倒序排列
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        //分页参数设置并创建分页对象
        Pageable pageable = new PageRequest(start, size, sort);
        //CategoryDAO根据这个分页对象获取结果page.
        Page<Category> page =categoryDAO.findAll(pageable);
         
        System.out.println(page.getNumber());
        System.out.println(page.getNumberOfElements());
        System.out.println(page.getSize());
        System.out.println(page.getTotalElements());
        System.out.println(page.getTotalPages());
         
        m.addAttribute("page", page);
         
        return "listCategory";
    }
 
    //增
    @RequestMapping("/addCategory")
    public String addCategory(Category c) throws Exception {
        categoryDAO.save(c);
        return "redirect:listCategory";
    }
    //删
    @RequestMapping("/deleteCategory")
    public String deleteCategory(Category c) throws Exception {
        categoryDAO.delete(c);
        return "redirect:listCategory";
    }
    //改
    @RequestMapping("/updateCategory")
    public String updateCategory(Category c) throws Exception {
        categoryDAO.save(c);
        return "redirect:listCategory";
    }
    //编辑修改页
    @RequestMapping("/editCategory")
    public String ediitCategory(int id,Model m) throws Exception {
        Category c= categoryDAO.getOne(id);
        m.addAttribute("c", c);
        return "editCategory";
    }
}

listCategory.jsp

在分页的时候通过page.number获取当前页面,page.totalPages获取总页面数。

page.getContent会返回一个泛型是Category的集合。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
   
<div align="center">
 
</div>
 
<div style="width:500px;margin:20px auto;text-align: center">
    <table align='center' border='1' cellspacing='0'>
        <tr>
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${page.content}" var="c" varStatus="st">
            <tr>
                <td>${c.id}</td>
                <td>${c.name}</td>
                <td><a href="editCategory?id=${c.id}">编辑</a></td>
                <td><a href="deleteCategory?id=${c.id}">删除</a></td>
            </tr>
        </c:forEach>
         
    </table>
    <br>
    <div>
                <a href="?start=0">[首  页]</a>
            <a href="?start=${page.number-1}">[上一页]</a>
            <a href="?start=${page.number+1}">[下一页]</a>
            <a href="?start=${page.totalPages-1}">[末  页]</a>
    </div>
    <br>
    <form action="addCategory" method="post">
     
    name: <input name="name"> <br>
    <button type="submit">提交</button>
     
    </form>
</div>

editCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>
 
<div style="margin:0px auto; width:500px">
 
<form action="updateCategory" method="post">
 
name: <input name="name" value="${c.name}"> <br>
 
<input name="id" type="hidden" value="${c.id}"> 
<button type="submit">提交</button>
 
</form>
</div>

Spring Boot + Mybatis

注解版

修改pom.xml

增加对Mybatis的支持

		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

Category.java实体类

public class Category {
  
    private int id;
      
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
      
}

CategoryMapper.java接口类

@Mapper  //表示这是一个Mybatis Mapper接口
public interface CategoryMapper {
 
    @Select("select * from category_ ")
    List<Category> findAll();
 
}

CategoryController.java类

@Controller
public class CategoryController {
    @Autowired CategoryMapper categoryMapper;
      
    @RequestMapping("/listCategory")
    public String listCategory(Model m) throws Exception {
        List<Category> cs=categoryMapper.findAll();
          
        m.addAttribute("cs", cs);
          
        return "listCategory";
    }
      
}

listCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
   
<table align='center' border='1' cellspacing='0'>
    <tr>
        <td>id</td>
        <td>name</td>
    </tr>
    <c:forEach items="${cs}" var="c" varStatus="st">
        <tr>
            <td>${c.id}</td>
            <td>${c.name}</td>
                
        </tr>
    </c:forEach>
</table>
XML版

修改CategoryMapper.java

将注解去掉

@Mapper
public interface CategoryMapper {
 
    List<Category> findAll();
 
}

新建Category.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.how2java.springboot.mapper.CategoryMapper">
        <select id="findAll" resultType="Category">
            select * from category_ 
        </select>    
    </mapper>

application.properties

指明从哪加载xml配置文件

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 
mybatis.mapper-locations=classpath:com/how2java/springboot/mapper/*.xml
mybatis.type-aliases-package=com.example.springboot.pojo
Mybatis分页


pom.xml

增加对分页插件PageHelper的支持

        <!-- pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>

新建PageHelperConfig.java类

//表示此类是配置类
@Configuration
public class PageHelperConfig {

    //启动PageHelper这个拦截器
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        //将RowBounds第一个参数offset当成pageNum页码使用
        p.setProperty("offsetAsPageNum", "true");
        //使用RowBounds分页会进行count查询
        p.setProperty("rowBoundsWithCount", "true");
        //启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

CategoryMapper.java

修改CategoryMapper,增加CRUD方法的支持

@Mapper
public interface CategoryMapper {
 
    @Select("select * from category_ ")
    List<Category> findAll();
     
    @Insert(" insert into category_ ( name ) values (#{name}) ") 
    public int save(Category category);  
     
    @Delete(" delete from category_ where id= #{id} ") 
    public void delete(int id); 
         
    @Select("select * from category_ where id= #{id} ") 
    public Category get(int id); 
       
    @Update("update category_ set name=#{name} where id=#{id} ") 
    public int update(Category category);  
 
}

CategoryController.java

为CategoryController添加: 增加、删除、获取、修改映射

@Controller
public class CategoryController {
    @Autowired CategoryMapper categoryMapper;
      
    @RequestMapping("/addCategory")
    public String listCategory(Category c) throws Exception {
        categoryMapper.save(c);
        return "redirect:listCategory";
    }
    @RequestMapping("/deleteCategory")
    public String deleteCategory(Category c) throws Exception {
        categoryMapper.delete(c.getId());
        return "redirect:listCategory";
    }
    @RequestMapping("/updateCategory")
    public String updateCategory(Category c) throws Exception {
        categoryMapper.update(c);
        return "redirect:listCategory";
    }
    @RequestMapping("/editCategory")
    public String listCategory(int id,Model m) throws Exception {
        Category c= categoryMapper.get(id);
        m.addAttribute("c", c);
        return "editCategory";
    }
     
    @RequestMapping("/listCategory")
    public String listCategory(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
        PageHelper.startPage(start,size,"id desc");
        List<Category> cs=categoryMapper.findAll();
        PageInfo<Category> page = new PageInfo<>(cs);
        m.addAttribute("page", page);         
        return "listCategory";
    }
     
}

listCategory.jsp

通过page.getList遍历当前页面的Category对象。

在分页的时候通过page.pageNum获取当前页面,page.pages获取总页面数。

注:page.getList会返回一个泛型是Category的集合。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    
<div align="center">
  
</div>
  
<div style="width:500px;margin:20px auto;text-align: center">
    <table align='center' border='1' cellspacing='0'>
        <tr>
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${page.list}" var="c" varStatus="st">
            <tr>
                <td>${c.id}</td>
                <td>${c.name}</td>
                <td><a href="editCategory?id=${c.id}">编辑</a></td>
                <td><a href="deleteCategory?id=${c.id}">删除</a></td>
            </tr>
        </c:forEach>
          
    </table>
    <br>
    <div>
                <a href="?start=1">[首  页]</a>
            <a href="?start=${page.pageNum-1}">[上一页]</a>
            <a href="?start=${page.pageNum+1}">[下一页]</a>
            <a href="?start=${page.pages}">[末  页]</a>
    </div>
    <br>
    <form action="addCategory" method="post">
      
    name: <input name="name"> <br>
    <button type="submit">提交</button>
      
    </form>
</div>

editCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>
  
<div style="margin:0px auto; width:500px">
  
<form action="updateCategory" method="post">
  
name: <input name="name" value="${c.name}"> <br>
  
<input name="id" type="hidden" value="${c.id}">
<button type="submit">提交</button>
  
</form>
</div>

上传文件


uploadPage.jsp

1. method="post" 是必须的

2. enctype="multipart/form-data" 是必须的,表示提交二进制文件

3. name="file" 是必须的,和后续服务端对应

4. accept="image/*" 表示只选择图

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 
<form action="upload" method="post" enctype="multipart/form-data">
  选择图片:<input type="file" name="file" accept="image/*" /> <br>
  <input type="submit" value="上传">
</form>

 UploadController.java

@Controller
public class UploadController {
  
    @RequestMapping("/uploadPage")
    public String uploadPage() {
        return "uploadPage";
    }
    
    //@RequestParam("file") MultipartFile file(上传的文件)
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(HttpServletRequest req, @RequestParam("file") MultipartFile file,Model m) {
            try {
                //根据时间戳创建新的文件名,这样即便是第二次上传相同名称的文件,也不会把第一次的文件覆盖了
                String fileName = System.currentTimeMillis()+file.getOriginalFilename();
                //通过req.getServletContext().getRealPath("") 获取当前项目的真实路径,然后拼接前面的文件名
                String destFileName=req.getServletContext().getRealPath("")+"uploaded"+File.separator+fileName;
                //第一次运行的时候,这个文件所在的目录往往是不存在的,这里需要创建一下目录 
                File destFile = new File(destFileName);
                destFile.getParentFile().mkdirs();
                //把浏览器上传的文件复制到指定的位置
                file.transferTo(destFile);
                //把文件名放在model里,以便后续显示用甀
                m.addAttribute("fileName",fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return "上传失败," + e.getMessage();
            } catch (IOException e) {
                e.printStackTrace();
                return "上传失败," + e.getMessage();
            }
             
            return "showImg";
    }    
}

application.properties

设置上传文件的大小,默认是1m

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb

Spring Boot默认视图Thymeleaf

什么是 Thymeleaf?

thymeleaf 跟 JSP 一样,就是运行之后,就得到纯 HTML了。 区别在与,不运行之前, thymeleaf 也是 纯 html ...所以 thymeleaf 不需要 服务端的支持,就能够被以 html 的方式打开,这样就方便前端人员独立设计与调试, jsp 就不行了, 不启动服务器 jsp 都没法运行出结果来。

pom.xml

添加Thymeleaf支持

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</
</dependency>
基本语法
1.声明当前文件是 thymeleaf, 里面可以用th开头的属性
<html xmlns:th="http://www.thymeleaf.org">

2.用OGNL的写法${name}把 name 的值显示在当前 p里,使用的是th开头的属性: th:text

<p th:text="${name}" >name</p>

3.字符串拼写。 两种方式,一种是用加号,一种是在前后放上 ||, 显然第二种方式可读性更好。

<p th:text="'Hello! ' + ${name} + '!'" >hello world</p>
<p th:text="|Hello! ${name}!|" >hello world</p>

4.通过 th:href="@{/static/css/style.css}" 和 th:src="@{/static/js/thymeleaf.js}" 引入 css 和 js 文件

<link rel="stylesheet" type="text/css" media="all" href="../../webapp/static/css/style.css" th:href="@{/static/css/style.css}"/>
<script type="text/javascript" src="../../webapp/static/js/thymeleaf.js" th:src="@{/static/js/thymeleaf.js}"></script>

5.转义与非转义的html

<p th:text="${htmlContent}" ></p>
<p th:utext="${htmlContent}" ></p>

6.获取对象属性的两种方式,这里可以直接调用方法了

<p th:text="${currentProduct.name}" ></p>
<p th:text="${currentProduct.getName()}" ></p>

7.使用 *{} 方式显示当前对象的属性

<p th:text="*{name}" ></p>

8.算数运算

<p th:text="${currentProduct.price+999}" ></p>

9.用 th:fragment 标记代码片段

<footer th:fragment="footer1">  
   <p >All Rights Reserved</p>
</footer>
<footer th:fragment="footer2(start,now)">  
   <p th:text="|${start} - ${now} All Rights Reserved|"></p>
</footer>

用th:replace调用

<div th:replace="include::footer1" ></div>
<div th:replace="include::footer2(2015,2018)" ></div>

除了th:replace, 还可以用th:insert, 

区别:th:insert :保留自己的主标签,保留th:fragment的主标签。

th:replace :不要自己的主标签,保留th:fragment的主标签。

10.Thymeleaf 的条件判断是 通过 th:if 来做的

<p th:if="${testBoolean}" >如果testBoolean 是 true ,本句话就会显示</p>

取反可以用not, 或者用th:unless.

<p th:if="${not testBoolean}" >取反 ,所以如果testBoolean 是 true ,本句话就不会显示</p>
<p th:unless="${testBoolean}" >unless 等同于上一句,所以如果testBoolean 是 true ,本句话就不会显示</p>

除此之外,三元表达式也比较常见

<p th:text="${testBoolean}?'当testBoolean为真的时候,显示本句话,这是用三相表达式做的':''" ></p>

不只是布尔值的 true 和 false, th:if 表达式返回其他值时也会被认为是 true 或 false,规则如下:

boolean 类型并且值是 true, 返回 true

数值类型并且值不是 0, 返回 true

字符类型(Char)并且值不是 0, 返回 true

String 类型并且值不是 "false", "off", "no", 返回 true

不是 boolean, 数值, 字符, String 的其他类型, 返回 true

值是 null, 返回 false

11.使用 th:each 遍历

        <tbody>
            <tr th:each="p: ${ps}">
                <td th:text="${p.id}"></td>
                <td th:text="${p.name}"></td>
                <td th:text="${p.price}"></td>
            </tr>
        </tbody>

带状态的遍历

th:each="p,status: ${ps}

status里还包含了如下信息:

index 属性, 0开始的索引值

count 属性, 1开始的索引值

size 属性, 集合内元素的总量

current 属性, 当前的迭代对象

even/odd 属性, boolean 类型的, 用来判断是否是偶数个还是奇数个

first 属性, boolean 类型, 是否是第一个

last 属性, boolean 类型, 是否是最后一个

用3元表达式判断奇偶

th:class="${status.even}?'even':'odd'" 

还是用 th:each,但是放在option元素上,就可以遍历出多个下拉框出来了。

<select size="3">
        <option th:each="p:${ps}" th:value="${p.id}"     th:selected="${p.id==currentProduct.id}"    th:text="${p.name}" ></option>
    </select>

单选框也是同样的做法,其中 th:checked用于判断是否选中

<input name="product" type="radio" th:each="p:${ps}" th:value="${p.id}"  th:checked="${p.id==currentProduct.id}"     th:text="${p.name}"  />

12.内置工具

使用#dates这个内置工具进行格式化日期

<div class="showing date">
	<h2>格式化日期</h2>
	直接输出日期 ${now}:
	<p th:text="${now}"></p>
	默认格式化 ${#dates.format(now)}:
	<p th:text="${#dates.format(now)}"></p>
	自定义格式化 ${#dates.format(now,'yyyy-MM-dd HH:mm:ss')}:
	<p th:text="${#dates.format(now,'yyyy-MM-dd HH:mm:ss')}"></p>
</div>

像 #date 这样的 thymeleaf内置工具有很多种,一共有如下16种。

Execution Info
Messages
URIs/URLs
Conversions
Dates
Calendars
Numbers
Strings
Objects
Booleans
Arrays
Lists
Sets
Maps
Aggregates
IDs

猜你喜欢

转载自blog.csdn.net/The_ProgramLife/article/details/80928769
今日推荐