1.创建springboot项目
Maven类型+Lombok依赖+Spring Web 依赖+MySQL Driver依赖 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springBoot-Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springBoot-Test</name>
<description>springBoot-Test</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--导入Mybatis坐标-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!--导入mybatis-plus坐标-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!--导入数据库druid坐标-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
<!--简略get,set方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!--模版引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.springboottest.SpringBootTestApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2.idea建表()
1. 首先点击右侧的数据库->右击@localhost->点击新建->查询控制台 2. 选择在那个数据库建表 use `数据库名`
use `数据库名`;
create table `表名`(
`id` INTEGER primary key auto_increment comment '主键id',
`type` varchar(20) comment '书籍类型',
`create_time` timestamp comment '创建时间',
`update_time` timestamp comment '修改时间',
`version` INTEGER comment '版本号' (注意最后没有,)
)default charset = utf8 comment '书籍表';
insert into `表名`(`type`)
values
('科幻'),
('玄幻'),
('架空');
这里一连写入几个,不要写一个insert一个。
3.配置yml文件
spring: datasource: # 如果使用com.mysql.jdbc.Driver爆红,已经被弃用 driver-class-name: com.mysql.cj.jdbc.Driver # 时区serverTimezone根据自己需要修改 url: jdbc:mysql://127.0.0.1:3306/数据库名?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 username: 用户名 password: 密码 mybatis-plus: # 设置mybatis映射器(就是xml文件的路径) mapper-location: classpath:mapper/*.xml # 开启mybatis-plus运行日志 (建议开启) configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 如果密码忘记可以查看他的文章: https://www.cnblogs.com/murmansk/p/17648639.html
4.目录结构如下
config层+controller层+dao层+mapper层+service层
简单了解一下结构:
Java(dao、service、controller)解释:
1.dao层:持久层(Repository 或 DAO:数据访问层) *负责与数据库进行联络的一些任务都封装在此 *dao层属于一种底层,比较基础的操作,具体到对于某个表的CRUD操作,也就是说某个dao一定是和数据库某一张表对应的。 *mapper设计dao层的接口(属于dao层),然后在spring的配置文件中定义此接口的实现类。 *建议只做原子操作
2.service层: 服务层 *对一个或多个dao进行再次封装的事务控制。 *service层负责逻辑应用,同样先设计接口,在设计其实现类,接着在设计spring的配置文件中配置其实现的关联。 *封装service层业务逻辑有利于通用业务逻辑的独立性和重复利用性。程序显得非常简洁。
3.controller层:控制层 * 控制层负责请求转发,接受页面传递过来的请求,传给service层处理,接到响应,再传给页面。
关系:控制层(controller)接受页面传递过来的参数,调用接口传递给中间层也就是业务层(service),业务层(service)调用持久层的接口(dao层:mapper),对数据库进行操作,返回操作结果,controller响应给页面。
5. CRUD操作
1.编写底层(实体类)
@Data // 提供get、set、toString等方法
@AllArgsConstructor // 提供全参构造
@NoArgsConstructor // 提供无参构造
// 如果不使用这个依赖,默认映射(首字母小写)寻找表名,当实体类与
// 表名不一致会出现错误
@TableName("表名")
public class BooK {
@TableId(value = "id",type = IdType.AUTO)
// 设置主键并自增(这里只是告诉mybatis,表中还是要设置主键自增的)
private Integer id;
@TableField(value = "type")
private String type;
@TableField(value = "create_time",fill = FieldFill.INSERT)
/* value: 指定java属性createTime对应数据库字段,代表一种映射
fill: 表示在插入记录时,该字段应该被自动填充
使用自动填充需要实现MetaObjectHandler 接口,并重写方法*/
private Date createTime;
@TableField
(value = "update_time",fill = FieldFill.INSERT_UPDATE)
// fill: 表示在插入和更新记录时,该字段自动更新
private Date updateTime;
@Version
// 乐观锁:当同时更新某个记录会保留第一个更新值
private Integer version;
}
编写mapper: 直接继承BaseMapper,接口中封装了一系列 CRUD 常用操作
public interface BookMapper extends BaseMapper<实体类> {
}
我们需要在启动类添加MapperScan注解。指定mapper扫描路径,指定后就不用再mapper层写@Mapper注解(建议)
@SpringBootApplication
@MapperScan("com.example.mapper")
//sources root下的mapper路径 作用:自动注册映射器接口为spring Bean
public class SpringBootDemo1Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo1Application.class,args);
}
}
2.编写业务层(service) IService内部进一步封装BaseMapper接口的方法,使用时可以通过mapper类,也可以通过service。
public interface BookService extends IService<实体类> { }
service实现类记得加@service注解
@Service
public class BookTestServiceImpl implements UserTestService{
@Autowired // 根据类型找实现类bean
private GameMapper gm;
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
}
3.编写控制层(controller)
@RestController
@RequestMapping("book/test") // 映射路径
public class BookController {
@Autowired
private BookService bs;
}
无参,@RequestParam 和@PathVaiable的情况下使用GetMapping 如果传的参数是@RequestBody ,多参或者传对象的情况下使用@PostMapping注解
6.分页插件
1.配置分页插件 编写一个配置类,使用@Bean注解将其交给spring容器管理
@Configuration // 加入这个才能被spring扫描
@Component // 注入spring管理
public class MPConfig {
/** 分页插件* */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
2.定义一个包装类,保存分页所需要的数据
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GameFy {
private Integer current; // 当前页
private Integer size; // 每页记录量
private Long total; // 记录总量
private List<Game> game; // 记录信息
}
3.service层自定义接口
public interface BookService extends IService<Book> { BookPage pagelist(Integer current,Integer size); }
3.service实现类调用接口 编写分页代码:调用mybatis-plus提供的分页方法(selectPage),会将数据封装到Page对象中。
service实现类:
@Override
public BookPage pageList(Integer current,Integer size){
BookPage bg = new BookPage();
Page<Book> book = new Page<>(current,size);
gm.selectPage(book,null);
// 如果没有其他条件,用null 作用执行分页查询,并把结果返回给book
bg.setCurrent(current);
bg.setSize(size);
bg.setTotal(book.getTotal());
bg.setBook(book.getRecords());// 获取所需要的实体类数据
return bg;
}
4.controller层:
@GetMapping("pagelist")
public BookPage pageList(@RequestParam("current") Integer current,@RequestParam("size") Integer size){
return bs.pageList(current,size);
}
7.自动填充数据功能
比如:数据创建时间和修改时间。mybatis-plus支持自动填充这些字段的数据。 这个在上面已经提到过,只是不完善,下面给出完整步骤。
1.在实体类中使用@TableField注解(映射字段、condition预处理WHERE实体条件自定义运算规则)上面已经写过。
2.自定义类,实现MetaObjectHandler接口,并重写方法。 注意这里的Date():java.util不是sql
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/*
* 自定义填充内容,根据属性名去填充数据*/
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject,"create_time",Date.class, new Date()); // 插入数据时实现创建时间自动插入
this.strictInsertFill(metaObject,"update_time",Date.class, new Date());// 插入数据时实现更新时间自动插入
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject,"update_time",Date.class, new Date()); // 更新数据时实现更新时间自动更新
}
}
8.乐观锁功能
通过version实现(上面提到过) 实现思路: 1.取出数据时,获取当前version(默认为1) 2.更新数据时(version会递增),带上这个version 3.执行更新时,判断此时version是否等于之前的version 4.如果version不对,更新失败
配置乐观锁插件:
@Configuration @Component public class MyConfig { @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
2.定义一个数据库字段verison(上面已经做过) 3.使用@Version注解标注对应的实体类。通过@TableField进行数据自动填充
service实现类: @Version @TableField(fill = FieldFill.INSERT) private Integer version;
4.简单测试:
@Test public void test() { Book book = gm.selectById(1); book.setType("tom"); gm.updateById(book); book.setName("jarry"); gm.updateById(book); }
swagger-ui:接口测试
用于接口测试:前后端问题及时协商,尽早解决
1.添加Maven依赖:
<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>
2.配置swagger,编写配置类SwaggerConfig
@Configuration @EnableSwagger2 public class SwaggerConfig{ }
yml文件:解决springboot和swagger冲突
spring: mvc: pathmatch: matching-strategy: ant_path_matcher
3.访问测试 :http://localhost:8080/swagger-ui.html ,(这个页面是自动生成的)可以看到swagger的界面;8080改成你自己的端口号
4.基本实现swagger
@Configuration // 配置类
@EnableSwagger2 // 开启swagger2的自动配置
public class SwaggerConfig {
/*swagger2*/
@Bean //配置docket以配置Swagger具体参数
public Docket docket() {
/*构建Docket通过select()方法配置扫描接口*/
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(true) //配置是否启用Swagger,如果是false,在浏览器将无法访问
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller")) // controller路径
// 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口
//.paths(PathSelectors.ans("/kuang/**"))
.build();
}
/*通过apiInfo()属性配置文档信息:*/
private ApiInfo apiInfo(){
//下面的这套配置就把原来的static代码块覆盖掉:联系人访问链接、联系人邮箱
Contact contact = new Contact("***", "https://baidu.com/", "3153734397@qq.com");
return new ApiInfo(
"***的API文档",
"学习使用swagger2",
"v1.0",
"https://baidu.com/", // 组织链接
contact, // 联系人信息
"Apache 2.0许可",
"https://baidu.com",// 许可连接
new ArrayList<>() // 扩展
);
}
/*配置API分组,如果想多创几个分组,多写几个就可以*/
@Bean
public Docket docket1(){
return new Docket(DocumentationType.SWAGGER_2).groupName("分组");
}
@Bean
public Docket docket2(){
return new Docket(DocumentationType.SWAGGER_2).groupName("学习");
}
}
@Api:放在请求的类上,与@RestController并列,说明该类的作用 @Api(value = "订单模块") @RestController public class OrderController {
}
@ApiOperation:说明方法的作用 @ApiOperation(value = "查询所有信息")
@ApilmplicitParams、@ApilmpllicitParam: 说明参数的作用
@ApiOperation(value = "根据姓名模糊查询") @ApiImplicitParam(name="username",value="用户名",required=true) @GetMapping("likeName") public List<Game> listName(@RequestParam("username") String username){ return bs.LikeUserName(username); } @ApiOperation(value = "分页信息") @ApiImplicitParams({ // paramType:以什么类型传递信息,目前是表单形式,注意如果发生错误,可能就是这里格式的问题 @ApiImplicitParam(name="current",value="当前页",required=true), @ApiImplicitParam(name="size",value="每页记录数",required=true,paramType="query") }) @GetMapping(path = "pagelist") public GameFy pageList(@RequestParam ("current") Integer current,@RequestParam ("size") Integer size){ return bs.pagelist(current,size); }
@ApiResponses、@ApiResponse:方法返回值状态码的含义(必须一起使用)
@ApiResponses({ @ApiResponse(code = 200, message = "请求成功"), @ApiResponse(code = 400, message = "请求参数没填好"), @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径不对") }) @GetMapping(path = "pagelist",produces = {"application/json"}) // 注意这里必须添加produces public Dto list(@RequestParam String userId) {}