1、创建一个父类工程
1、删除src文件夹,并引入pom文件
<!-- springboot依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<!--依赖版本管理-->
<properties>
<mybatis-plus.version>3.3.2</mybatis-plus.version>
<druid.version>1.1.21</druid.version>
<fastjson.version>1.2.8</fastjson.version>
<commons-lang.version>2.6</commons-lang.version>
<commons-collections.version>3.2.2</commons-collections.version>
<commons-io.version>2.6</commons-io.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Java版本号-->
<java.version>1.8</java.version>
</properties>
<!--实际依赖-->
<dependencies>
<!--mybatis-plus启动器-->
<!-- mybatis PLus是对Mybatis进行封装 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--生成setter,getter-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--Spring Seucrity 加密模块-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<!-- yml配置处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 工具类依赖 -->
<!-- 阿里巴巴的Json转化工具-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 对基本数据类型的包装的工具类-->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<!-- 集合的工具处理-->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections.version}</version>
</dependency>
<!-- 文件io处理-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
</dependencies>
2、创建一个子工程(存放工具类)
创建一个子工程jhj-member-util,这个工程的作用是装一些工具类
右击父工程——>new——>Module(创建子类工程)
一、添加日志信息
在jhj-member-util工程的resources下面添加logback.xml文件
xml信息如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="stdout" />
</root>
</configuration>
二、添加restful工具类
创建com.jhj.member.base包,下面创建一个ResultEnum 构造器,
@Getter ——创建getter 方法,下面Lombok 介绍了这个
@AllArgsConstructor ——这个Lombok 里面的添加所有构造器的方法
package com.jhj.member.base;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.io.Serializable;
//创建枚举统一格式
//枚举就是针对一个个属性,创建一个个实例,类似于单例模式
@Getter
//所有参数的构造器
@AllArgsConstructor
public enum ResultEnum {
SUCCESS(200, "成功"),
ERROR(999, "失败");
private Integer code;
private String desc;
}
在创建的base包下面创建Result类
package com.jhj.member.base;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
/**
* @program: jhjmember
* @ClassName Result
* @description:
* @author:蒋皓洁
* @create: 2020-08-04 20:07
* @Version 1.0
**/
//返回结果
// implements Serializable 实现一下序列化接口
// 统一进行管理响应的数据
@Data
public class Result implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(Result.class);
/**
* 因为下面引入是静态的
*/
private static final long serialVersionUID = 1L;
/**
* 响应业务状态码
*/
private Integer code;
/**
* 是否正常
*/
private Boolean flag;
/**
* 响应信息
*/
private String message;
/**
* 响应中的数据
* 第三章 Api 接口模块搭建 mengxuegu-member-api
*/
private Object data;
public Result(Integer code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
this.flag = code == ResultEnum.SUCCESS.getCode() ? true : false;
}
public static Result ok() {
return new Result(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getDesc(),
null);
}
public static Result ok(Object data) {
return new Result(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getDesc(),
data);
}
public static Result ok(String message, Object data) {
return new Result(ResultEnum.SUCCESS.getCode(), message, data);
}
public static Result error(String message) {
logger.debug("返回错误:code={}, message={}", ResultEnum.ERROR.getCode(), message);
return new Result(ResultEnum.ERROR.getCode(), message, null);
}
public static Result build(int code, String message) {
logger.debug("返回结果:code={}, message={}", code, message);
return new Result(code, message, null);
}
public static Result build(ResultEnum resultEnum) {
logger.debug("返回结果:code={}, message={}", resultEnum.getCode(),
resultEnum.getDesc());
return new Result(resultEnum.getCode(), resultEnum.getDesc(), null);
}
public String toString() {
return JSON.toJSONString(this);
}
}
3、Lombok 介绍
官方网址: https://www.projectlombok.org/features/all
Lombok 工具提供一系列的注解,使用这些注解可以不用定义getter、setter、equals、构造方法等,可以消除
java代码的臃肿,它会在编译时在字节码文件自动生成这些通用的方法,简化开发 人员的工作。
@Getter 生成 getter 方法。
@Setter 生成 setter 方法。
@ToString 生成 toString 方法。
@NoArgsConstructor 生成无参构造方法。
@AllArgsConstructor 生成包含所有属性的构造方法。
@RequiredArgsConstructor 会一个包含常量,和标识了NotNull的变量的构造方法。生成的构造方法是私有
的private。
主要使用 @NoArgsConstructor 和 @AllArgsConstructor 两个注解,这样就不需要自己写构造方法,代码简
洁规范。
@Data 生成setter 、getter 、toString 、hashCode 、equals 和 @RequiredArgsConstructor 实现方
法。
@Accessors(chain = true) 生成的 setter 方法返回当前对象,如下:
类上加了 @Accessors(chain = true) ,对应生成的 setter 方法有返回值 this , 如下:
public Category setName(String name) {
this.name = name;
return this; // 会返回 this 当前对象
}
类上没加 @Accessors(chain = true) ,void 无返回值,如下:
public void setName(String name) {
this.name = name;
}
4、创建一个子工程(存放api)
创建jhj- member-api的子工程
一、创建jhj- member-api工程的启动类
创建com.jhj.member包下面创建MemberApplication 启动类
package com.jhj.member;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @program: jhjmember
* @ClassName MemberApplication
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 10:52
* @Version 1.0
**/
@SpringBootApplication
public class MemberApplication {
public static void main(String[] args) {
SpringApplication.run(MemberApplication.class,args);
}
}
二、创建mybatisPlus的工具类
com.jhj.member文件夹下面创建config文件夹,并创建MybaitisPlusConfig类,用于整合mybatis插件配置
参考mybatisPlus官网
https://baomidou.com/guide/page.html
下面是整合mybatisPlus的分页插件
package com.jhj.member.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @program: jhjmember
* @ClassName MybaitisPlusConfig
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 15:26
* @Version 1.0
* <p>
* mybatis插件配置
* mybatis插件配置
* mybatis插件配置
* <p>
* 参考mybatisPlus官网
* https://baomidou.com/guide/page.html
**/
@EnableTransactionManagement//开启事务管理
@MapperScan("com.jhj.member.mapper")//扫描mapper接口
@Configuration
public class MybaitisPlusConfig {
// 添加分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
三、创建实体类Member
其中注意的几点
1、@Accessors(chain = true),set方法有返回值
2、@Data、生成setter 、getter 、toString 、hashCode 、equals 和 @RequiredArgsConstructor 实现方法。
3、@TableName("")里面放数据库的表名称
4、@TableId(value = “id”, type = IdType.AUTO)
private Integer id;//TableId放在id上面,IdType.AUTO实现ID自增
5、Member implements Serializable 中Member 实现序列化接口,方便远程调用
package com.jhj.member.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* @program: jhjmember
* @ClassName Member
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 16:10
* @Version 1.0
**/
//lobok中的set方法有返回值,this
@Accessors(chain = true)
//生成get与set方法
@Data
//指定数据库哪张表
@TableName("tb_member")
//实现序列化接口,远程传输需要
public class Member implements Serializable {
// 定义数据库的Id,并设置Id自增长
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
// 卡号
private String cardNum;
// 姓名
private String name;
private Date birthday;
private String phone;
private Integer integral;
private Double money;
private String payType;
private String address;
}
四、创建mapper数据库连接层
com.jhj.member文件夹下面创建mapper文件夹,并在该文件夹下创建xml文件夹(用于存放xml文件)
在mapper文件夹下面,创建MemberMapper 类,
接口继承 MybatisPlus的BaseMapper泛型,这个里面封装了单表的增删改查的方法
package com.jhj.member.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jhj.member.entity.Member;
/**
* @program: jhjmember
* @ClassName MemberMapper
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 15:45
* @Version 1.0
**/
//接口继承 MybatisPlus的BaseMapper泛型,这个里面封装了单表的增删改查的方法
public interface MemberMapper extends BaseMapper<Member> {
}
在xml文件夹下面创建MemberMapper.xml文件,并namespace后引入com.jhj.member.mapper.MemberMapper
<?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.jhj.member.mapper.MemberMapper">
</mapper>
五、更改jhj- member-api工程的pom文件夹
加入的依赖如下
<dependencies>
<!--依赖工具模块包-->
<dependency>
<groupId>com.jhj</groupId>
<artifactId>jhj-member-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!--打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.jhj.member.MemberApplication</mainClass>
</configuration>
</plugin>
</plugins>
<!-- 引入扫描制定的目录下面的xml文件,如果xml文件放在resources下面则不需配置-->
<resources>
<resource>
<directory>sec/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
引入jhj-member-util工具工程
<dependency>
<groupId>com.jhj</groupId>
<artifactId>jhj-member-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
加入web启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
指定启动类
<plugins>
<!--打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.jhj.member.MemberApplication</mainClass>
</configuration>
</plugin>
</plugins>
下面这个关键
!!
将原本xml文件目录替换,本来指定的xml文件存放目录在src/main/resources下面
现在存放在mapper的xml文件夹下面,目录改变,所以这个配置一定要加上
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include> **/ *.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
六、添加application.yml文件
server:
port: 6666
# 数据源配置
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/mxg_member?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
#mysql8版本以上驱动包指定新的驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源其他配置, 在 DruidConfig配置类中手动绑定
initialSize: 8
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
mybatis-plus:
# 扫描实体类所在的包,这样在mapper.xml文件中就不用配置实体类全路径,直接写类名就行
type-aliases-package: com.jhj.member.entity
# 扫描xml包下面的xml文件
mapper-locations: classpath:com/jhj/member/mapper/xml/**.xml
# 配置日志级别
logging:
level:
com.jhj.member.mapper: debug #打印sql的日志信息
添加mybatisplus的配置,
mybatis-plus:
# 扫描实体类所在的包,这样在mapper.xml文件中就不用配置实体类全路径,直接写类名就行
type-aliases-package: com.jhj.member.entity
# 扫描xml包下面的xml文件
mapper-locations: classpath:com/jhj/member/mapper/xml/**.xml
打印日志级别
logging:
level:
com.jhj.member.mapper: debug #打印sql的日志信息
七、配置service层实现分页
在com.jhj.member创建service文件夹,并文件夹下面创建impl文件夹
service文件夹下面创建IMemberService 并继承IService< Member >
package com.jhj.member.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jhj.member.base.Result;
import com.jhj.member.entity.Member;
import com.jhj.member.req.MemberREQ;
//继承mybatisPlus的IService传入泛型
public interface IMemberService extends IService<Member> {
// Member的条件查询
Result seach( Long page, Long size,MemberREQ req);
}
在impl文件夹下面创建MermberServiceImpl 文件,继承IMemberService 接口,
但是!IMemberService 接口继承了IService接口,里面包含增删改查一些接口,这不可能一一去实现,所以
继承ServiceImpl实现父接口里面的方法来实现IService接口的方法。
baseMapper.selectPage接收一个分页对象和查询条件
baseMapper是MemberMapper一个实例,可以点进ServiceImpl里面去看、能看到大致下面这样的
ServiceImpl<M extends BaseMapper< T >, T>
protected M baseMapper;
前端传过来的请求参数封装到MemberREQ ,在将MemberREQ 的参数判断是否为空,并拼接成查询条件封装到query 中
package com.jhj.member.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jhj.member.base.Page;
import com.jhj.member.base.Result;
import com.jhj.member.entity.Member;
import com.jhj.member.mapper.MemberMapper;
import com.jhj.member.req.MemberREQ;
import com.jhj.member.service.IMemberService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
/**
* @program: jhjmember
* @ClassName MermberServiceImpl
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 17:33
* @Version 1.0
* 继承ServiceImpl实现父接口里面的方法
* 实现IMemberService里面的方法
* ServiceImpl是泛型,第一个是mapper的接口,第二个是实体类
**/
@Service
public class MermberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {
@Override
public Result seach(Long page, Long size, MemberREQ req) {
QueryWrapper query = new QueryWrapper();
if (req != null) {
// 判断入果不是空的则
if (StringUtils.isNotBlank(req.getName())) {
// query.like进行,模糊查询的条件拼接
query.like("name", req.getName());
}
if (StringUtils.isNotBlank(req.getCardNum())) {
query.like("card_num", req.getCardNum());
}
//查询生日
if (req.getBirthday() != null) {
query.eq("birthday", req.getBirthday());
}
if (StringUtils.isNotBlank(req.getPayType())) {
query.eq("pay_type", req.getPayType());
}
}
// IPage<Member> p封装一个分页对象 p
IPage<Member> p = new Page<>(page, size);
//baseMapper.selectPage接收一个分页对象和查询条件
// baseMapper是MemberMapper一个实例,可以点进ServiceImpl里面去看、
// ServiceImpl<M extends BaseMapper<T>, T>
// protected M baseMapper;
IPage<Member> data = baseMapper.selectPage(p, query);
// 返回data值,并以resultful格式返回
return Result.ok(data);
}
}
八、创建请求类,用于接收请求参数
创建的请求类,接收请求前端传过来的参数
package com.jhj.member.req;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @program: jhjmember
* @ClassName MemberREQ
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 17:18
* @Version 1.0
* 创建的请求类,接收请求参数
* 封装好这个请求,通过这个请求来接收参数
* 接收会员查询条件
* REQ:作为 request 简写,主要作用是把将查询条件请求参数封装为一个对象。
* 比如:会员姓名、卡号、支付类型、会员生日 作为条件,查询出对应分类数据。
**/
//实现序列化接口
@Data
public class MemberREQ implements Serializable {
/**
* 会员姓名
*/
private String name;
/**
* 卡号
*/
private String cardNum;
/**
* 支付类型('1'现金, '2'微信, '3'支付宝, '4'银行卡)
*/
private String payType;
/**
* 会员生日
*/
private Date birthday;
}
九、controller层
1、 @PostMapping("/list/seach/{page}/{size}")分页查询采用post方式传参,
2、 @RequestBody MemberREQ req,采用前端传参,并将参数封装在MemberREQ 这个类中,
package com.jhj.member.controller;
import com.jhj.member.MemberApplication;
import com.jhj.member.base.Result;
import com.jhj.member.entity.Member;
import com.jhj.member.req.MemberREQ;
import com.jhj.member.service.IMemberService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @program: jhjmember
* @ClassName MemberController
* @description:
* @author:蒋皓洁
* @create: 2020-08-05 11:48
* @Version 1.0
**/
@RestController
@RequestMapping("/Member")
public class MemberController {
// 打印日志
Logger logger = LoggerFactory.getLogger(MemberApplication.class);
@Autowired
private IMemberService memberService;
//采用post方式进行传参
@PostMapping("/list/seach/{page}/{size}")
public Result seach(@PathVariable("page") Long page,
@PathVariable("size") Long size,
@RequestBody MemberREQ req
) {
logger.info("查询会员列表:page={},size+{}", page, size);
return memberService.seach(page,size,req);
}
}
十、传参测试分页效果
使用postman工具测试
请求方式:post
请求地址:http://127.0.0.1:6666/Member/list/seach/1/3
查询结果如下
因为前端接收的为row,而不是records,为了适应前端,所以要对page方法做改变
十一、修改page方法,改变返回结果
在jhj-member util这个子工程(存放工具)的下面的base包下面创建Page类
1、 Page< T>继承mybatisplus包下面的Page
2、覆写父类的方法getRecords使得getRecords返回值为null,records值为null
3、复写父类Page方法
4、自定义一个getRows()方法,返回super.getRecords();,返回父类getRecords()的值,
5、如果定义的是getRows()方法,则返回rows,如果定义的是getRowws()方法,则返回rowws,
package com.jhj.member.base;
import java.util.List;
/**
* @program: jhjmember
* @ClassName Page
* @description:
* @author:蒋皓洁
* @create: 2020-08-17 18:17
* @Version 1.0
**/
public class Page<T> extends com.baomidou.mybatisplus.extension.plugins.pagination.Page {
// 返回父类的getRecords()的值,也就是查询的limit的值
public List<T> getRows() {
return super.getRecords();
}
// 使得返回的record数据为空
public List<T> getRecords() {
return null;
}
// 调用父类的方法
public Page(long current, long size) {
super(current, size);
}
}
修改引入的page