springboot特点:基于编程式和注解式配置,习惯(约定)优于配置。
springboot优势:
①:springboot让配置更简单
springboot推出了starter组件,即自动配置器,我们只需要在应用中引入相关组件的starter即可完成配置,从spring应用中复杂而繁琐的配置中解脱出来,实现项目的快速搭建。
springboot官方提供的starter命名格式为spring-boot-starter-×××
第三方提供的starter命名格式为×××-spring-boot-starter
②:springboot让开发更简单
springboot支持内嵌容器,如tomcat,jetty,应用自带服务器,直接启动应用即可,无需额外安装服务器。
springboot提供了强大的开发工具包,支持热启动。
③:springboot让测试更简单
springboot内置了常用的测试框架,仅需引入一个spring-boot-starter-test依赖包,即可进行各种测试
④:springboot让部署更加简单
springboot应用默认打包jar包
⑤:springboot让监控更简单
springboot就是一款自带监控的框架,专门提供了监控组件来完成这个工作。
眺望springcloud:
spring为应对互联网应用的要求(高可靠,高并发,能够负载均衡等),基于springboot推出了微服务框架springcloud,因此springcloud完全建立在springboot之上。
二. 开发一个springboot应用,引入依赖
org.springframework.boot
spring-boot-starter-parent
2.6.4
org.springframework.boot
spring-boot-starter-web
2.6.4
org.springframework.boot
spring-boot-devtools
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.1
mysql
mysql-connector-java
8.0.27
org.springframework.boot
spring-boot-starter-test
com.github.pagehelper
pagehelper-spring-boot-starter
1.4.1
org.springframework.boot
spring-boot-maven-plugin
2.6.4
parent:spring-boot-starter-parent:引入springboot父项目:该父项目中内置了很多习惯性配置和jar版本号之间的关联
dependencies:
①:spring-boot-starter-web:web组件
②:spring-boot-devtools:引入springboot开发工具包,可以支持热启动
③:mybatis-spring-boot-starter
④:mysql-connector-java
⑤:spring-boot-starter-test:springboot测试组件
⑥:pagehelper-spring-boot-starter:分页组件
build:
spring-boot-maven-plugin:引入springboot构建插件,用于打包生成可执行jar文件
三. 开发springboot启动类import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//说明本应用为springboot应用,
// 而且还说明这是一个springboot的启动类,同时还说明这是一个配置类
//而且还是一个自动配置类
//主类所在的包,就是springboot应用的根包
//在springboot应用中,一般所有的组件如:controller,service,和dao等对象都应该在应用根包下或其子包下
@SpringBootApplication
//自动扫描映射器,并放入spring容器
@MapperScan("org.xupt.ygq.demo.dao")
public class MyApp {
public static void main(String[] args) {
//该语句为springboot应用的启动语句
SpringApplication.run(MyApp.class,args);
}
}
两个注解:
①:@SpringBootApplication:
说明本应用为springboot应用,而且还说明这是一个springboot的启动类,同时还说明这是一个配置类。
主类所在的包,就是springboot应用的根包,在springboot应用中,一般所有的组件如:controller,service,和dao,等对象都应该在应用根包或者根包的子包下面
②:@MapperScan:自动扫描映射器(也就是dao包),并存放在spring容器中
一条语句:
SpringApplication.run(MyApp.class,args);启动语句!!!
四. 配置application.properties资源文件#配置内置服务器端口号,默认为8080 server.port=9999 #配置根日志的输出级别,默认为info logging.level.root=info #配置org.xupt.ygq.demo.dao包下的日志输出级别为trace,可以打印mybatis映射器执行结果 logging.level.org.xupt.ygq.demo.dao=trace logging.level.org.xupt.ygq.demo=debug #配置springmvc的日志 logging.level.web=trace #配置数据源 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/wddb spring.datasource.username=root spring.datasource.password=123456 #配置mybatis #配置映射文件位置,在类路径下,mapper目录下的任意层级文件夹下的以.xml结尾的文件 mybatis.mapper-locations=classpath:mapper*.xml #pagehelper #配置方言,即配置使用哪一个数据库 pagehelper.helper-dialect=mysql #分页的合理化配置,即如果请求页码不合理时,自动合理化,比如:请求-9页,自动合理化成第一页 pagehelper.reasonable=true五.因为要做分页查询,封装分页 5.1 分页类
import java.util.List; public class Page{ //当前页 private Integer current; //首页 private Integer first; //上页 private Integer pre; //下页 private Integer next; //尾页 private Integer last; //每页最大记录数 private Integer pageSize; //总记录数 private Long total; //总页数 private Integer pages; //当前页实际记录数 private Integer currSize; //当前页数据记录 private List list; public Integer getCurrent() { return current; } public void setCurrent(Integer current) { this.current = current; } public Integer getFirst() { return first; } public void setFirst(Integer first) { this.first = first; } public Integer getPre() { return pre; } public void setPre(Integer pre) { this.pre = pre; } public Integer getNext() { return next; } public void setNext(Integer next) { this.next = next; } public Integer getLast() { return last; } public void setLast(Integer last) { this.last = last; } public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public Long getTotal() { return total; } public void setTotal(Long total) { this.total = total; } public Integer getPages() { return pages; } public void setPages(Integer pages) { this.pages = pages; } public Integer getCurrSize() { return currSize; } public void setCurrSize(Integer currSize) { this.currSize = currSize; } public List getList() { return list; } public void setList(List list) { this.list = list; } @Override public String toString() { return "Page{" + "current=" + current + ", first=" + first + ", pre=" + pre + ", next=" + next + ", last=" + last + ", pageSize=" + pageSize + ", total=" + total + ", pages=" + pages + ", currSize=" + currSize + ", list=" + list + '}'; } }
类定义成泛型的:因为查询到的结果list,里面装的对象是什么,是不确定的。
5.2 分页参数public class PageParam {
private Integer pageNum=1;//请求页码
private Integer pageSize=5;//每页最大记录数
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
在进行分页之前要先设置分页参数(包含两个属性,页码pageName和每页记录数pageSize)
PageHelper.startPage(pageParam);
5.3 分页查询apiimport com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.common.page.QueryAction;
import java.util.List;
public class Utils {
public static Page getPage(PageParam pageParam, QueryAction queryAction){
//在查询之前设置分页参数,再执行查询和设置分页参数之间不能有其他的查询。
//该方法用于设置分页参数对象(含有页码pageName和每页记录数pageSize两个属性)
PageHelper.startPage(pageParam);
List list = queryAction.executeQuery();//执行一个查询,获得List集合
//紧挨在查询之后构造分页信息对象
PageInfo pageInfo = new PageInfo<>(list);
Page page = new Page<>();
page.setCurrent(pageInfo.getPageNum());//当前页
page.setFirst(1);//首页
page.setPre(pageInfo.getPrePage());//上一页
page.setNext(pageInfo.getNextPage());//下一页
page.setLast(pageInfo.getPages());//最后一页
page.setPageSize(pageInfo.getPageSize());//每页最大记录数
page.setTotal(pageInfo.getTotal());//总记录数
page.setPages(pageInfo.getPages());//总页数
page.setCurrSize(pageInfo.getSize());//当前页实际记录数
page.setList(pageInfo.getList());//当前页数据记录
return page;
}
}
定义一个泛型生成分页对象的泛型类:(两个参数)
①:PageParame:声明分页参数,
②:QueryAction:一个查询行为的接口,表示要进行分页的查询行为
其中要注意分页信息对象:PageInfo:我们对于自己的分页对象的设置基于分页信息对象
最后返回一个分页对象:
5.4 定义抽象的查询行为import java.util.List; public interface QueryAction5.5 封装返回结果{ public List executeQuery(); }
public class Result六. 开发model和dto{ public static final int CODE_OK = 200; public static final int CODE_ERR_BUSINESS = 500; public static final int CODE_ERR_SYS = 530; public static final int CODE_ERR_UNLOGINED = 520; public static Result ok(){ return new Result(true,CODE_OK,null,null); } public static Result ok(String message){ return new Result(true,CODE_OK,message,null); } public static Result ok(T data){ return new Result(true,CODE_OK,null,data); } public static Result ok(String message,T data){ return new Result(true,CODE_OK,message,data); } public static Result err(int errCode ,String message){ return new Result(false,errCode,message,null); } public static Result err(int errCode ,String message,T data){ return new Result(false,errCode,message,data); } private boolean success;//是否成功 private int code;//200 成功 500 业务失败,530 系统错误,520 未登录 private String message;//概要信息 private T data; public Result(boolean success, int code, String message, T data) { this.success = success; this.code = code; this.message = message; this.data = data; } public boolean isSuccess() { return success; } public int getCode() { return code; } public String getMessage() { return message; } public T getData() { return data; } }
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class Employee {
private String e_id;
private Integer d_id;//部门编号
private Integer e_sex;
private String e_name;
private Date e_birth;
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public Integer getD_id() {
return d_id;
}
public void setD_id(Integer d_id) {
this.d_id = d_id;
}
public Integer getE_sex() {
return e_sex;
}
public void setE_sex(Integer e_sex) {
this.e_sex = e_sex;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
//声明生成json的时间格式和时区
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT=8")
public Date getE_birth() {
return e_birth;
}
public void setE_birth(Date e_birth) {
this.e_birth = e_birth;
}
@Override
public String toString() {
return "Employee{" +
"e_id='" + e_id + ''' +
", d_id=" + d_id +
", e_sex=" + e_sex +
", e_name='" + e_name + ''' +
", e_birth=" + e_birth +
'}';
}
}
import java.util.Date;
//表示封装查询条件的dto
public class EmployeeQueryDto extends PageParam {
private String e_id;
private Integer d_id;//部门编号
private Integer e_sex;
private String e_name;
private Date e_birth_start;
private Date e_birth_end;
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public Integer getD_id() {
return d_id;
}
public void setD_id(Integer d_id) {
this.d_id = d_id;
}
public Integer getE_sex() {
return e_sex;
}
public void setE_sex(Integer e_sex) {
this.e_sex = e_sex;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")//对前端传来的时间格式说明
public Date getE_birth_start() {
return e_birth_start;
}
public void setE_birth_start(Date e_birth_start) {
this.e_birth_start = e_birth_start;
}
public Date getE_birth_end() {
return e_birth_end;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")//对前端传来的时间格式说明
public void setE_birth_end(Date e_birth_end) {
this.e_birth_end = e_birth_end;
}
}
dto继承了PageParam:继承了他的分页参数,方便一起从前端页面传回数据。这样子就可以把dto和分页参数融合在一起进行参数传递。
七. 开发控制器组件import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xupt.ygq.demo.common.Result;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.dto.EmployeeQueryDto;
import org.xupt.ygq.demo.model.Employee;
import org.xupt.ygq.demo.service.EmpService;
@RestController
public class MyController {
@Autowired
private EmpService empService;
@GetMapping("/emp")
//分页查询需要分页参数,dto继承了分页参数类,所以他里面就有分页参数
public Result empList(EmployeeQueryDto dto){
Page page = empService.getEmpPage(dto);
return Result.ok(page);
}
}
三个注解:
①:RestController
②:Autowired
③:GetMapping
定义处理方法:传递参数
八. 开发业务对象import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.model.Employee;
public interface EmpService {
public Page getEmpPage(PageParam pageParam);
}
这里为什么用PageParam接受呢,因为dto对象时PageParam的子类,所以用父类型接收。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xupt.ygq.demo.common.Utils;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.dao.EmpDao;
import org.xupt.ygq.demo.model.Employee;
import org.xupt.ygq.demo.service.EmpService;
@Service//表示本对象是业务对象,并且受spring容器管理
@Transactional//声明本业务对象的所有方法都是事务性的
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpDao empDao;
// @Override
// public Page getEmpPage(PageParam pageParam) {
// QueryAction action =()->{
// return empDao.findEmpList();
// };
//
// return Utils.getPage(pageParam,action);
// }
@Override
public Page getEmpPage(PageParam pageParam) {
//QueryAction action =()-> empDao.findEmpList();
return Utils.getPage(pageParam,()-> empDao.findEmpList(pageParam));
}
}
实现类里面有一个重要的点:就是调用分页查询api的时候,参数QueryAction接口的实现是内部类,再加上接口中只有一个方法,所以可以简化书写
九. 开发持久层import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.model.Employee;
import java.util.List;
public interface EmpDao {
//@Select("select * from t_emp")
public List findEmpList(PageParam pageParam);
}
持久层返回的List在Service实现中被封装成了page对象。
十. 开发mapperselect * from t_emp and e_id like concat('%',#{e_id},'%') and e_name like concat('%',#{e_name},'%') and e_sex=#{e_sex} and d_id=#{d_id} and e_date >= #{e_date_start} and e_date <= #{e_date_end}
整个分页由插件完成!!!
mapper需要在application.properties中配置映射路径。
还需要注意映射的包:
十一. 测试



