IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 骨灰级SSM 和spring boot大全(二) -> 正文阅读

[Java知识库]骨灰级SSM 和spring boot大全(二)

08_SpringBoot_整合PageHelper(掌握)

PageHelper插件

我们在正常的查询业务之中,只需要加上一行代码就可以实现分页的数据的封装处理

实现原理

PageHelper方法使用了静态的ThreadLocal参数,分页参数和线程是绑定的。内部流程是ThreadLocal中设置了分页参数(pageIndex,pageSize),之后在查询执行的时候,获取当线程中的分页参数,执行查询的时候通过拦截器在sql语句中添加分页参数,之后实现分页查询,查询结束后在 finally 语句中清除ThreadLocal中的查询参数

使用方法

1.调用PageHelper方法:PageHelper.startPage(pageNum, pageSize)

2. MyBatis 查询方法

注意:只要你可以保证在PageHelper方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为PageHelper在finally代码段中自动清除了ThreadLocal存储的对象。

MyBatis整合PageHelper插件,自行阅读即可

mybatis中pageHelper的配置使用_铛铛响的博客-CSDN博客

添加PageHelper启动器依赖

1.	<dependency>
2.	    <groupId>com.github.pagehelper</groupId>
3.	    <artifactId>pagehelper-spring-boot-starter</artifactId>
4.	    <version>1.2.12</version>
5.	</dependency>

EmpController

1.	package com.msb.controller;
2.	
3.	import com.msb.pojo.Emp;
4.	import com.msb.service.EmpService;
5.	import org.springframework.beans.factory.annotation.Autowired;
6.	import org.springframework.stereotype.Controller;
7.	import org.springframework.web.bind.annotation.PathVariable;
8.	import org.springframework.web.bind.annotation.RequestMapping;
9.	import org.springframework.web.bind.annotation.ResponseBody;
10.	
11.	import java.util.List;
12.	
13.	/**
14.	 * @Author: Ma HaiYang
15.	 * @Description: MircoMessage:Mark_7001
16.	 */
17.	@Controller
18.	@RequestMapping("/emp")
19.	public class EmpController {
20.	
21.	    @Autowired
22.	    private EmpService empService;
23.	
24.	    @RequestMapping("/findByPage/{pageNum}/{pageSize}")
25.	    @ResponseBody
26.	    public List<Emp> findByPage(@PathVariable("pageNum") Integer pageNum,@PathVariable("pageSize") Integer pageSize){
27.	        return empService.findByPage(pageNum,pageSize);
28.	    }
29.	}
30.	

Service层代码编写

1.	package com.msb.service.impl;
2.	
3.	import com.github.pagehelper.Page;
4.	import com.github.pagehelper.PageHelper;
5.	import com.github.pagehelper.PageInfo;
6.	import com.msb.mapper.EmpMapper;
7.	import com.msb.pojo.Emp;
8.	import com.msb.service.EmpService;
9.	import org.springframework.beans.factory.annotation.Autowired;
10.	import org.springframework.stereotype.Service;
11.	
12.	import java.util.List;
13.	
14.	/**
15.	 * @Author: Ma HaiYang
16.	 * @Description: MircoMessage:Mark_7001
17.	 */
18.	@Service
19.	public class EmpServiceImpl implements EmpService {
20.	    @Autowired
21.	    private EmpMapper empMapper;
22.	    @Override
23.	    public List<Emp> findByPage(Integer pageNum, Integer pageSize) {
24.	        Page<Emp> page = PageHelper.startPage(pageNum, pageSize);
25.	        List<Emp> list =empMapper.findAll();
26.	
27.	        // 方式1
28.	        System.out.println("当前页:"+page.getPageNum());
29.	        System.out.println("总页数"+page.getPages());
30.	        System.out.println("页大小:"+page.getPageSize());
31.	        System.out.println("总记录数:"+page.getTotal());
32.	        System.out.println("当前页数据"+page.getResult());
33.	
34.	        // 方式2
35.	        PageInfo<Emp> pi =new PageInfo<>(list);
36.	        System.out.println("当前页"+pi.getPageNum());
37.	        System.out.println("总页数"+pi.getPages());
38.	        System.out.println("页大小"+pi.getSize());
39.	        System.out.println("总记录数"+pi.getTotal());
40.	        System.out.println("当前页数据"+pi.getList());
41.	
42.	        return list;
43.	    }
44.	}

PageInfo对象和Page对象的区别

Page和PageInfo_程序员^晓洋的博客-CSDN博客_page和pageinfo

?

?

09_SpringBoot_整合Druid((掌握)

Druid是由阿里巴巴推出的数据库连接池。它结合了C3P0、DBCP、PROXOOL等数据库连接池的优点。之所以从众多数据库连接池中脱颖而出,还有一个重要的原因就是它包含控制台,很方便的帮助我们实现对于sql执行的监控。

添加依赖

<dependency>
2.	            <groupId>com.alibaba</groupId>
3.	            <artifactId>druid-spring-boot-starter</artifactId>
4.	            <version>1.1.10</version>
5.	        </dependency>

修改配置文件application.yml

1.	spring:
2.	  datasource:
3.	    # 使用阿里的Druid连接池
4.	    type: com.alibaba.druid.pool.DruidDataSource
5.	    driver-class-name: com.mysql.cj.jdbc.Driver
6.	    # 填写你数据库的url、登录名、密码和数据库名
7.	    url: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
8.	    username: root
9.	    password: root
10.	  druid:
11.	    # 连接池的配置信息
12.	    # 初始化大小,最小,最大
13.	    initial-size: 5
14.	    min-idle: 5
15.	    maxActive: 20
16.	    # 配置获取连接等待超时的时间
17.	    maxWait: 60000
18.	    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
19.	    timeBetweenEvictionRunsMillis: 60000
20.	    # 配置一个连接在池中最小生存的时间,单位是毫秒
21.	    minEvictableIdleTimeMillis: 300000
22.	    validationQuery: SELECT 1
23.	    testWhileIdle: true
24.	    testOnBorrow: false
25.	    testOnReturn: false
26.	    # 打开PSCache,并且指定每个连接上PSCache的大小
27.	    poolPreparedStatements: true
28.	    maxPoolPreparedStatementPerConnectionSize: 20
29.	    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
30.	    filters: stat,wall,slf4j
31.	    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
32.	    connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
33.	    # 配置DruidStatFilter
34.	    web-stat-filter:
35.	      enabled: true
36.	      url-pattern: "/*"
37.	      exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
38.	    # 配置DruidStatViewServlet
39.	    stat-view-servlet:
40.	      url-pattern: "/druid/*"
41.	      # IP白名单(没有配置或者为空,则允许所有访问)
42.	      allow: 127.0.0.1,192.168.8.109
43.	      # IP黑名单 (存在共同时,deny优先于allow)
44.	      deny: 192.168.1.188
45.	      #  禁用HTML页面上的“Reset All”功能
46.	      reset-enable: false
47.	      # 登录名
48.	      login-username: admin
49.	      # 登录密码
50.	      login-password: 123456

代码测试

?

?访问监控页面

?

10_SpringBoot_整合JSP(了解)

添加依赖

<!--JSP依赖-->
2.	        <dependency>
3.	            <groupId>org.apache.tomcat.embed</groupId>
4.	            <artifactId>tomcat-embed-jasper</artifactId>
5.	            <scope>provided</scope>
6.	        </dependency>

添加webapps目录并设置目录

?

??

设置工作目录,如果在IDEA中项目结构为聚合工程。那么在运行jsp是需要指定路径。如果项目结构为独立项目则不需要。 ?

?

?在 yml配置文件中配置视图解析器参数

?

?在控制类中声明单元方法请求转发jsp资源

1.	package com.msb.controller;
2.	
3.	import org.springframework.stereotype.Controller;
4.	import org.springframework.web.bind.annotation.PathVariable;
5.	import org.springframework.web.bind.annotation.RequestMapping;
6.	
7.	/**
8.	 * @Author: Ma HaiYang
9.	 * @Description: MircoMessage:Mark_7001
10.	 */
11.	@Controller
12.	public class PageController {
13.	    @RequestMapping("/{uri}")
14.	    public String getPage(@PathVariable("uri") String uri){
15.	        return uri;
16.	    }
17.	}

11_SpringBoot_整合FreeMarker(熟悉)

1FreeMarker的简介

? ? FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

? ? FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据, 而在模板之外注意于要展示什么数据。

常用的java模板引擎还有哪些?

Jsp、Freemarker、Thymeleaf 、Velocity 等。

模板+数据模型=输出

freemarker并不关心数据的来源,只是根据模板的内容,将数据模型在模板中显示并输出文件(通常为html,也可以生成其它格式的文本文件)

freemarker作为springmvc一种视图格式,默认情况下SpringMVC支持freemarker视图格式。 需要创建Spring Boot+Freemarker工程用于测试模板。

2FreeMarker初次使用

导入依赖

 <!--freeMaker依赖-->
2.	        <dependency>
3.	            <groupId>org.springframework.boot</groupId>
4.	            <artifactId>spring-boot-starter-freemarker</artifactId>
5.	        </dependency>

创建controller

 @RequestMapping("/freemarker")
2.	    @Controller
3.	    public class FreemarkerController {
4.	        @RequestMapping("/show")
5.	        public String freemarker(Map<String, Object> map){
6.	            map.put("name","msb");
7.	           //返回模板文件名称
8.	            return "show";
9.	        }
10.	    }

通过查阅配置信息发现,默认前缀为 &apos;&apos; ,后缀为.ftlh,默认路径为templates

templates目录下创建模板文件

?

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	</head>
7.	<body>
8.	this is showftlh
9.	<br/>
10.	${name}
11.	<img src="img/a.jpg"></img>
12.	</body>
13.	</html>

3FreeMarker常用指令

A遍历List集合

1、注释,即<#‐‐和‐‐>,介于其之间的内容会被freemarker忽略

2、插值(Interpolation):即${..}部分,freemarker会用真实的值代替${..}

3、FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑。

4、文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容。

1.	@Controller
2.	public class FreemarkerController {
3.	    @Autowired
4.	    private EmpService empService;
5.	
6.	    @RequestMapping("/showEmp")
7.	    public ModelAndView testList(){
8.	        ModelAndView mv =new ModelAndView();
9.	        List<Emp> list =empService.findAll();
10.	        mv.addObject("empList", list);
11.	        mv.setViewName("showEmp");
12.	        return mv;
13.	    }
14.	}
15.	

页面代码

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	    <style type="text/css">
7.	        #empTable{
8.	            width: 80%;
9.	            border: 1px solid blue;
10.	            margin: 0px auto;
11.	        }
12.	        #empTable th,td{
13.	            border: 1px solid green;
14.	            text-align: center;
15.	        }
16.	
17.	    </style>
18.	</head>
19.	<body>
20.	
21.	<table id="empTable" cellpadding="0px" cellspacing="0px">
22.	    <tr>
23.	        <th>索引</th>
24.	        <th>工号</th>
25.	        <th>姓名</th>
26.	        <th>岗位</th>
27.	        <th>薪资</th>
28.	        <th>部门号</th>
29.	    </tr>
30.	    <#list empList as emp>
31.	        <tr>
32.	            <td>${emp_index}</td>
33.	            <td>${emp.empno}</td>
34.	            <td>${emp.ename}</td>
35.	            <td>${emp.job}</td>
36.	            <td>${emp.sal}</td>
37.	            <td>${emp.deptno}</td>
38.	        </tr>
39.	    </#list>
40.	
41.	
42.	</table>
43.	
44.	</body>
45.	</html>

说明: _index:得到循环的下标,使用方法是在stu后边加"_index",它的值是从0开始?

B遍历Map数据

遍历输出指定内容

controller

1.	@Controller
2.	public class FreemarkerController {
3.	    @Autowired
4.	    private EmpService empService;
5.	
6.	    @RequestMapping("/showEmpMap")
7.	    public ModelAndView testMap(){
8.	        ModelAndView mv =new ModelAndView();
9.	        List<Emp> list =empService.findAll();
10.	        Map<String,Emp> empMap =new HashMap<>();
11.	        for (Emp emp : list) {
12.	            empMap.put(emp.getEmpno().toString(), emp);
13.	        }
14.	
15.	        mv.addObject("empMap", empMap);
16.	        mv.setViewName("showEmpMap");
17.	        return mv;
18.	    }

页面

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	    <style type="text/css">
7.	        #empTable{
8.	            width: 80%;
9.	            border: 1px solid blue;
10.	            margin: 0px auto;
11.	        }
12.	        #empTable th,td{
13.	            border: 1px solid green;
14.	            text-align: center;
15.	        }
16.	
17.	    </style>
18.	</head>
19.	<body>
20.	
21.	输出7521员工信息:<br/>
22.	工号:${empMap['7521'].empno}<br/>
23.	姓名:${empMap['7521'].ename}<br/>
24.	岗位:${empMap['7521'].job}<br/>
25.	薪资:${empMap['7521'].sal}<br/>
26.	部门号:${empMap['7521'].deptno}<br/>
27.	<br/>
28.	遍历EmpMap
29.	
30.	<table id="empTable" cellpadding="0px" cellspacing="0px">
31.	    <tr>
32.	        <th>索引</th>
33.	        <th>工号</th>
34.	        <th>姓名</th>
35.	        <th>岗位</th>
36.	        <th>薪资</th>
37.	        <th>部门号</th>
38.	    </tr>
39.	    <#list empMap?keys as k>
40.	        <tr>
41.	            <td>${k_index}</td>
42.	            <td>${k}</td>
43.	            <td>${empMap[k].ename}</td>
44.	            <td>${empMap[k].job}</td>
45.	            <td>${empMap[k].sal}</td>
46.	            <td>${empMap[k].deptno}</td>
47.	        </tr>
48.	    </#list>
49.	
50.	
51.	</table>
52.	
53.	</body>
54.	</html>

FreeMarker在遍历map集合是,key必须是String

C ?if指令

if 指令即判断指令,是常用的FTL指令,freemarker在解析时遇到if会进行判断,条件为真则输出if中间的内容,否 则跳过内容不再输出。

if中支持的运算符

? ? a算数运算符 FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , %

? ? b逻辑运算符有如下几个: 逻辑与:&& 逻辑或:|| 逻辑非:! 逻辑运算符只能作用于布尔值,否则将产生错误

? ? c比较运算符有如下几个:

? ? ? ? ① =或者==:判断两个值是否相等.

? ? ? ? ② !=:判断两个值是否不等.

? ? ? ? ③ > 或者gt:判断左边值是否大于右边值

? ? ? ? ④ >=或者gte:判断左边值是否大于等于右边值

? ? ? ? ⑤ <或者lt:判断左边值是否小于右边值

? ? ? ? ⑥ <=或者lte:判断左边值是否小于等于右边值

注意:?=和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>

如何判断空值

1、判断某变量是否存在使用 “??” 用法为:variable??,如果该变量存在,返回true,否则返回false 例:为防止stus为空报错可以加上判断如下

2、缺失变量默认值使用 “!” 使用!要以指定一个默认值,当变量为空时显示默认值。例: ${name!&apos;&apos;}表示如果name为空显示空字符串。如果是嵌套对象则建议使用()括起来。

<#if empList??>
2.	        <#list empList as emp>
3.	            <tr <#if emp_index%2 ==0 > style="background-color: gray" </#if>>
4.	                <td>${emp_index}</td>
5.	                <td>${emp.empno}</td>
6.	                <td <#if emp.ename == 'KING'> style="color: aqua" </#if>>${emp.ename}</td>
7.	                <td>${emp.job}</td>
8.	                <td>${emp.mgr!'无'}</td>
9.	                <td <#if emp.sal gte 2000.0> style="color: red" </#if>>${emp.sal}</td>
10.	                <td>${emp.comm!'0'}</td>
11.	                <td>${emp.deptno}</td>
12.	            </tr>
13.	        </#list>
14.	    </#if>

4 内置函数

内建函数语法格式: 变量+?+函数名称

1、内建函数获取某个集合的大小

${集合名?size}

2、内建函数日期格式化

显示年月日: ? ? ? ? ${today?date}

显示时分秒: ? ? ?${today?time}

显示日期+时间:${today?datetime}

自定义格式化: ? ${today?string("yyyy年MM月")}

3、内建函数将json字符串转成对象

1.	<#assign text="{'bank':'工商银行','account':'10101920201920212'}" />
2.	<#assign data=text?eval />
3.	开户行:${data.bank} 账号:${data.account}

其中用到了 assign标签,assign的作用是定义一个变量。

页面

1.	员工人数:${empList?size}
2.	<table id="empTable" cellpadding="0px" cellspacing="0px">
3.	    <tr>
4.	        <th>索引</th>
5.	        <th>工号</th>
6.	        <th>姓名</th>
7.	        <th>岗位</th>
8.	        <th>上级</th>
9.	        <th>入职日期a</th>
10.	        <th>入职日期b</th>
11.	        <th>入职日期c</th>
12.	        <th>入职日期d</th>
13.	        <th>薪资</th>
14.	        <th>补助</th>
15.	        <th>部门号</th>
16.	    </tr>
17.	    <#if empList??>
18.	        <#list empList as emp>
19.	            <tr <#if emp_index%2 ==0 > style="background-color: gray" </#if>>
20.	                <td>${emp_index}</td>
21.	                <td>${emp.empno}</td>
22.	                <td <#if emp.ename == 'KING'> style="color: aqua" </#if>>${emp.ename}</td>
23.	                <td>${emp.job}</td>
24.	                <td>${emp.mgr!'无'}</td>
25.	                <td>${emp.hiredate?date}</td>
26.	                <td>${emp.hiredate?time}</td>
27.	                <td>${emp.hiredate?datetime}</td>
28.	                <td>${emp.hiredate?string("yyyy年MM月dd日")}</td>
29.	                <td <#if emp.sal gte 2000.0> style="color: red" </#if>>${emp.sal}</td>
30.	                <td>${emp.comm!'0'}</td>
31.	                <td>${emp.deptno}</td>
32.	            </tr>
33.	        </#list>
34.	    </#if>
35.	
36.	</table>

更多内置函数FreeMarker内置函数的用法_WO木子的博客-CSDN博客_freemarker lower_case?

12_SpringBoot_整合Thymeleaf(掌握)

Thymeleaf的主要目标是将优雅的自然模板带到开发工作流程中,并将HTML在浏览器中正确显示,并且可以作为静态原型,让开发团队能更容易地协作。Thymeleaf能够处理HTML,XML,JavaScript,CSS甚至纯文本。

? ? 长期以来,jsp在视图领域有非常重要的地位,随着时间的变迁,出现了一位新的挑战者:Thymeleaf,Thymeleaf是原生的,不依赖于标签库.它能够在接受原始HTML的地方进行编辑和渲染.因为它没有与Servelet规范耦合,因此Thymeleaf模板能进入jsp所无法涉足的领域。

? ? Thymeleaf在Spring Boot项目中放入到resources/templates中。这个文件夹中的内容是无法通过浏览器URL直接访问的(和WEB-INF效果一样),所有Thymeleaf页面必须先走控制器。

创建项目,准备配置文件及各层级代码

项目中添加依赖

1.	<dependencies>
2.	        <dependency>
3.	            <groupId>org.springframework.boot</groupId>
4.	            <artifactId>spring-boot-starter-web</artifactId>
5.	        </dependency>
6.	
7.	        <dependency>
8.	            <groupId>org.springframework.boot</groupId>
9.	            <artifactId>spring-boot-starter-test</artifactId>
10.	            <scope>test</scope>
11.	        </dependency>
12.	
13.	        <dependency>
14.	            <groupId>org.mybatis.spring.boot</groupId>
15.	            <artifactId>mybatis-spring-boot-starter</artifactId>
16.	            <version>2.1.3</version>
17.	        </dependency>
18.	        <dependency>
19.	            <groupId>mysql</groupId>
20.	            <artifactId>mysql-connector-java</artifactId>
21.	            <version>8.0.21</version>
22.	        </dependency>
23.	
24.	        <dependency>
25.	            <groupId>org.projectlombok</groupId>
26.	            <artifactId>lombok</artifactId>
27.	            <version>1.18.12</version>
28.	            <scope>provided</scope>
29.	        </dependency>
30.	
31.	
32.	        <dependency>
33.	            <groupId>com.alibaba</groupId>
34.	            <artifactId>druid-spring-boot-starter</artifactId>
35.	            <version>1.1.10</version>
36.	        </dependency>
37.	
38.	
39.	        <dependency>
40.	            <groupId>com.github.pagehelper</groupId>
41.	            <artifactId>pagehelper-spring-boot-starter</artifactId>
42.	            <version>1.2.12</version>
43.	        </dependency>
44.	
45.	        <dependency>
46.	            <groupId>org.springframework.boot</groupId>
47.	            <artifactId>spring-boot-starter-thymeleaf</artifactId>
48.	            <version>2.4.5</version>
49.	        </dependency>
50.	
51.	    </dependencies>

关于Thymeleaf默认配置

?

?在resources下新建templates文件夹。新建index.html

新建控制器

1.	package com.msb.controller;
2.	
3.	import org.springframework.stereotype.Controller;
4.	import org.springframework.web.bind.annotation.RequestMapping;
5.	
6.	/**
7.	 * @Author: Ma HaiYang
8.	 * @Description: MircoMessage:Mark_7001
9.	 */
10.	@Controller
11.	public class ThymeleafController {
12.	    @RequestMapping("showIndex")
13.	    public String showIndex(){
14.	        return "index";
15.	    }
16.	}

13_SpringBoot_Thymeleaf基础语法(掌握)

Thymeleaf通过标准变量表达式完成数据的展示和处理

1 标准变量表达式必须依赖标签,不能独立使用

2 标准变量表达式一般在开始标签中,以 th开头

3 语法为: <tag th:***="${key}" ? ></tag>

4 表达式中可以通过${}取出域中的值并放入标签的指定位置

5 ${}在这里不能单独使用,必须在 th:后面的双引号里使用

为了有提示,修改html页面中<html>标签为

1.	<html xmlns:th="http://www.thymeleaf.org" >

举例

1.	<input th:type="" th:text="${}" th:style="" th:id="" th:class=""  ... ... >

th:text属性

向HTML标签内部输出信息。

处理器 Controller

 @RequestMapping("showIndex")
2.	    public String  showIndex(Map<String,Object> map){
3.	        map.put("msg", "testMessage");
4.	        return "index";
5.	    }

页面代码

<!--向span双标签内部添加文本-->
2.	    <span th:text="pageMessage"></span> <br/>
3.	    <!--从域中根据参数名取出参数值放在双标签中-->
4.	    <span th:text="${msg}"></span>      <br/>

th:value

表单元素,设置HTML标签中表单元素value属性时使用。

 <!--向input标签中的value属性赋值-->
2.	    <input type="text"  th:value="pageMessage"/>
3.	    <!--从域中根据参数名取出参数值 向input标签中的value属性赋值-->
4.	    <input type="text"  th:value="${msg}"/>

th:if

1.	<span th:if="${name}!='张三'">会显示</span>

循环遍历.th:each

示例中u为迭代遍历。

th:each="u,i :${list}"?其中i表示迭代状态。

1,index:当前迭代器的索引 从0开始

2,count:当前迭代对象的计数 从1开始

3,size:被迭代对象的长度

4,even/odd:布尔值,当前循环是否是偶数/奇数 从0开始

5,first:布尔值,当前循环的是否是第一条,如果是返回true否则返回false

6,last:布尔值,当前循环的是否是最后一条,如果是则返回true否则返回false

controller代码

1.	@Controller
2.	public class ThymeleafController {
3.	
4.	    @Autowired
5.	    private EmpService empService;
6.	
7.	    @RequestMapping("/showEmp")
8.	    public String showEmp(Map<String, Object> map) {
9.	        List<Emp> empList = empService.findAll();
10.	        map.put("empList", empList);
11.	        map.put("emp", empList.get(0));
12.	        return "showEmp";
13.	    }

页面模板代码

1.	<!DOCTYPE html>
2.	<html lang="en" xmlns:th="http://www.thymeleaf.org">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	    <style type="text/css">
7.	        #empTable{
8.	            width: 80%;
9.	            border: 1px solid blue;
10.	            margin: 0px auto;
11.	        }
12.	        #empTable th,td{
13.	            border: 1px solid green;
14.	            text-align: center;
15.	        }
16.	    </style>
17.	</head>
18.	<body>
19.	展示单个员工信息:
20.	<span th:if="${emp}!=null">
21.	    工号:<span th:text="${emp.empno}"></span><br/>
22.	    姓名:<span th:text="${emp.ename}"></span><br/>
23.	    职务:<span th:text="${emp.job}"></span><br/>
24.	    上级:<span th:text="${emp.mgr}"></span><br/>
25.	    入职日期:<span th:text="${emp.hiredate}"></span><br/>
26.	    工资:<span th:text="${emp.sal}"></span><br/>
27.	    补助:<span th:text="${emp.comm}"></span><br/>
28.	    部门号:<span th:text="${emp.deptno}"></span><br/>
29.	</span>
30.	<hr/>
31.	<span  th:if="${empList}!=null">
32.	    <span  th:if="${empList.size()} ne 0">
33.	        工号:<span th:text="${empList[0].empno}"></span><br/>
34.	        姓名:<span th:text="${empList[0].ename}"></span><br/>
35.	        职务:<span th:text="${empList[0].job}"></span><br/>
36.	        上级:<span th:text="${empList[0].mgr}"></span><br/>
37.	        入职日期:<span th:text="${empList[0].hiredate}"></span><br/>
38.	        工资:<span th:text="${empList[0].sal}"></span><br/>
39.	        补助:<span th:text="${empList[0].comm}"></span><br/>
40.	        部门号:<span th:text="${empList[0].deptno}"></span><br/>
41.	    </span>
42.	</span>
43.	<table  id="empTable" cellpadding="0px" cellspacing="0px">
44.	    <tr>
45.	        <th>索引</th>
46.	        <th>序号</th>
47.	        <th>总人数</th>
48.	        <th>偶数索引?</th>
49.	        <th>奇数索引?</th>
50.	        <th>第一?</th>
51.	        <th>最后?</th>
52.	        <th>工号</th>
53.	        <th>姓名</th>
54.	        <th>职务</th>
55.	        <th>上级</th>
56.	        <th>入职日期</th>
57.	        <th>工资</th>
58.	        <th>补助</th>
59.	        <th>部门号</th>
60.	    </tr>
61.	    <tr th:each="emp,i:${empList}">
62.	        <td th:text="${i.index}"></td>
63.	        <td th:text="${i.count}"></td>
64.	        <td th:text="${i.size}"></td>
65.	        <td th:text="${i.odd}"></td>
66.	        <td th:text="${i.even}"></td>
67.	        <td th:text="${i.first}"></td>
68.	        <td th:text="${i.last}"></td>
69.	        <td th:text="${emp.empno}"></td>
70.	        <td th:text="${emp.ename}"></td>
71.	        <td th:text="${emp.job}"></td>
72.	        <td th:text="${emp.mgr}"></td>
73.	        <td th:text="${emp.hiredate}"></td>
74.	        <td th:text="${emp.sal}"></td>
75.	        <td th:text="${emp.comm}"></td>
76.	        <td th:text="${emp.deptno}"></td>
77.	    </tr>
78.	    
79.	</table>
80.	
81.	</body>
82.	</html>

页面效果

标准变量表达式运算符支持

标准变量表达式支持的运算符

算数运算符

算术运算:+ , - , * , / , %
1.	<span th:text="1+1"></span>
2.	<span th:text="'1'+1"></span>
3.	<span th:text="${emp.empno}+1"></span>
4.	<span th:text="${emp.empno+1}"></span>

关系运算符

 gt:     great than(大于)>
2 ge:    great equal(大于等于)>=
3 eq:    equal(等于)==
4 lt:    less than(小于)<
5 le:    less equal(小于等于)<=
6 ne:    not equal(不等于)!= 

逻辑运算符

&&? 或 and:? ?表示并且

||? 或? or? : 表示或者

1.	<div th:text="1>0 and 2<3"></div>
2.	<div th:text="1>0 and 2>3"></div>
3.	<div th:text="1>0 or 2<3"></div>
4.	<div th:text="1>0 or 2>3"></div>
5.	<hr/>
6.	<div th:text="${emp.sal ge 800}"></div>
7.	<div th:text="${emp.sal } ge 800"></div>
8.	<div th:text="${emp.sal ge 800} and ${emp.deptno eq 20}"></div>
9.	<div th:text="(${emp.sal }ge 800) or (${emp.deptno } ne 20)"></div>
10.	<div th:text="${emp.sal ge 800 or emp.deptno ne 20 }"></div>

在早期的thymeleaf模板引擎框架中 逻辑运算符要写在${}的外边,目前我们2.4.5版本中,可以写在${}里面

三目运算符

1.	<tr th:each="emp,i:${empList}" th:class="${i.odd}?a:b">

对空值作出处理

 <tr th:each="emp,i:${empList}" th:class="${i.odd}?a:b">
2.	        <td th:text="${i.index}"></td>
3.	        <td th:text="${i.count}"></td>
4.	        <td th:text="${i.size}"></td>
5.	        <td th:text="${i.odd}"></td>
6.	        <td th:text="${i.even}"></td>
7.	        <td th:text="${i.first}"></td>
8.	        <td th:text="${i.last}"></td>
9.	        <td th:text="${emp.empno}"></td>
10.	        <td th:text="${emp.ename}"></td>
11.	        <td th:text="${emp.job}"></td>
12.	        <td th:text="${emp.mgr} eq null ?老板:${emp.mgr}"></td>
13.	        <td th:text="${emp.hiredate}"></td>
14.	        <td th:text="${emp.sal}"></td>
15.	        <td th:text="${emp.comm} eq null ?0:${emp.comm}"></td>
16.	        <td th:text="${emp.deptno}"></td>
17.	    </tr>

th:href

设置href属性的。取值使用@{}取值

1.	<a th:href="@{/getParam(id=1,name='msb')}" >跳转</a>
2.	<!-- 获取作用域值-->
3.	<a th:href="@{/getParam(name=${stu.name},age=${stu.age})}">跳转二</a>

页面代码

 <tr th:each="emp,i:${empList}" th:class="${i.odd}?a:b">
2.	        <td th:text="${i.index}"></td>
3.	        <td th:text="${i.count}"></td>
4.	        <td th:text="${i.size}"></td>
5.	        <td th:text="${i.odd}"></td>
6.	        <td th:text="${i.even}"></td>
7.	        <td th:text="${i.first}"></td>
8.	        <td th:text="${i.last}"></td>
9.	        <td th:text="${emp.empno}"></td>
10.	        <td th:text="${emp.ename}"></td>
11.	        <td th:text="${emp.job}"></td>
12.	        <td th:text="${emp.mgr} eq null ?老板:${emp.mgr}"></td>
13.	        <td th:text="${emp.hiredate}"></td>
14.	        <td th:text="${emp.sal}"></td>
15.	        <td th:text="${emp.comm} eq null ?0:${emp.comm}"></td>
16.	        <td th:text="${emp.deptno}"></td>
17.	        <td>
18.	            <a th:href="@{/removeEmp(empno=${emp.empno},ename=${emp.ename})}">删除</a>
19.	        </td>
20.	    </tr>

后台controller处理器

1.	@Controller
2.	public class ThymeleafController {
3.	
4.	    @Autowired
5.	    private EmpService empService;
6.	
7.	    @RequestMapping("/showAllEmp")
8.	    public String showEmp(Map<String, Object> map) {
9.	        List<Emp> empList = empService.findAll();
10.	        map.put("empList", empList);
11.	        map.put("emp", empList.get(0));
12.	        return "showEmp";
13.	    }
14.	
15.	    @RequestMapping("/removeEmp")
16.	    public String removeEmp(Integer empno,String ename){
17.	        boolean success =empService.removeEmp(empno,ename);
18.	        return "redirect:showAllEmp";
19.	    }
20.	}

?service和mapper 略

th:onclick?

给元素绑定事件,单击事件并传递参数

写法1:仅仅支持数字和布尔类型参数的传递,字符串不支

1.	<a href="javascript:viod(0)"  th:onclick="'del('+${emp.empno}+')'">删除</a>

写法2:支持数字和文本类型的参数传递

1.	<a href="javascript:void(0)" th:onclick="delEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>

前端代码

1.	<table  id="empTable" cellpadding="0px" cellspacing="0px">
2.	    <tr>
3.	        <th>索引</th>
4.	        <th>序号</th>
5.	        <th>总人数</th>
6.	        <th>偶数索引?</th>
7.	        <th>奇数索引?</th>
8.	        <th>第一?</th>
9.	        <th>最后?</th>
10.	        <th>工号</th>
11.	        <th>姓名</th>
12.	        <th>职务</th>
13.	        <th>上级</th>
14.	        <th>入职日期</th>
15.	        <th>工资</th>
16.	        <th>补助</th>
17.	        <th>部门号</th>
18.	        <th>操作</th>
19.	    </tr>
20.	    <tr th:each="emp,i:${empList}" th:class="${i.odd}?a:b">
21.	        <td th:text="${i.index}"></td>
22.	        <td th:text="${i.count}"></td>
23.	        <td th:text="${i.size}"></td>
24.	        <td th:text="${i.odd}"></td>
25.	        <td th:text="${i.even}"></td>
26.	        <td th:text="${i.first}"></td>
27.	        <td th:text="${i.last}"></td>
28.	        <td th:text="${emp.empno}"></td>
29.	        <td th:text="${emp.ename}"></td>
30.	        <td th:text="${emp.job}"></td>
31.	        <td th:text="${emp.mgr} eq null ?老板:${emp.mgr}"></td>
32.	        <td th:text="${emp.hiredate}"></td>
33.	        <td th:text="${emp.sal}"></td>
34.	        <td th:text="${emp.comm} eq null ?0:${emp.comm}"></td>
35.	        <td th:text="${emp.deptno}"></td>
36.	        <td>
37.	            <a href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>
38.	        </td>
39.	    </tr>
40.	    
41.	</table>
42.	<script>
43.	    function removeEmp(empno,ename){
44.	        var resulet =confirm("确定要删除编号为"+empno+"的"+ename);
45.	        if(resulet){
46.	            window.location.href="removeEmp?empno="+empno+"&ename="+ename;
47.	        }
48.	    }
49.	
50.	</script>

14_SpringBoot_Thymeleaf内置对象(掌握)

Thymeleaf提供了一些内置对象,内置对象可直接在模板中使用。这些对象是以#引用的。

使用内置对象的语法

1引用内置对象需要使用#

2大部分内置对象的名称都以s结尾。如:strings、numbers、dates
3常见内置对象如下

#arrays:数组操作的工具;

#aggregates:操作数组或集合的工具;

#bools:判断boolean类型的工具;

#calendars:类似于#dates,但是是java.util.Calendar类的方法;

#ctx:上下文对象,可以从中获取所有的thymeleaf内置对象;

#dates:日期格式化内置对象,具体方法可以参照java.util.Date;

#numbers: 数字格式化;#strings:字符串格式化,具体方法可以参照String,如startsWith、contains等;

#objects:参照java.lang.Object;

#lists:列表操作的工具,参照java.util.List;

#sets:Set操作工具,参照java.util.Set;#maps:Map操作工具,参照java.util.Map;

#messages:操作消息的工具。

更多

??

这里我们着重学习 ?strings dates numbers和域对象

strings对象 ?

??

dates对象

??

#numbers

#numbers.formatDecimal(numbwe,整数位,整数位千分位标识符,小数位,小数位表示符)

${#numbers.formatDecimal(num,1,&apos;COMMA&apos;,2,&apos;POINT&apos;)}

显示:99,999,999.99

1:表示整数位至少一位,不足以0补齐,如:num = 0.00,

${#numbers.formatDecimal(num,0,&apos;COMMA&apos;,2,&apos;POINT&apos;)}则显示 .00

${#numbers.formatDecimal(num,1,&apos;COMMA&apos;,2,&apos;POINT&apos;)}则显示 0.00

COMMA:&apos;,&apos;

POINT:‘.’

域对象

??

更多内置 对象:?Tutorial: Using Thymeleaf

?controller

@RequestMapping("showIndex")
2.	    public String  showIndex(Map<String,Object> map, HttpServletRequest req, HttpSession session){
3.	        // 向request域放数据
4.	        req.setAttribute("msg", "requestMessage");
5.	        // 向session域放数据
6.	        session.setAttribute("msg", "sessionMessage");
7.	        // 向application域放数据
8.	        req.getServletContext().setAttribute("msg", "applicationMessage");
9.	
10.	        // 对象List集合数据
11.	        List<Emp> empList = empService.findAll();
12.	        map.put("empList", empList);
13.	        return "index";
14.	    }

页面

1.	<!DOCTYPE html>
2.	<html lang="en" xmlns:th="http://www.thymeleaf.org">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	    <style type="text/css">
7.	        #empTable{
8.	            width: 80%;
9.	            border: 1px solid blue;
10.	            margin: 0px auto;
11.	        }
12.	        #empTable th,td{
13.	            border: 1px solid green;
14.	            text-align: center;
15.	        }
16.	        .a{
17.	            background-color: antiquewhite;
18.	        }
19.	        .b{
20.	            background-color: gray;
21.	        }
22.	    </style>
23.	</head>
24.	<body>
25.	<table  id="empTable" cellpadding="0px" cellspacing="0px">
26.	    <tr>
27.	        <th>索引</th>
28.	        <th>序号</th>
29.	        <th>总人数</th>
30.	        <th>偶数索引?</th>
31.	        <th>奇数索引?</th>
32.	        <th>第一?</th>
33.	        <th>最后?</th>
34.	        <th>工号</th>
35.	        <th>姓名</th>
36.	        <th>职务</th>
37.	        <th>上级</th>
38.	        <th>入职日期</th>
39.	        <th>入职年</th>
40.	        <th>入职月</th>
41.	        <th>入职日</th>
42.	        <th>工资</th>
43.	        <th>补助</th>
44.	        <th>部门号</th>
45.	        <th>操作</th>
46.	    </tr>
47.	    <tr th:each="emp,i:${empList}" th:class="${i.odd}?a:b">
48.	        <td th:text="${i.index}"></td>
49.	        <td th:text="${i.count}"></td>
50.	        <td th:text="${i.size}"></td>
51.	        <td th:text="${i.odd}"></td>
52.	        <td th:text="${i.even}"></td>
53.	        <td th:text="${i.first}"></td>
54.	        <td th:text="${i.last}"></td>
55.	        <td th:text="${emp.empno}"></td>
56.	        <td th:text="${emp.ename}"></td>
57.	        <td th:text="${emp.job}"></td>
58.	        <td th:text="${#strings.isEmpty(emp.mgr)}?老板:${emp.mgr}"></td>
59.	        <td th:text="${#dates.format(emp.hiredate,'yyyy-MM-dd HH:mm:ss')}"></td>
60.	        <td th:text="${#dates.year(emp.hiredate)}"></td>
61.	        <td th:text="${#dates.month(emp.hiredate)}"></td>
62.	        <td th:text="${#dates.day(emp.hiredate)}"></td>
63.	        <td th:text="${#numbers.formatDecimal(emp.sal,7,'COMMA',2,'POINT')}"></td>
64.	        <td th:text="${#strings.isEmpty(emp.comm)}?0:${#numbers.formatDecimal(emp.sal,7,'COMMA',2,'POINT')}"></td>
65.	        <td th:text="${emp.deptno}"></td>
66.	        <td>
67.	            <a href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>
68.	        </td>
69.	    </tr>
70.	    
71.	</table>
72.	<script>
73.	    function removeEmp(empno,ename){
74.	        var resulet =confirm("确定要删除编号为"+empno+"的"+ename);
75.	        if(resulet){
76.	            window.location.href="removeEmp?empno="+empno+"&ename="+ename;
77.	        }
78.	    }
79.	
80.	</script>
81.	
82.	<hr/>
83.	request:<br/>
84.	<span th:text="${#httpServletRequest.getAttribute('msg')}"></span><br/>
85.	<span th:text="${#request.getAttribute('msg')}"></span><br/>
86.	<span th:text="${msg}"></span><br/>
87.	
88.	session:<br/>
89.	<span th:text="${#httpSession.getAttribute('msg')}"></span><br/>
90.	<span th:text="${#session.getAttribute('msg')}"></span><br/>
91.	<span th:text="${session.msg}"></span><br/>
92.	
93.	application:<br/>
94.	<span th:text="${#servletContext.getAttribute('msg')}"></span><br/>
95.	<span th:text="${application.msg}"></span><br/>
96.	
97.	</body>
98.	</html>

15_SpringBoot_模板引擎总结(了解)

jsp

优点:

1、功能强大,可以写java代码

2、支持jsp标签(jsp tag)

3、支持表达式语言(el)

4、官方标准,用户群广,丰富的第三方jsp标签库

缺点:

性能问题。不支持前后端分离

freemarker

FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

目前企业中:主要用Freemarker做静态页面或是页面展示

优点:

1、不能编写java代码,可以实现严格的mvc分离

2、性能非常不错

3、对jsp标签支持良好

4、内置大量常用功能,使用非常方便

5、宏定义(类似jsp标签)非常方便

6、使用表达式语言

缺点:

1、不是官方标准

2、用户群体和第三方标签库没有jsp多

Thymeleaf

Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用。

Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。接下来,这些标签属性就会在DOM(文档对象模型)上执行预先制定好的逻辑。Thymeleaf的可扩展性也非常棒。你可以使用它定义自己的模板属性集合,这样就可以计算自定义表达式并使用自定义逻辑。这意味着Thymeleaf还可以作为模板引擎框架。

优点:静态html嵌入标签属性,浏览器可以直接打开模板文件,便于前后端联调。springboot官方推荐方案。

缺点:模板必须符合xml规范

VUE: 前后端分离,最多,未来趋势

16_SpringBoot_开发者工具(了解)

使用开发者工具包不需要重启。监听内容改变。

1导入依赖

<dependency>
2.	            <groupId>org.springframework.boot</groupId>
3.	            <artifactId>spring-boot-devtools</artifactId>
4.	            <version>2.4.5</version>
5.	            <optional>true</optional>
6.	        </dependency>

1修改idea自动编译

??

2修改Reigstry

Ctrl+Shift+Alt+/ 点击弹出框中Registry...

??

??

17_SpringBoot_项目打包部署(熟练)

SpringBoot项目可以是jar类型的maven项目,也可以是一个war类型的maven项目,取决于我们要不要整合jsp使用。但是不管是哪种项目类型,已经不是我们传统意义上的项目结构了

在本地使用SpringBoot的启动器即可访问我们开发的项目。如果我们将项目功能开发完成后,需要使用SpringBoot的打包功能来将项目进行打包。

SpringBoot项目打包在linux服务器中运行:

? ? ①jar类型项目会打成jar包:

? ? jar类型项目使用SpringBoot打包插件打包时,会在打成的jar中内置一个tomcat的jar。所以我们可以使用jdk直接运行该jar项目可,jar项目中有一个功能,将功能代码放到其内置的tomcat中运行。我们直接使用浏览器访问即可。

? ? ②war类型项目会打成war包:

? ? 在打包时需要将内置的tomcat插件排除,配置servlet的依赖。将war正常的放到tomcat服务器中运行即可。

导入springboot打包插件

1.	<build>
2.	    <plugins>
3.	        <plugin>
4.	            <groupId>org.springframework.boot</groupId>
5.	            <artifactId>spring-boot-maven-plugin</artifactId>
6.	            <configuration>
7.	                <fork>true</fork>
8.	            </configuration>
9.	        </plugin>
10.	    </plugins>
11.	</build>

将项目导出成jar包并运行

项目类型为jar

??

使用maven ?package指令打包即可

?

打成包后,可以通过dos ?java -jar指令直接启动运行 ??

??

将项目导出war包并运行

项目打包成war之后,要放在一个Tomcat上运行

如果我们当前的maven项目本身就是war类型的项目,直接打包即可,但是如果我们当前的maven项目是jar类型的项目,我们需要将项目修改为war类型,修改项目的pom文件,使用packaging标签设置值为war.并且需要在项目中创建webapp文件夹,并设置为资源文件夹。

??

webapp文件夹可加可不加

??

排除项目中自带的所有的Tomcat插件和jsp servlet 依赖,因为这里要将项目放到一个Tomcat上运行

1.	<!--配置SpringBoot的web启动器-->
2.	<dependency>
3.	    <groupId>org.springframework.boot</groupId>
4.	    <artifactId>spring-boot-starter-web</artifactId>
5.	    <!--排除web启动中自动依赖的tomcat插件-->
6.	    <exclusions>
7.	        <exclusion>
8.	            <groupId>org.springframework.boot</groupId>
9.	            <artifactId>spring-boot-starter-tomcat</artifactId>
10.	        </exclusion>
11.	    </exclusions>
12.	</dependency>
13.	<!--
14.	    手动依赖tomcat插件,但是表明项目打包时该依赖不会被打进去,目的主要是保证开发阶段本地SpringBoot
15.	    项目可以正常运行
16.	-->
17.	<dependency>
18.	    <groupId>org.springframework.boot</groupId>
19.	    <artifactId>spring-boot-starter-tomcat</artifactId>
20.	    <!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
21.	        相当于compile,但是打包阶段做了exclude操作-->
22.	    <scope>provided</scope>
23.	</dependency>
24.	

SpringBoot的启动类继承SpringBootServletInitializer,并重写configure

1.	@SpringBootApplication
2.	public class MyApplication extends SpringBootServletInitializer {
3.	    //重写配置方法
4.	    @Override
5.	    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
6.	        return application.sources(MyApplication.class);
7.	    }
8.	    public static void main(String[] args) {
9.	        //启动SpringBoot
10.	        SpringApplication.run(MyApplication.class,args);
11.	    }
12.	}
13.	

使用install命令打包项目,并将war包放到tomcat下的webapps下,启动tomcat即可。

??

??

如果我们使用的是tomcat7则需要将javax.el-api-3.0.0.jar包放到tomcat下? ? ? ? 的lib目录中。

18_SpringBoot_异常处理(掌握)

??

默认情况,Spring Boot项目错误页面如下。当项目实际上线,如果给用户显示这个页面就不是很友好。当系统出现异常时应该给用户显示更加友好的错误页面。

1设置具体的状态码页面

在templates/下新建error文件夹,在error中新建:状态码.html的页面。例如当出现500时显示的页面为500.html

2使用x进行模糊匹配

当出现5开头状态码的错误时,显示页面可以命名为5xx.html

当出现50开头状态码的错误时,显示页面可以命名为50x.html

3统一错误显示页面

在templates下新建error.html。如果项目中不存在具体状态码的页面或没有使用x成功匹配的页面时,显示error.html作为错误显示页面。

SpringMVC异常简介

系统中异常包括两类:预期异常(检查型异常)和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息, 后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图

??

异常处理具体实现

1使用@ExceptionHandler注解处理异常
缺点:只能处理当前Controller中的异常。

1.	@Controller
2.	public class ControllerDemo1 {
3.	    @RequestMapping("test1.action")
4.	    public String test1(){
5.	        int i = 1/0;
6.	        return "success";
7.	    }
8.	    @RequestMapping("test2.action")
9.	    public String test2(){
10.	        String s =null;
11.	        System.out.println(s.length());
12.	        return "success";
13.	    }
14.	    @ExceptionHandler(value ={ArithmeticException.class,NullPointerException.class} )
15.	    public ModelAndView handelException(){
16.	        ModelAndView mv =new ModelAndView();
17.	        mv.setViewName("error1");
18.	        return mv;
19.	    }
20.	}

2使用:@ControllerAdvice+@ExceptionHandler

此处优先级低于局部异常处理器

1.	package com.msb.exceptionhandler;
2.	
3.	import org.springframework.web.bind.annotation.ControllerAdvice;
4.	import org.springframework.web.bind.annotation.ExceptionHandler;
5.	import org.springframework.web.servlet.ModelAndView;
6.	
7.	/**
8.	 * @Author: Ma HaiYang
9.	 * @Description: MircoMessage:Mark_7001
10.	 */
11.	@ControllerAdvice
12.	public class GloableExceptionHandler1 {
13.	    @ExceptionHandler(value ={ArithmeticException.class,NullPointerException.class} )
14.	    public ModelAndView handelException(){
15.	        ModelAndView mv =new ModelAndView();
16.	        mv.setViewName("error1");
17.	        return mv;
18.	    }
19.	}
20.	

3使用:SimpleMappingExceptionResolver

xml配置

配置类配置

1.	/**
2.	
3.	 * 全局异常
4.	
5.	 */
6.	
7.	  @Configuration
8.	
9.	  public class GloableException2 {
10.	
11.	    @Bean
12.	
13.	    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
14.	
15.	        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
16.	
17.	        Properties prop = new Properties();
18.	
19.	        prop.put("java.lang.NullPointerException","error1");
20.	
21.	        prop.put("java.lang.ArithmeticException","error2");
22.	
23.	        resolver.setExceptionMappings(prop);
24.	
25.	        return resolver;
26.	
27.	    }
28.	
29.	}

4自定义的HandlerExceptionResolver

1.	/**
2.	
3.	 * 全局异常
4.	
5.	 * HandlerExceptionResolve
6.	
7.	 */
8.	
9.	  @Configuration
10.	
11.	  public class GloableException3 implements HandlerExceptionResolver {
12.	
13.	    @Override
14.	
15.	    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
16.	
17.	        ModelAndView mv = new ModelAndView();
18.	
19.	        if(e instanceof NullPointerException){
20.	
21.	                mv.setViewName("error1");
22.	
23.	        }
24.	
25.	        if(e instanceof ArithmeticException){
26.	
27.	                mv.setViewName("error2");
28.	
29.	        }
30.	
31.	        mv.addObject("msg",e);
32.	
33.	        return mv;
34.	
35.	    }}

19_SpringBoot_单元测试支持(了解)

在src/main/test里面新建com.msb.项目上下文

注意:

1. 测试类不能叫做Test,会和注解同名

2. 测试方法必须是public

3. 测试方法返回值必须是void

4. 测试方法必须没有参数

1.	package com.msb;
2.	
3.	import com.msb.pojo.Emp;
4.	import com.msb.service.EmpService;
5.	import org.junit.jupiter.api.Test;
6.	import org.springframework.beans.factory.annotation.Autowired;
7.	import org.springframework.boot.test.context.SpringBootTest;
8.	
9.	import java.util.List;
10.	
11.	@SpringBootTest(classes = Springboot03Application.class)
12.	class Springboot03AppliactionTests {
13.	    @Autowired
14.	    private EmpService empService;
15.	    @Test
16.	    public void testFindAll() {
17.	        List<Emp> list = empService.findAll();
18.	        list.forEach(System.out::println);
19.	    }
20.	
21.	}
22.	

20_SpringBoot_bean管理(了解)

Spring Boot中Bean管理

Spring Boot 由于没有XML文件,所以所有的Bean管理都放入在一个配置类中实现。

配置类就是类上具有@Configuration的类。这个类就相当于之前的applicationContext.xml

1 新建配置类

com.msb.config.MyConfig , 规范都是放入到config文件夹中。

注意:配置类要有@Configuration,方法要有@Bean

1.	@Configuration
2.	public class MyConfig {
3.	    //访问权限修饰符没有强制要求,一般是protected
4.	    //返回值就是注入到Spring容器中实例类型。
5.	    // 方法名没有强制要求,相当于<bean >中id属性。
6.	    @Bean
7.	    protected User getUser(){
8.	        User user = new User();
9.	        user.setId(1L);
10.	        user.setName("张三");
11.	        return user;
12.	    }
13.	    //自定义bean名称
14.	    @Bean("user2")
15.	    protected  User getUser2(){
16.	        User user = new User();
17.	        user.setId(2L);
18.	        user.setName("李四");
19.	        return user;
20.	    }
21.	}

如果Spring容器中存在同类型的Bean通过Bean的名称获取到Bean对象。或结合@Qualifier使用

1.	@SpringBootTest
2.	public class TestGetBean {
3.	    @Autowired
4.	    @Qualifier("user2")
5.	    private User user;
6.	    @Test
7.	    public void testGetUser(){
8.	        System.out.println(user);
9.	    }
10.	}
11.	

在配置类的方法中通过方法参数让Spring容器把对象注入。

1.	//自定义bean名称
2.	@Bean("user1")
3.	public  User getUser(){
4.	    User user = new User();
5.	    user.setId(2L);
6.	    user.setName("李四");
7.	    return user;
8.	}
9.	
10.	@Bean
11.	//可以直接从方法参数中取到。
12.	public People getPeople(User user1){
13.	    People p = new People();
14.	    p.setUser(user1);
15.	    return p;
16.	}
17.	
18.	

22_SpringBoot其他拓展

01_SpringBoot_注解拓展

springboot默认已经帮助我们整合好了SpringMVC,同时也给我们默认配置了DispathcerServlet 和编码过滤器,同时也给我们配置好了WEB项目开发的常见组件

查看容器中的所有组件

@SpringBootApplication

1.	/*
2.	* 默认扫描启动类所在包下的所有层级的子包
3.	* 可以通过scanBasePackages属性指定扫描路径
4.	* SpringBootApplication是一个合成注解,可以拆分为以下三个注解
5.	*   @SpringBootConfiguration
6.	*   @EnableAutoConfiguration
7.	*   @ComponentScan(basePackages = "com.msb")
8.	*
9.	*
10.	* */
11.	@SpringBootApplication
12.	public class Springboot04Application {
13.	    public static void main(String[] args) {
14.	        //返回一个spring容器
15.	        ConfigurableApplicationContext context = SpringApplication.run(Springboot04Application.class, args);
16.	        // 查看所有组件的名
17.	        String[] names = context.getBeanDefinitionNames();
18.	        for (String name : names) {
19.	            System.out.println(name);
20.	        }
21.	    }
22.	}

@Configuration?

1.	package com.msb.config;
2.	
3.	import com.msb.pojo.User;
4.	import org.springframework.context.annotation.Bean;
5.	import org.springframework.context.annotation.Configuration;
6.	
7.	/**
8.	 * @Author: Ma HaiYang
9.	 * @Description: MircoMessage:Mark_7001
10.	 * MyConfig配置类本身也是一个spring容器中的bean
11.	 * proxyBeanMethods=true 属性,给MyConfig对象产生一个代理对象
12.	 * 通过代理对象控制反复调用MyConfig里面的方法返回的是容器中的一个单实例
13.	 * 如果proxyBeanMethods=false 那么我们拿到的MyConfig对象就不是一个代理对象
14.	 * 那么这个时候反复调用MyConfig中的方法返回的就是多实例
15.	 *
16.	 * proxyBeanMethods=false 称之为Lite模式  特点启动快
17.	 * proxyBeanMethods=true  称之为Full模式  特点依赖spring容器控制bean单例
18.	 *
19.	 */
20.	@Configuration(proxyBeanMethods = true)
21.	public class MyConfig {
22.	
23.	    /*<bean id = "user1" class ="com.msb.pojo.User">... ...</bean>*/
24.	    @Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
25.	    public User user1(){
26.	        return new User("zhangsan", 10);
27.	    }
28.	
29.	    /*<bean id = "user2" class ="com.msb.pojo.User">... ...</bean>*/
30.	    @Bean("user2") // 向容器中添加一个Bean,手动指定Bean的name属性,返回值类型作为组件的类型
31.	    public User getUser(){
32.	        return new User("lisi", 11);
33.	    }
34.	}

测试代码

1.	package com.msb;
2.	
3.	import com.msb.config.MyConfig;
4.	import com.msb.pojo.User;
5.	import org.springframework.boot.SpringApplication;
6.	import org.springframework.boot.SpringBootConfiguration;
7.	import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
8.	import org.springframework.boot.autoconfigure.SpringBootApplication;
9.	import org.springframework.context.ConfigurableApplicationContext;
10.	import org.springframework.context.annotation.ComponentScan;
11.	
12.	
13.	@SpringBootApplication(scanBasePackages = "com.msb")
14.	public class Springboot04Application {
15.	    public static void main(String[] args) {
16.	        //返回一个spring容器
17.	        ConfigurableApplicationContext context = SpringApplication.run(Springboot04Application.class, args);
18.	      
19.	
20.	        System.out.println(context.getBean("user1"));
21.	        System.out.println(context.getBean("user2"));
22.	        User usera = context.getBean(MyConfig.class).getUser();
23.	        User userb = context.getBean(MyConfig.class).getUser();
24.	        System.out.println(usera==userb);
25.	    }
26.	}

@Import

1.	package com.msb.config;
2.	
3.	import com.msb.pojo.User;
4.	import org.springframework.context.annotation.Bean;
5.	import org.springframework.context.annotation.Configuration;
6.	import org.springframework.context.annotation.Import;
7.	
8.	
9.	/*
10.	* @Import({User.class}) 在容器中自动创建Bean的注解
11.	* 通过传入字节码,默认调用bean的无参构造器,向容器中存放一个Bean
12.	* 默认组件的名字就是类的全路径名
13.	* @Import只要放到可以被扫描到的类之上就可以,不必非得是配置类或者Controller
14.	* */
15.	@Import({User.class})
16.	@Configuration(proxyBeanMethods = true)
17.	public class MyConfig {
18.	
19.	}
1.	@SpringBootApplication(scanBasePackages = "com.msb")
2.	public class Springboot04Application {
3.	    public static void main(String[] args) {
4.	        //启动SpringBoot, 返回一个spring容器
5.	        ConfigurableApplicationContext context = SpringApplication.run(Springboot04Application.class, args);
6.	        // 根据类型获取Bean
7.	        User bean = context.getBean(User.class);
8.	        System.out.println(bean);
9.	        // 获取属性User类的所有bean的name
10.	        String[] beanNamesForType = context.getBeanNamesForType(User.class);
11.	        for (String s : beanNamesForType) {
12.	            System.out.println(s);
13.	        }
14.	    }
15.	}

@Conditional 条件装配

满足Conditional指定的条件,则进行组件注入

@Conditional下还有很多子注解

??

1.	package com.msb.config;
2.	
3.	import com.msb.pojo.Emp;
4.	import com.msb.pojo.User;
5.	import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
6.	import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
7.	import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
8.	import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
9.	import org.springframework.context.annotation.Bean;
10.	import org.springframework.context.annotation.Conditional;
11.	import org.springframework.context.annotation.Configuration;
12.	import org.springframework.context.annotation.Import;
13.	
14.	
15.	@Configuration
16.	/*
17.	 * 当配置中存在一个aaa.b的配置并且值为x的时候,当前配置中所有的配置才会生效
18.	 * */
19.	//@ConditionalOnProperty( name = "aaa.b",havingValue = "x")
20.	public class MyConfig {
21.	    /*
22.	    * 当配置中存在一个aaa.b的配置并且值为x的时候,容器才会初始化user1
23.	    * */
24.	    @ConditionalOnProperty( name = "aaa.b",havingValue = "x")
25.	    @Bean
26.	    public User user1(){
27.	        return new User("zhangsan", 10);
28.	    }
29.	}

??

@ImportResource

原生配置文件引入,允许我们自己定义xml配置文件,在文件中配置bean

resources目录下准备一个xml配置文件

???

配置类中加载该配置文件

1.	package com.msb.config;
2.	
3.	import org.springframework.context.annotation.*;
4.	
5.	@Configuration
6.	@ImportResource("classpath:beans.xml")
7.	public class MyConfig {
8.	}
9.	

从容器中获取beans.xml中配置的bean

1.	@SpringBootApplication
2.	public class Springboot04Application {
3.	    public static void main(String[] args) {
4.	        //启动SpringBoot, 返回一个spring容器
5.	        ConfigurableApplicationContext context = SpringApplication.run(Springboot04Application.class, args);
6.	        System.out.println(context.getBean("userx"));
7.	
8.	    }
9.	}

@ConfigurationProperties

读取application.properties配置文件中的内容,读取进入bean

1.	/*prefix前缀,为配置文件中对应的前缀
2.	* 通过前缀找到对应的配置信息后,在根据属性名去注入匹配的数据*/
3.	@ConfigurationProperties( prefix = "user")
4.	@Component
5.	public class User {
6.	    private String uname;
7.	    private int age;
8.	}

?配置类代码

1.	package com.msb.config;
2.	
3.	import com.msb.pojo.User;
4.	import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
5.	import org.springframework.boot.context.properties.EnableConfigurationProperties;
6.	import org.springframework.context.annotation.Configuration;
7.	
8.	/**
9.	 * @Author: Ma HaiYang
10.	 * @Description: MircoMessage:Mark_7001
11.	 */
12.	@Configuration
13.	/*开启了User的属性自动配置功能并把User自动注册到容器中
14.	* 这个时候,我们的User上就不用加@Component注解了
15.	* 适用于Bean来自于第三方JAR场景
16.	* */
17.	@EnableConfigurationProperties(User.class)
18.	public class MyConfig {
19.	}

测试代码

1.	package com.msb;
2.	
3.	import com.msb.pojo.User;
4.	import org.springframework.boot.SpringApplication;
5.	import org.springframework.boot.autoconfigure.SpringBootApplication;
6.	import org.springframework.context.ConfigurableApplicationContext;
7.	
8.	@SpringBootApplication
9.	public class Springboot04Application {
10.	    public static void main(String[] args) {
11.	        //启动SpringBoot, 返回一个spring容器
12.	        ConfigurableApplicationContext context = SpringApplication.run(Springboot04Application.class, args);
13.	        System.out.println(context.getBean(User.class));
14.	
15.	    }
16.	}

02_SpringBoot_静态资源

静态资源默认存放位置

resources 目录下,static/public目录是我们的静态资源目录,直接访问该目录下的资源的映射路径不需要携带/public或者/static,直接访问即可

?

如果controller的映射路径和静态资源路径冲突,会发生什么事情呢?

?

1.	package com.msb.controller;
2.	
3.	import org.springframework.stereotype.Controller;
4.	import org.springframework.web.bind.annotation.RequestMapping;
5.	import org.springframework.web.bind.annotation.ResponseBody;
6.	
7.	/**
8.	 * @Author: Ma HaiYang
9.	 * @Description: MircoMessage:Mark_7001
10.	 */
11.	@Controller
12.	public class MyController {
13.	    @RequestMapping("/logo.png")
14.	    @ResponseBody
15.	    public String logo(){
16.	        return "controller logo";
17.	    }
18.	}
19.	

请求进来,先去看Controller中有没有对应的资源,如果有则,执行controller资源,如果没有,就交给静态资源处理器,静态资源处理器也没有找到,则返回404

静态资源访问前缀

默认无前缀,如果想指定静态资源前缀,可以 通过spring.mvc.static-path-pattern配置

yml配置如下

?

?请求路径上通过 项目上下文路径+静态资源前缀+静态资源名的方式访问

?

指定静态资源位置

静态资源默认存放的路径为static content from a directory called /static (or /public or /resources or /META-INF/resources)

可以通过

?

static-locations 指定专门的静态资源路径

?

springboot还支持静态资源webjars 的处理方式,就是将静态资源打成jar导入

WebJars - Web Libraries in Jars? ??

?

项目中导入jQuery依赖

?

1.	<dependency>
2.	    <groupId>org.webjars</groupId>
3.	    <artifactId>jquery</artifactId>
4.	    <version>3.6.0</version>
5.	</dependency>

导入后,自动映射

http://localhost:8080/springboot-static-content/res/webjars/jquery/3.6.0/jquery.js

或者

http://localhost:8080/springboot-static-content/webjars/jquery/3.6.0/jquery.js

?

欢迎页功能 ?

方式1 支持静态资源欢迎页, index.html ?注意此时不能配置静态资源前缀,否则不生效

静态资源位置

?

方式2 通过controller ,定义 / 和/index映射 路径 ?

   @RequestMapping(path={"/","/index"})
2.	    public String welcome(){
3.	        return "welcome";
4.	    }

导入thymeleaf

  <dependency>
2.	            <groupId>org.springframework.boot</groupId>
3.	            <artifactId>spring-boot-starter-thymeleaf</artifactId>
4.	            <version>2.4.5</version>
5.	        </dependency>

定义Favicon

static目录下准备一个favicon.ico的一个图片即可

浏览器默认访问favicon.ico的路径为 ?协议://ip:端口号/favicon.ico,所以这里不要设置项目的上下文路径

拦截器静态资源放行

定义一个登陆页面

?

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	    <link type="text/css" href="css/mycss.css">
7.	    <script src="js/myjs.js"></script>
8.	</head>
9.	<body>
10.	<img src="img/logo.png">
11.	<form action="login">
12.	    <input type="text" name="username" >
13.	    <input type="submit">
14.	</form>
15.	
16.	</body>
17.	</html>

?定义一个登陆controller

?

1.	package com.msb.controller;
2.	
3.	import org.springframework.stereotype.Controller;
4.	import org.springframework.web.bind.annotation.RequestMapping;
5.	
6.	import javax.servlet.http.HttpServletRequest;
7.	
8.	/**
9.	 * @Author: Ma HaiYang
10.	 * @Description: MircoMessage:Mark_7001
11.	 */
12.	@Controller
13.	public class LoginController {
14.	
15.	    @RequestMapping("/login")
16.	    public String login(String username, HttpServletRequest request){
17.	        if(null != username&&!"".equals(username)){
18.	            request.getSession().setAttribute("username", username);
19.	            return "main";
20.	        }
21.	        return "redirect:/login.html";
22.	    }
23.	}

定义一个登陆拦截器

1.	package com.msb.interceptor;
2.	
3.	import org.springframework.stereotype.Component;
4.	import org.springframework.web.servlet.HandlerInterceptor;
5.	
6.	import javax.servlet.http.HttpServletRequest;
7.	import javax.servlet.http.HttpServletResponse;
8.	
9.	/**
10.	 * @Author: Ma HaiYang
11.	 * @Description: MircoMessage:Mark_7001
12.	 */
13.	@Component
14.	public class LoginInterceptor implements HandlerInterceptor {
15.	    @Override
16.	    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
17.	        Object username = request.getSession().getAttribute("username");
18.	        // 如果登录过,那么就放行
19.	        if(null != username){
20.	            return true;
21.	        }
22.	        // 如果没登陆过,那么就回到登录页,重定向
23.	        response.sendRedirect("login.html");
24.	        return false;
25.	    }
26.	}
27.	

配置拦截器

1.	package com.msb.config;
2.	
3.	import com.msb.interceptor.LoginInterceptor;
4.	import org.springframework.beans.factory.annotation.Autowired;
5.	import org.springframework.context.annotation.Configuration;
6.	import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7.	import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8.	
9.	/**
10.	 * @Author: Ma HaiYang
11.	 * @Description: MircoMessage:Mark_7001
12.	 */
13.	@Configuration
14.	public class MyInterceptorRegist implements WebMvcConfigurer {
15.	    @Autowired
16.	    private LoginInterceptor loginInterceptor;
17.	    //配置拦截器的映射
18.	    @Override
19.	    public void addInterceptors(InterceptorRegistry registry) {
20.	        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login","/login.html","/css/**","/js/**","/img/**","/font/**");
21.	    }
22.	}

template下的main.html

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <title>Title</title>
6.	</head>
7.	<body>
8.	
9.	this is main... ...
10.	
11.	
12.	</body>
13.	</html>

03_SpringBoot_文件上传

创建项目:略

启动文件上传服务器:略

导入依赖

1.	<dependency>
2.	  <groupId>com.sun.jersey</groupId>
3.	  <artifactId>jersey-client</artifactId>
4.	  <version>1.19</version>
5.	</dependency>

页面代码

1.	<html>
2.	<head>
3.	    <meta charset="UTF-8">
4.	    <title>Title</title>
5.	    <style>
6.	        .progress {
7.	            width: 200px;
8.	            height: 10px;
9.	            border: 1px solid #ccc;
10.	            border-radius: 10px;
11.	            margin: 10px 0px;
12.	            overflow: hidden;
13.	        }
14.	        /* 初始状态设置进度条宽度为0px */
15.	        .progress > div {
16.	            width: 0px;
17.	            height: 100%;
18.	            background-color: yellowgreen;
19.	            transition: all .3s ease;
20.	        }
21.	    </style>
22.	    <script type="text/javascript" src="js/jquery.min.js"></script>
23.	    <script type="text/javascript">
24.	        $(function(){
25.	            $("#uploadFile").click(function(){
26.	                // 获取要上传的文件
27.	                var photoFile =$("#photo")[0].files[0]
28.	                if(photoFile==undefined){
29.	                    alert("您还未选中文件")
30.	                    return;
31.	                }
32.	                // 将文件装入FormData对象
33.	                var formData =new FormData();
34.	                formData.append("headPhoto",photoFile)
35.	                // ajax向后台发送文件
36.	                $.ajax({
37.	                    type:"post",
38.	                    data:formData,
39.	                    url:"file/upload",
40.	                    processData:false,
41.	                    contentType:false,
42.	                    success:function(result){
43.	                        // 接收后台响应的信息
44.	                        alert(result.message)
45.	                        // 图片回显
46.	                        $("#headImg").attr("src",result.newFileName);
47.	                    },
48.	                    xhr: function() {
49.	                        var xhr = new XMLHttpRequest();
50.	                        //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件
51.	                        xhr.upload.addEventListener('progress', function (e) {
52.	                            //loaded代表上传了多少
53.	                            //total代表总数为多少
54.	                            var progressRate = (e.loaded / e.total) * 100 + '%';
55.	                            //通过设置进度条的宽度达到效果
56.	                            $('.progress > div').css('width', progressRate);
57.	                        })
58.	                        return xhr;
59.	                    }
60.	                })
61.	            })
62.	        })
63.	    </script>
64.	</head>
65.	<body>
66.	<form action="addPlayer" method="get">
67.	    <p>账号<input type="text" name="name"></p>
68.	    <p>密码<input type="text" name="password"></p>
69.	    <p>昵称<input type="text" name="nickname"></p>
70.	    <p>头像:
71.	        <br/>
72.	        <input id="photo" type="file">
73.	        <br/>
74.	        <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
75.	        <br/>
76.	        <div class="progress">
77.	            <div></div>
78.	        </div>
79.	        <a id="uploadFile" href="javascript:void(0)">立即上传</a>
80.	    </p>
81.	    <p><input type="submit" value="注册"></p>
82.	</form>
83.	</body>
84.	</html>

Controller代码

1.	package com.msb.controller;
2.	
3.	import com.sun.jersey.api.client.Client;
4.	import com.sun.jersey.api.client.WebResource;
5.	import org.springframework.stereotype.Controller;
6.	import org.springframework.web.bind.annotation.RequestMapping;
7.	import org.springframework.web.bind.annotation.ResponseBody;
8.	import org.springframework.web.multipart.MultipartFile;
9.	
10.	import javax.servlet.http.HttpServletRequest;
11.	import java.io.File;
12.	import java.io.IOException;
13.	import java.util.HashMap;
14.	import java.util.Map;
15.	import java.util.UUID;
16.	
17.	/**
18.	 * @Author: Ma HaiYang
19.	 * @Description: MircoMessage:Mark_7001
20.	 */
21.	@Controller
22.	@RequestMapping("/file")
23.	public class FileController {
24.	
25.	    // 文件存储位置
26.	    private final static String FILESERVER="http://127.0.0.1:8090/upload/";
27.	
28.	    @RequestMapping("/upload")
29.	    @ResponseBody
30.	    public Map<String,String> upload(MultipartFile headPhoto, HttpServletRequest req) throws IOException {
31.	        Map<String,String> map=new HashMap<>();
32.	
33.	        // 指定文件存储目录为我们项目部署环境下的upload目录
34.	        String realPath = req.getServletContext().getRealPath("/upload");
35.	        File dir = new File(realPath);
36.	        // 如果不存在则创建目录
37.	        if(!dir.exists()){
38.	            dir.mkdirs();
39.	        }
40.	        // 获取文件名
41.	        String originalFilename = headPhoto.getOriginalFilename();
42.	        // 避免文件名冲突,使用UUID替换文件名
43.	        String uuid = UUID.randomUUID().toString();
44.	        // 获取拓展名
45.	        String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
46.	        // 新的文件名
47.	        String newFileName=uuid.concat(extendsName);
48.	        // 创建 sun公司提供的jersey包中的client对象
49.	        Client client=Client.create();
50.	        WebResource resource = client.resource(FILESERVER + newFileName);
51.	        //  文件保存到另一个服务器上去了
52.	        resource.put(String.class, headPhoto.getBytes());
53.	        // 上传成功之后,把文件的名字和文件的类型返回给浏览器
54.	        map.put("message", "上传成功");
55.	        map.put("newFileName", FILESERVER+newFileName);
56.	        map.put("filetype", headPhoto.getContentType());
57.	        return map;
58.	    }
59.	}

yml中配置文件大小限制

1.	spring:
2.	  servlet:
3.	    multipart:
4.	      max-file-size: 10MB
5.	      max-request-size: 100MB

多文件同步上传处理方式

页面代码

1.	<form action="file/upload" method="post" enctype="multipart/form-data">
2.	    <p>账号<input type="text" name="name"></p>
3.	    <p>密码<input type="text" name="password"></p>
4.	    <p>昵称<input type="text" name="nickname"></p>
5.	    <p>头像:
6.	        <br/>
7.	        <input id="photo" name="photo"  type="file">
8.	        <input id="photos" name="photos"  type="file" multiple>
9.	        <br/>
10.	        <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
11.	        <br/>
12.	    <div class="progress">
13.	        <div></div>
14.	    </div>
15.	    <a id="uploadFile" href="javascript:void(0)">立即上传</a>
16.	    </p>
17.	    <p><input type="submit" value="注册"></p>
18.	</form>

后台接收的处理单元参数处理

public Map<String,String> upload(String name,
2.	                                     String password,
3.	                                     String nickname,
4.	                                     @RequestPart("photo") MultipartFile photo,
5.	                                     @RequestPart("photos") MultipartFile[] photos, HttpServletRequest req)

04_SpringBoot_MyBatis-Plus

Redirect?

MyBatis-plus是mybatis的增强工具,在MyBatis 上只做增强,不做改变,为简化开发,提高效率而生

?

MyBatis-plus和mybatis就像是魂斗罗中的两个兄弟 ?

安装MyBatisX插件

创建项目

导入依赖

?

1.	<dependency>
2.	            <groupId>org.springframework.boot</groupId>
3.	            <artifactId>spring-boot-starter-web</artifactId>
4.	        </dependency>
5.	
6.	        <dependency>
7.	            <groupId>org.projectlombok</groupId>
8.	            <artifactId>lombok</artifactId>
9.	            <optional>true</optional>
10.	        </dependency>
11.	        <dependency>
12.	            <groupId>org.springframework.boot</groupId>
13.	            <artifactId>spring-boot-starter-test</artifactId>
14.	            <scope>test</scope>
15.	        </dependency>
16.	
17.	
18.	        <dependency>
19.	            <groupId>mysql</groupId>
20.	            <artifactId>mysql-connector-java</artifactId>
21.	            <version>8.0.21</version>
22.	        </dependency>
23.	
24.	        <dependency>
25.	            <groupId>com.alibaba</groupId>
26.	            <artifactId>druid-spring-boot-starter</artifactId>
27.	            <version>1.1.10</version>
28.	        </dependency>
29.	
30.	        <dependency>
31.	            <groupId>com.baomidou</groupId>
32.	            <artifactId>mybatis-plus-boot-starter</artifactId>
33.	            <version>3.4.2</version>
34.	        </dependency>
35.	

自动配置的内容

MyBatis PlusAutoConfiguration配置类,MyBatisPlusProperties配置项前缀 mybatis-plus: ***就是对mybatis-plus的参数的设置

SQLSessionFactory已经配置好

mapperlocations 自动配置好的,默认值是classpath*:/mapper/**/*.xml ?意为任意包路径下所有的mapper包下的xml文件

@Mapper建议替换成MapperScan

配置mybatisplus

1.	
2.	spring:
3.	  datasource:
4.	    type: com.alibaba.druid.pool.DruidDataSource
5.	    driver-class-name: com.mysql.cj.jdbc.Driver
6.	    url: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
7.	    username: root
8.	    password: root
9.	  druid:
10.	    initial-size: 5
11.	    min-idle: 5
12.	    maxActive: 20
13.	    maxWait: 60000
14.	    timeBetweenEvictionRunsMillis: 60000
15.	    minEvictableIdleTimeMillis: 300000
16.	    validationQuery: SELECT 1
17.	    testWhileIdle: true
18.	    testOnBorrow: false
19.	    testOnReturn: false
20.	    poolPreparedStatements: true
21.	    maxPoolPreparedStatementPerConnectionSize: 20
22.	    filters: stat,wall,slf4j
23.	    connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
24.	    web-stat-filter:
25.	      enabled: true
26.	      url-pattern: "/*"
27.	      exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
28.	    stat-view-servlet:
29.	      url-pattern: "/druid/*"
30.	      allow: 127.0.0.1,192.168.8.109
31.	      deny: 192.168.1.188
32.	      reset-enable: false
33.	      login-username: admin
34.	      login-password: 123456
35.	
36.	mybatis-plus:
37.	  type-aliases-package: com.msb.pojo

实体类

1.	@AllArgsConstructor
2.	@NoArgsConstructor
3.	@Data
4.	@TableName("dept")
5.	public class Dept implements Serializable {
6.	    /*@TableField(exist = false)
7.	    private String aaa;*/
8.	    @TableField("deptno")
9.	    private Integer deptno;
10.	    private String dname;
11.	    private String loc;
12.	}

mapper

1.	public interface DeptMapper  extends BaseMapper<Dept> {
2.	     
3.	}

service

接口

1.	public interface DeptService extends IService<Dept> {
2.	}

实现类

1.	@Service
2.	public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
3.	}

测试代码CURD

1.	package com.msb;
2.	
3.	import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4.	import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
5.	import com.msb.mapper.DeptMapper;
6.	import com.msb.pojo.Dept;
7.	import com.msb.service.DeptService;
8.	import lombok.AllArgsConstructor;
9.	import org.junit.jupiter.api.Test;
10.	import org.springframework.beans.factory.annotation.Autowired;
11.	import org.springframework.boot.test.context.SpringBootTest;
12.	
13.	import java.util.List;
14.	
15.	@SpringBootTest
16.	class SpringbootMybatisplusApplicationTests {
17.	
18.	
19.	    @Autowired
20.	    DeptService deptService;
21.	
22.	
23.	    @Test
24.	    public void testFindAll(){
25.	        List<Dept> list = deptService.list();
26.	        for (Dept dept : list) {
27.	            System.out.println(dept);
28.	        }
29.	    }
30.	    // 查询集合
31.	    @Test
32.	    public void testQueryWrapper(){
33.	        // 部门号》=20
34.	        // QueryWrapper 作用就是在原本的SQL语句后面拼接where条件
35.	        // selec * from where      delete from dept where  update dept set ...  where ....
36.	        QueryWrapper<Dept> queryWrapper=new QueryWrapper<>();
37.	        //queryWrapper.ge("deptno", 20).eq("dname", "ACCOUNTING").likeRight("dname", "A");
38.	        //queryWrapper.likeRight("dname", "A");
39.	        List<Dept> list = deptService.list(queryWrapper);
40.	        for (Dept dept : list) {
41.	            System.out.println(dept);
42.	        }
43.	
44.	
45.	    }
46.	    // 查询单个
47.	    @Test
48.	    public void testQueryWrapper2(){
49.	        QueryWrapper<Dept> queryWrapper=new QueryWrapper<>();
50.	        queryWrapper.eq("deptno", 20);
51.	        Dept dept = deptService.getOne(queryWrapper);
52.	        System.out.println(dept);
53.	
54.	    }
55.	
56.	    // 增加
57.	    @Test
58.	    public void testAdd(){
59.	        boolean save = deptService.save(new Dept(null, "aaa", "bbb"));
60.	        System.out.println(save);
61.	    }
62.	
63.	    // 修改
64.	    @Test
65.	    public void testUpdate(){
66.	        // 要更新的数据
67.	        Dept dept =new Dept();
68.	        dept.setDname("xxx");
69.	        dept.setLoc("yyy");
70.	        // 更新的条件
71.	        QueryWrapper<Dept> queryWrapper=new QueryWrapper<>();
72.	        queryWrapper.eq("deptno", 41);
73.	        boolean update = deptService.update(dept, queryWrapper);
74.	        System.out.println(update);
75.	    }
76.	    // 删除
77.	    @Test
78.	    public void testRemove(){
79.	        QueryWrapper<Dept> queryWrapper=new QueryWrapper<>();
80.	        queryWrapper.eq("deptno", 41);
81.	        boolean remove = deptService.remove(queryWrapper);
82.	        System.out.println(remove);
83.	    }
84.	
85.	
86.	
87.	}

分页插件的使用

配置分页插件

1.	package com.msb.config;
2.	
3.	import com.baomidou.mybatisplus.annotation.DbType;
4.	import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
5.	import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
6.	import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
7.	import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
8.	import org.springframework.context.annotation.Bean;
9.	import org.springframework.context.annotation.Configuration;
10.	
11.	/**
12.	 * @Author: Ma HaiYang
13.	 * @Description: MircoMessage:Mark_7001
14.	 */
15.	@Configuration
16.	public class MyBatisPlusConfig {
17.	    @Bean
18.	    public MybatisPlusInterceptor mybatisPlusInterceptor() {
19.	        MybatisPlusInterceptor mybatisPlusInterceptor =new MybatisPlusInterceptor();
20.	        PaginationInnerInterceptor paginationInnerInterceptor =new PaginationInnerInterceptor();
21.	        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
22.	        //paginationInnerInterceptor.setOverflow(false);
23.	        // 设置最大单页限制数量,默认 500 条,-1 不受限制
24.	        //paginationInnerInterceptor.setMaxLimit(500L);
25.	        // 设置数据库类型
26.	        paginationInnerInterceptor.setDbType(DbType.MYSQL);
27.	        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
28.	        return mybatisPlusInterceptor;
29.	    }
30.	}

测试分页插件

 @Test
2.	    public void testPage(){
3.	        // 当前页  页大小
4.	        QueryWrapper<Dept> queryWrapper=new QueryWrapper<>();
5.	        //queryWrapper.likeRight("dname", "A");
6.	        Page<Dept> page = deptService.page(new Page<>(1, 2), queryWrapper);
7.	        // 当前页数据  总页数  总记录数  当前页  页大小 ... ..
8.	        List<Dept> list = page.getRecords();
9.	        list.forEach(System.out::println);
10.	        System.out.println("总页数:"+page.getPages());
11.	        System.out.println("总记录数:"+page.getTotal());
12.	        System.out.println("当前页:"+page.getCurrent());
13.	        System.out.println("页大小:"+page.getSize());
14.	    }

05_SpringBoot_Junit5

springboot 2.2.0开始引入Junit5作为单元测试的默认库

JUnit5和之前的版本有很大的不同,由单个子项目的几个不同模块组成

JUnit Platform ,是在JVM上启动测试框架的技术,不仅支持Junit自己的测试引擎,其他的测试引擎也可以

JUnit Jupiter,提供了Junit5的最新的编程模型,是Junit5 的核心,内部包含了一个测试引擎,用于在Junit Platform上运行

JUnit Vintager: 提供了兼容Junit4/3 的测试引擎

Junit5 =?JUnit Platform+?JUnit Jupiter+JUnit Vintager

?

Junit支持Spring中的注解,测试起来比较方便, @Autowired @Transactional 等

1.	package com.msb;
2.	
3.	import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4.	import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
5.	import com.msb.mapper.DeptMapper;
6.	import com.msb.pojo.Dept;
7.	import com.msb.service.DeptService;
8.	import org.junit.jupiter.api.*;
9.	import org.junit.jupiter.api.extension.ExtendWith;
10.	import org.junit.platform.commons.annotation.Testable;
11.	import org.springframework.beans.factory.annotation.Autowired;
12.	import org.springframework.boot.test.context.SpringBootTest;
13.	import org.springframework.boot.test.context.SpringBootTestContextBootstrapper;
14.	import org.springframework.test.context.BootstrapWith;
15.	import org.springframework.test.context.junit.jupiter.SpringExtension;
16.	
17.	import java.util.List;
18.	import java.util.concurrent.TimeUnit;
19.	
20.	@SpringBootTest // 使用springboot的容器功能
21.	/*@BootstrapWith(SpringBootTestContextBootstrapper.class)
22.	@ExtendWith({SpringExtension.class})*/
23.	@DisplayName("Junit5测试类")// 测试类描述
24.	class SpringbootMybatisplusApplicationTests2 {
25.	
26.	    @Autowired
27.	    private DeptMapper deptMapper;
28.	
29.	
30.	    @BeforeEach
31.	    public void testForeach(){
32.	        System.out.println("beforeach");
33.	    }
34.	
35.	    @AfterEach
36.	    public void testAftereach(){
37.	        System.out.println("aferEach");
38.	    }
39.	
40.	    @BeforeAll
41.	    public static void beforeAll(){
42.	        System.out.println("beforall");
43.	    }
44.	
45.	    @AfterAll
46.	    public static void aferAll(){
47.	        System.out.println("afterAll");
48.	    }
49.	    @RepeatedTest(3)// 重复测试3次
50.	    @Timeout(value = 10000,unit = TimeUnit.MILLISECONDS)// 超时时间设置
51.	    @DisplayName("Junit测试方法1")
52.	    @Test
53.	    public void test1(){
54.	        System.out.println("a");
55.	        System.out.println(deptMapper);
56.	    }
57.	
58.	
59.	    @Disabled// 设置不可用
60.	    @DisplayName("Junit测试方法2") // 方法描述
61.	    @Test
62.	    public void test2(){
63.	        System.out.println("b");
64.	    }
65.	
66.	
67.	
68.	}

?

断言机制

断定某件事情,一定会发生,如果没有发生,那就是出现了问题,所欲的测试运行结束后,会有一个详细的断言报告

用来对测试需要满足的条件进行验证,这些断言方法都是org.junit.jupiter.api.Assertions中的静态方法,

简单断言

?

1.	package com.msb;
2.	
3.	
4.	import org.junit.jupiter.api.Assertions;
5.	import org.junit.jupiter.api.DisplayName;
6.	import org.junit.jupiter.api.Test;
7.	import org.springframework.boot.test.context.SpringBootTest;
8.	
9.	import java.time.Duration;
10.	import java.util.concurrent.TimeUnit;
11.	
12.	@SpringBootTest
13.	@DisplayName("Junit5断言测试类")
14.	class SpringbootMybatisplusApplicationTests3 {
15.	
16.	    @DisplayName("简单断言1")
17.	    @Test
18.	    public void testAssertions1(){
19.	        int add = add(1, 2);
20.	        Assertions.assertEquals(6,add,"add结果计算错误");
21.	    }
22.	    public int add(int a,int b){
23.	        return a+b;
24.	    }
25.	
26.	    @DisplayName("简单断言2")
27.	    @Test
28.	    public void testAssertions2(){
29.	        String s =new String("xxx");
30.	        String s2=new String("abc");
31.	        Assertions.assertEquals(s,s2,"String对象不一样");
32.	    }
33.	
34.	    // 组合断言
35.	    @DisplayName("组合断言")
36.	    @Test
37.	    public void testAssertAll(){
38.	        Assertions.assertAll("AssertAll",
39.	                ()-> Assertions.assertTrue(true&& false),
40.	                ()-> Assertions.assertEquals(1,2));
41.	    }
42.	
43.	    // 异常断言 认为应该会出现异常
44.	    @DisplayName("异常断言")
45.	    @Test
46.	    public void testAssertException(){
47.	        Assertions.assertThrows(ArithmeticException.class, ()->{ int i=1/0;}, "没有抛出异常");
48.	    }
49.	
50.	
51.	
52.	    // 超时断言 判断有没有超时
53.	    @DisplayName("超时断言")
54.	    @Test
55.	    public void testAssertTimeOut(){
56.	        Assertions.assertTimeout(Duration.ofMillis(1000),()-> Thread.sleep(5000));
57.	    }
58.	
59.	    // 快速失败
60.	    @DisplayName("快速失败")
61.	    @Test
62.	    public void testFail(){
63.	        if(true){
64.	            Assertions.fail("测试 失败");
65.	        }
66.	    }
67.	}

前置条件(assumptions假设)

类似于断言,不同在于,不满足断言回事方法测试失败,而不满足的前置条件会使得的是方法的执行中止,前置条件可以看成是测试方法执行的前提,当条件不满足时,就没有继续执行的必要

1.	package com.msb;
2.	
3.	
4.	import org.junit.jupiter.api.Assertions;
5.	import org.junit.jupiter.api.Assumptions;
6.	import org.junit.jupiter.api.DisplayName;
7.	import org.junit.jupiter.api.Test;
8.	import org.springframework.boot.test.context.SpringBootTest;
9.	
10.	import java.time.Duration;
11.	
12.	@SpringBootTest
13.	@DisplayName("Junit5测试前置条件")
14.	class SpringbootMybatisplusApplicationTests4 {
15.	
16.	    @DisplayName("测试前提条件")
17.	    @Test
18.	    public void testAssumptions(){
19.	        // 假设为true,才会执行
20.	        Assumptions.assumeTrue(false,"结果不是true");
21.	        System.out.println("后面的测试代码前提条件");
22.	    }
23.	
24.	    @DisplayName("简单断言1")
25.	    @Test
26.	    public void testAssertions1(){
27.	        int add =10;
28.	        Assertions.assertEquals(6,add,"add结果计算错误");
29.	        System.out.println("后面的测试代码简单断言");
30.	    }
31.	
32.	
33.	}
34.	

嵌套测试

1.	package com.msb;
2.	
3.	
4.	import org.junit.jupiter.api.*;
5.	import static org.junit.jupiter.api.Assertions.*;
6.	
7.	import java.util.EmptyStackException;
8.	import java.util.Stack;
9.	
10.	
11.	
12.	@DisplayName("嵌套测试")
13.	class SpringbootMybatisplusApplicationTests5 {
14.	
15.	    Stack<Object> stack;
16.	
17.	    @Test
18.	    @DisplayName("is instantiated with new Stack()")
19.	    void isInstantiatedWithNew() {
20.	        new Stack<>();
21.	        // 外层的测试不能驱动内层的测试方法
22.	        assertNull(stack);
23.	    }
24.	
25.	    @Nested
26.	    @DisplayName("when new")
27.	    class WhenNew {
28.	
29.	        @BeforeEach
30.	        void createNewStack() {
31.	            stack = new Stack<>();
32.	        }
33.	
34.	        @Test
35.	        @DisplayName("is empty")
36.	        void isEmpty() {
37.	            assertTrue(stack.isEmpty());
38.	        }
39.	
40.	        @Test
41.	        @DisplayName("throws EmptyStackException when popped")
42.	        void throwsExceptionWhenPopped() {
43.	            assertThrows(EmptyStackException.class, stack::pop);
44.	        }
45.	
46.	        @Test
47.	        @DisplayName("throws EmptyStackException when peeked")
48.	        void throwsExceptionWhenPeeked() {
49.	            assertThrows(EmptyStackException.class, stack::peek);
50.	        }
51.	
52.	        @Nested
53.	        @DisplayName("after pushing an element")
54.	        class AfterPushing {
55.	
56.	            String anElement = "an element";
57.	
58.	            @BeforeEach // 内层Test可以驱动外层的BeforeEach
59.	            void pushAnElement() {
60.	                stack.push(anElement);
61.	            }
62.	
63.	            @Test
64.	            @DisplayName("it is no longer empty")
65.	            void isNotEmpty() {
66.	
67.	                assertFalse(stack.isEmpty());
68.	            }
69.	
70.	            @Test
71.	            @DisplayName("returns the element when popped and is empty")
72.	            void returnElementWhenPopped() {
73.	                assertEquals(anElement, stack.pop());
74.	                assertTrue(stack.isEmpty());
75.	            }
76.	
77.	            @Test
78.	            @DisplayName("returns the element when peeked but remains not empty")
79.	            void returnElementWhenPeeked() {
80.	                assertEquals(anElement, stack.peek());
81.	                assertFalse(stack.isEmpty());
82.	            }
83.	        }
84.	    }
85.	}

参数化测试

1.	package com.msb;
2.	
3.	
4.	import org.junit.jupiter.api.BeforeEach;
5.	import org.junit.jupiter.api.DisplayName;
6.	import org.junit.jupiter.api.Nested;
7.	import org.junit.jupiter.api.Test;
8.	import org.junit.jupiter.params.ParameterizedTest;
9.	import org.junit.jupiter.params.provider.MethodSource;
10.	import org.junit.jupiter.params.provider.ValueSource;
11.	
12.	import java.util.EmptyStackException;
13.	import java.util.Stack;
14.	import java.util.stream.Stream;
15.	
16.	import static org.junit.jupiter.api.Assertions.*;
17.	
18.	
19.	@DisplayName("参数化测试")
20.	class SpringbootMybatisplusApplicationTests6 {
21.	
22.	
23.	    @ParameterizedTest
24.	    @ValueSource(ints = { 1, 2, 3 })
25.	    void testWithValueSource(int argument) {
26.	        System.out.println(argument);
27.	        assertTrue(argument > 0 && argument < 4);
28.	    }
29.	
30.	
31.	
32.	    @ParameterizedTest
33.	    @MethodSource("stringProvider")
34.	    void testWithExplicitLocalMethodSource(String argument) {
35.	        assertNotNull(argument);
36.	    }
37.	
38.	    static Stream<String> stringProvider() {
39.	        return Stream.of("apple", "banana");
40.	    }
41.	
42.	
43.
44.	
45.	}

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:36:15  更:2022-07-03 10:38:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 7:13:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码