本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Step1:初始化一个SpringBoot项目
编辑
手动在pom.xml文件中添加Druid依赖, 需要加版本,因为父类中没有维护这个依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency>
配置数据库信息
将配置文件改为yml后缀
spring: datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/spring?serverTimezone=UTC username: root password: niit server: port: 80 mybatis-plus: global-config: db-config: table-prefix: id-type: auto #数据库自增,向插入某个对象时,主键会自增,忽略对象的主属性的值
Step2:实体类开发
使用Lombok快速制作实体类
添加依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
使用
@TableName("`tbl_accounts`")//指定该实体类用于操作哪个表 @Data//自动生成属性的get和set方法,还要toString,equals,hashCode等方法 @Setter//自动生成属性的set方法 @Getter//自动生成属性的get方法 @NoArgsConstructor//生成无参构造方法 @AllArgsConstructor//生成全参构造方法 public class accounts { @TableId//指定该属性为主键 private Integer aid;//属性名要和字段名相同 private String aname; private String acontent; }
Step3:Mapper开发
在此整合MyBatis-Plus
@Mapper public interface UsersMapper extends BaseMapper<accounts> { }
记得要添加注解@Mapper,如果不想每个接口都添加注解,可以在引导类中添加包扫描@MapperScan
添加日志功能
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
在配置文件中添加配置
分页查询
创建config包,创建MyBatis-Plus的配置拦截器用来分页,分页操作是在常规操作的基础上增强得到的,内部动态拼写SQL语句,因此需要增强对应功能,使用拦截器实现。感觉是用了装饰者模式
@Configuration public class MPConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
查询具体页的数据
IPage page = new Page(1,2); usersMapper.selectPage(page,null); System.out.println(page.getRecords()); System.out.println(page.getPages());//一共多少页 System.out.println(page.getCurrent());//第一页 System.out.println(page.getSize());//获取某页多少个数据 System.out.println(page.getTotal());//该表中的总数据条数
最后查询出来的数据和分页信息都封装在了page对象中,通过page对象获取。
条件查询
QueryWrapper<Accounts> qw = new QueryWrapper<>(); qw.like("aname","c");//查询aname字段中包含c的元组 usersMapper.selectList(qw);
为了避免字段名有可能写错,还要lambda表达式形式方法查询
LambdaQueryWrapper<Accounts> lqw = new LambdaQueryWrapper<>(); lqw.like(Accounts::getAname,"c"); usersMapper.selectList(lqw);
必须判断关键字不能为null,不然会把null当作是字符串去查找数据
也可以这样写
String keyword = "c"; LambdaQueryWrapper<Accounts> lqw = new LambdaQueryWrapper<>(); lqw.like(keyword != null,Accounts::getAname,keyword); usersMapper.selectList(lqw);
当结果为true才连接该条件进行查询,不然执行无条件查询
Step5:Service层开发
service层接口与数据层接口的命名风格
业务层与具体业务挂钩,数据层与数据挂钩
selectByUserNameAndPassword(String username,String password);
login(String username,String password);
业务层的快速开发
public interface IUserService extends IService<Accounts> { }
@Service public class UserServiceImpl2 extends ServiceImpl<UsersMapper,Accounts> implements IUserService { }
通过继承两个类,那些基本的通用业务方法都包含在内了
如果要实现具体的业务处理,可以在接口中自己重新定义,但要避免重写原先的基本方法,可以通过@Override注解来判断,报错就是没有重写
Step6:表现层开发
@RestController @RequestMapping("/accounts") public class AccountController { @Autowired IUserService userService; //获取全部 @GetMapping public List<Accounts> getAll(){ return userService.list(); } //添加数据 @PostMapping public Boolean save(@RequestBody Accounts accounts){ return userService.save(accounts); } //更新数据 @PutMapping public Boolean update(@RequestBody Accounts accounts){ return userService.updateById(accounts); } //删除数据 @DeleteMapping("{id}") public Boolean delete(@PathVariable Integer id){ return userService.removeById(id); } //获取一条 @GetMapping("{id}") public Accounts getById(@PathVariable Integer id){ return userService.getById(id); } //分页 @GetMapping("{currentPage}/{pageSize}") public IPage<Accounts> getPage(@PathVariable Integer currentPage,@PathVariable Integer pageSize){ return userService.getPage(currentPage,pageSize); } }
新增数据
编辑
修改数据
编辑
接收路径参数用@PathVariable注解
接收实体数据用@RequestBody注解(区分@ResponseBody)
表现层消息一致性处理
进行增删改时,返回结果是true或false
查询单条数据时,返回结果是JSON格式
查询全部数据时,返回结果是数组
编辑
如何将返回的数据格式统一起来,方便前端处理?
将所有的数据都封装在data中,但是当查询到的数据为null时,不一定是数据库中没有相应数据,可能是操作执行失败,导致没有搜索到数据,所以又加了个flag,用来判断操作是否执行成功。
编辑
创建一个工具类
用来封装返回的数据
@Data public class R { private Boolean flag; private Object data; public R() { } public R(Boolean flag){ this.flag = flag; } public R(Boolean flag,Object data) { this.flag = flag; this.data = data; } }
修改controller内的代码返回格式
@RestController @RequestMapping("/accounts") public class AccountController { @Autowired IUserService userService; //获取全部 @GetMapping public R getAll(){ return new R(true,userService.list()); } //添加数据 @PostMapping public R save(@RequestBody Accounts accounts){ return new R(userService.save(accounts)); } //更新数据 @PutMapping public R update(@RequestBody Accounts accounts){ return new R(userService.modify(accounts)); } //删除数据 @DeleteMapping("{id}") public R delete(@PathVariable Integer id){ return new R(userService.delete(id)); } //获取一条 @GetMapping("{id}") public R getById(@PathVariable Integer id){ return new R(true,userService.getById(id)); } //分页 @GetMapping("{currentPage}/{pageSize}") public R getPage(@PathVariable Integer currentPage,@PathVariable Integer pageSize){ return new R(true,userService.getPage(currentPage,pageSize)); } }
这样前端接收数据时,都从这个对象的data属性里找,返回结果由前后端统一规定,没有固定的格式。
Step7:页面开发
基于Vue和ElementUI制作
黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)_哔哩哔哩_bilibili p43-p53
Step8:项目异常处理和调整
\