部署JiaKaoFE
前端部署很简单 直接点击index.html 浏览器打开即可
主键增长
configuration:
use-generated-keys: true
global-config:
db-config:
id-type: auto
Mapper接口报错 实际没啥问题
// 为了减少报错 我欺骗性加了 Componet 哈哈
//@Mapper
//@Component
老太太裹脚布继续开始
截止学习到 异常统一处理前 学习到一部分封装参数问题 所以这边记录一波 方便后续继续完善
创建Maven项目
配置仓库位置
Pom.xml
属性
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
配置一些库的version
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<druid.version>1.2.1</druid.version>
<mybatis-plus.version>3.4.1</mybatis-plus.version>
<tinypinyin.version>2.0.3</tinypinyin.version>
<springfox.version>3.0.0</springfox.version>
<swagger-models.version>1.6.2</swagger-models.version>
<mapStruct.version>1.4.1.Final</mapStruct.version>
<captcha.version>1.6.2</captcha.version>
<commons-io.version>2.7</commons-io.version>
</properties>
springboot项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!-- 权限控制 -->
<!-- <dependency>-->
<!-- <groupId>org.apache.shiro</groupId>-->
<!-- <artifactId>shiro-spring-boot-web-starter</artifactId>-->
<!-- <version>1.7.1</version>-->
<!-- </dependency>-->
<!-- 缓存 -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>${captcha.version}</version>
</dependency>
<!-- 对象转换 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapStruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapStruct.version}</version>
<scope>provided</scope>
</dependency>
<!-- 接口文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger-models.version}</version>
</dependency>
<!-- 后端校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 拼音 -->
<dependency>
<groupId>com.github.promeg</groupId>
<artifactId>tinypinyin</artifactId>
<version>${tinypinyin.version}</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- debug阶段 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>provided</scope>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
记得添加依赖 可以Maven安装一下哦
编写一个最简单的Application和Controller
配置数据库端口 创建 application.yml
项目肯定有数据库 先配置吧 不然pom.xml导入后 没用 没配置则会报错
application.yml:配置公共的部分
application-dev.yml:测试环境配置
yml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
profiles:
active: dev
mybatis-plus:
type-aliases-package: com.mj.jk.pojo
configuration:
use-generated-keys: true
global-config:
db-config:
id-type: auto
dev-yml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/new_jiakao?serverTimezone=GMT%2B8
server:
port: 8888
# servlet:
# context-path: /jiakao
logging:
level:
com.mj.jk.mapper: debug
# root:debug
jk:
cfg:
cors-origins:
- http://localhost:63342
创建Application
package com.mj.jk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JiaKaoApplication {
public static void main(String[] args) {
SpringApplication.run(JiaKaoApplication.class, args);
}
}
debug一下 默认端口是8080
创建简单控制器
设置port 和 context-path
server:
port: 8888
servlet:
context-path: /jiakao
链接一下数据库
自己连接一下
开始一个最简单的 crud
有个模版技术就是Eeay Code
pojo->po->DictType.java
DictType.java
public class DictType {
private Long id;
private String name;
private String value;
private String intro;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getIntro() {
return intro;
}
public void setIntro(String intro) {
this.intro = intro;
}
}
mapper->DictTypeMapper.java 接口
DictTypeMapper.java
public interface DictTypeMapper {
@Select("SELECT id, name, value, intro FROM dict_type")
List<DictType> list();
}
记得扫描哦 暂时放在Application.java 里面
@MapperScan("com.mj.jk.mapper")
service->DictTypeService.java [impl->DictTypeServiceImpl.java]
DictTypeService.java
DictTypeServiceImpl.java
public interface DictTypeService {
List<DictType> list();
}
@Service
@Transactional
public class DictTypeServiceImpl implements DictTypeService {
@Autowired(required = false)
private DictTypeMapper mapper;
@Override
@Transactional(readOnly = true)
public List<DictType> list() {
// 只读功能 用readOnly = true
return mapper.list();
}
}
接口注入报错 其实不影响编译的 解决方案加个@Component
Could not autowire. No beans of 'DictTypeMapper' type found.
controller->DictTypeController.java
DictTypeController.java
@RestController
@RequestMapping("/dictTypes")
public class DictTypeController {
@Autowired
private DictTypeService service;
@RequestMapping("/list")
public List<DictType> list() {
return service.list();
}
}
结果json:
JiaKao1
优化1
利用MyBatis-plus 开发项目 十分简约了
Mapper 继承 BaseMapper
public interface DictTypeMapper extends BaseMapper<DictType> {
}
service - 继承IService、ServiceImpl
public interface DictTypeService extends IService<DictType> {
}
@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements DictTypeService {
}
控制器内无需修改因为 Mybatis-plus 里面有list方法 还有其他很多方法哦。
优化2
添加mybatis-plus分页
我目前是复制课程里面的 不过有的新的版本了 具体可以百度哦
创建一个 MyBatisPlusCfg.java
把mapper扫描放到这里吧
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.mj.jk.mapper")
public class MybatisPlusCfg {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
// 当页数超过总页数时,自动跳回到第1页
innerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(innerInterceptor);
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}
注入优化
Field injuection is not recommended
参考
建议不能直接注入 修改成set方法或者构造器都可以
这个不建议的
@Autowired
private DictTypeService service;
用这个吧
private DictTypeService service;
@Autowired
public void setService(DictTypeService service) {
this.service = service;
}
这个也行
private final DictTypeService service;
@Autowired
public DictTypeController (DictTypeService service) {
this.service = service;
}
优化3
引入query
思路:引入 query 查询条件 把查询条件 也作为返回值 返回
PageQuery
import lombok.Data;
import java.util.List;
@Data
public class PageQuery {
private static final int DEFAULT_SIZE = 10;
private long page;
private long size;
/**
* 总记录数
*/
private long count;
/**
* 总页数
*/
private long pages;
private List<?> data;
public long getPage() {
return Math.max(1,page);
}
public long getSize() {
return (size < 1) ? DEFAULT_SIZE : size;
}
}
KeyWordQuery
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class KeywordQuery extends PageQuery{
private String keyword;
}
DictTypeQuery
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class DictTypeQuery extends KeywordQuery{
}
service中改写方法
DictTypeQuery list(DictTypeQuery query);
@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements DictTypeService {
@Override
public DictTypeQuery list(DictTypeQuery query) {
query.setData(list());
return query;
}
}
添加mapper方法进行一些条件选择
Could not autowire.NO beans of 'DictTypeMapper' type found.
解决一下吧 搞个@Compnent 在mapper中
Field injuection is not recommended
解决方案set 注入
Wrapper、Page
分页 Wrapper Page
Wrapper、LambdaQueryWrapper
@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements DictTypeService {
@Autowired
private DictTypeMapper mapper;
@Override
public DictTypeQuery list(DictTypeQuery query) {
LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
String keyword = query.getKeyword();
if (!StringUtils.isEmpty(keyword)) {
wrapper.like(DictType::getName, keyword).or()
.like(DictType::getValue, keyword).or()
.like(DictType::getIntro, keyword);
}
query.setData(list(wrapper));
return query;
}
}
LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
String keyword = query.getKeyword();
if (!StringUtils.isEmpty(keyword)) {
wrapper.like(DictType::getName, keyword).or()
.like(DictType::getValue, keyword).or()
.like(DictType::getIntro, keyword);
}
// 倒叙
wrapper.orderByDesc(DictType::getId);
搜索
http://localhost:8888/dictTypes/list?keyword=职业
page 、iPage
分页功能 记得添加mybatis的插件哦
Page<DictType> page = new Page<>(query.getPage(),query.getSize());
IPage iPage = mapper.selectPage(page, wrapper);
IPage 和 Page是一个对象
getRecords、getTotal、getPages、getCurrent、getSize
回填数据 数据、
query.setData(iPage.getRecords());
query.setCount(iPage.getTotal());
query.setPages(iPage.getPages());
query.setPage(iPage.getCurrent());
query.setSize(iPage.getSize());
优化4
enhance 继续封装query
初始化传入query
updateQuery
public class MpPage<T> extends Page<T> {
public MpPage(PageQuery query) {
super(query.getPage(), query.getSize());
}
public void updateQuery(PageQuery query) {
query.setCount(getTotal());
query.setPages(getPages());
query.setData(getRecords());
query.setPage(getCurrent());
query.setSize(getSize());
}
}
优化5
去掉 mapper 引入 用baseMapper
R 返回值
R.java Rs.java
统一异常处理
有个jsonable 接口 然后R 实现jsonable
拦截异常 处理 CommonExceptionHandler
JSONable
CommonException
CodeMsg
优化6
json null返回
jackson:
default-property-inclusion: non_null
还有jsonable
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
异常返回的json
response.setContentType("application/json; charset=UTF-8");