Java学习-springboot-RESTful-mybatisplus-swagger
------------------23年12月9日学习记录-------------------
springboot
由于新版本的idea自带的springboot initializer不支持jdk1.8和springboot2,但是大部分的应用还是基于jdk1.8和springboot2,所以需要自己导入依赖
application.properties为springboot核心配置文件且只有这一个配置文件
配置文件里可以设置启动端口,默认端口8080
框架依赖
父依赖
这个依赖是放在dependency外的,是将springboot父依赖里的相关依赖导入我们这个项目,有助于减少我们依赖导入的数量
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/>
</parent>
springMVC依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
test依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
热部署依赖
热部署可以让我们在代码修改时自动重启项目,可以提高开发效率
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
application.properties里添加
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=src/main/java
paths设置哪些包下的代码更改时执行热部署
插件依赖
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
启动类注解
需要在启动类加上@SpringBootApplication注解
启动springboot项目就从这启动
@MapperScan就是扫描这些包下的mapper注解
@SpringBootApplication
@MapperScan("org.feibelman.mapper")
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class);
}
}
控制层注解
定义controller-@RestController
文件上传
- 前端页面表单需要设置enctype = “multipart/form-data”
- 控制器参数类型为MultipartFile
- 通过httpServletRequest参数的getServletContext方法可以获取到项目运行的上下文地址
- 通过MultipartFile对象的tansferTo方法并传入File类型对象即可将上传的文件写入磁盘
拦截器
定义拦截器配置类
@Configuration
public class WebInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new WebInterceptor()).addPathPatterns("/hello");
}
}
其他的都是固定套路,使用的时候只需要注意addPathPatterns里的url,这就是我们要拦截的请求路径
- /hello/* 代表hello下一级的请求会被拦截
- /hello/** 代表hello下的所有请求都会被拦截
定义拦截器类
public class WebInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("WebInterceptor");
return true;
}
}
preHandle就是在Controller处理请求前执行,还有postHandler,afterCompletion
RESTful风格
用来规范前端对后端请求的方式
- post:提交资源,比如创建一个用户
- get:获取资源,比如获取用户信息
- put:修改资源
- patch:修改部分资源
- delete:删除资源,比如删除用户
springboot中的RESTful实现
在RESTful架构中,url中不应包含动词,只包含名词,名词通常与数据库表对应
Method | 接口 | 接口说明 |
---|---|---|
post | /user | 创建用户 |
get | /user/id | 根据id查询用户 |
put | /user | 更新用户 |
delete | /user/id | 根据id删除用户 |
具体实现
@RestController
public class UserController{
@GetMapping("user/{id}")
public String getUserById(@PathVariable int id){
}
@PostMapping("/user")
public String save(User user){
}
@PutMapping("/user")
public String update(User user){
}
@DeleteMapping("/user/{id}")
public String deleteById(@PathVariable int id){
}
}
由于id是会变的,所以可以使用可变地址来实现,方法参数加入@PathVariable注解且名字与传入的名字相同即可获得地址栏的值
MybatisPlus
导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
添加配置到application.properties
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatistest?userSSL=false
spring.datasource.username=root
spring.datasource.password=20030317
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
基本使用
我们只需要定义接口,不需要实现类,在Controller中使用的时候只需要使用@Autowired注解完成自动装配即可
@Mapper
public interface XufeiMapper extends BaseMapper<Xufei> {
@Select("select * from xufei where id = #{id}")
List<Xufei> find(int id);
}
方法的参数id会赋值给#{id}
@Select注解为Mybatis所有,但是BaseMapper为MyBatisPlus所有,MybatisPlus可以省去写一些基本方法,使用BaseMapper内置的方法必须满足参数的一致性,如果实体类中有表中不存在的列就必须使用@TableField(exist=false)注解在实体类中的特有属性上。
注解 | 功能 |
---|---|
@Insert | 实现插入 |
@Update | 实现更新 |
@Delete | 实现删除 |
@Select | 实现查询 |
之前学习Mybatis的时候没有用注解来写sql语句,用的是mapper.xml来写sql语句,现在想想真的是太麻烦了。
多表查询
@Mapper
public interface TestMapper extends BaseMapper<Test> {
@Select("select * from test")
@Results({
@Result(column = "name",property = "name"),
@Result(column = "password",property = "password"),
@Result(column = "xid",property = "xufeis",javaType = List.class,
many = @Many(select = "org.feibelman.mapper.XufeiMapper.find"))
})
List<Test> find();
}
使用场景比如用户有多个订单,那么我就给用户实体类定义订单这么一个列表属性,这个属性肯定是要加@TableField(exist=false),我想在查询用户的时候也要根据用户id去订单表里查询相应的订单并注入到用户实体对象中,就需要使用到多表查询。
@Results相当于在实现ResultMapper,@Result对应每一个列和属性的对应,表示哪个列的值应该放在注入到哪个属性里
主要是最后一个,Test实体类里有一个xid属性,表中也有一个xid列,这个列是test表的主键,是xufei表的外键,所以才有一个xid对应多个xufei,并且Test实体类里有一个xufeis属性,这个属性的类型是列表,里面存储的是Xufei实体类对象。
many属性是核心,@Many注解并调用了XufeiMapper里面的find方法,这个方法是根据id查询Xufei,注解会自动将xid的值注入到方法里,然后返回数据放入xufeis属性里。
23/12/10更新
@many注解用于一对多的情况,由于一个test有多个xufei,所以用到@many,那么如果是一个test只对应一个xufei,那么就要用到@One注解,如下
@Mapper
public interface TestMapper extends BaseMapper<Test> {
@Select("select * from test")
@Results({
@Result(column = "name",property = "name"),
@Result(column = "password",property = "password"),
@Result(column = "xid",property = "xufei",javaType = Xufei.class,
one = @One(select = "org.feibelman.mapper.XufeiMapper.selectById"))
})
List<Test> find();
}
类型改为Xufei.class,注解改为One,select语句改为查询一条记录的selectById。
分页查询
官网文档:官网文档
这个在网页里一般都会用到,数据肯定得是一页一页显示
- 定义MybatisPlusConfig类
- 给MybatisPlusConfig类加上@Configuration注解
- 创建paginationInterceptor方法,返回类型为MybatisPlusInterceptor
- MybatisPlusConfig类如下
@Configuration
public class MybatisPlusConfig{
@Bean
public MybatisPlusInterceptor paginationInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
这个类的代码是固定的,只需要修改DbType,根据自己的数据库类型来更改,我用的MYSQL,这个类有用的前提是加了@Configuration和@Bean注解,类的名字没有什么关系。
- 定义findByPage方法
@GetMapping("/test/findByPage")
public IPage findByPage(){
Page<Test> page = new Page<>(0,2);
IPage ipage = testMapper.selectPage(page,null);
return ipage;
}
需要先创建一个Page的对象,放入两个参数,0表示从第0条数据开始,2表示一页有2条数据,然后调用mapper里面的selectPage方法,传入page对象和null,第二个参数是条件查询相关的,现在没啥用,得到IPage类型引用ipage,返回ipage。
Springboot会自动将ipage转为json类型,前端页面收到的数据里面有很多条目的,不仅仅是查到的几条数据,还包括了起始条数,一页的大小等等
需要注意的是,selectPage这个方法是在配置完Config后能直接用的,不需要自己定义
Swagger
Swagger可以帮我们生成Controller层的api文档,这样和前端交互的时候就很方便,只需要通过这个文档就能知道后端Controller有哪些方法,每个方法的作用
效果图:
- 导入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
-----------swagger2.9.2匹配springboot2.5.6-------------
-----------swagger3.0.0匹配springboot2.6.5------------
2. 编写配置类SwaggerConfig
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("org"))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("项目演示APi")
.description("演示项目")
.version("1.0")
.build();
}
}
模板是比较固定的,需要根据实际情况修改的地方:
- basePackage 哪个包下的Controller,这里org是我这个项目的根目录
- title 标题
- description 项目描述
- version 版本
- 可以自定义给Controller添加注释
@Api(value = "jiekou",tags = {"jiekou"})
通过在Controller类上添加@Api实现
- 启动项目
- 在浏览器地址栏输入http://localhost:8080/swagger-ui.html
------------23年12月9日学习内容记录------