3.2基本用法
由于Service
中经常需要定义与业务有关的自定义方法,因此我们不能直接使用IService
,而是自定义Service
接口,然后继承IService
以拓展方法。同时,让自定义的Service实现类
继承ServiceImpl
,这样就不用自己实现IService
中的接口了。
首先,定义IUserService
,继承IService
:
package com.itheima.mp.service; import com.baomidou.mybatisplus.extension.service.IService; import com.itheima.mp.domain.po.User; public interface IUserService extends IService<User> { // 拓展自定义方法 }
然后,编写UserServiceImpl
类,继承ServiceImpl
,实现UserService
:
package com.itheima.mp.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itheima.mp.domain.po.User; import com.itheima.mp.domain.po.service.UserService; import com.itheima.mp.mapper.UserMapper; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }
项目结构如下:
接下来,我们快速实现下面4个接口:
编号 |
接口 |
请求方式 |
请求路径 |
请求参数 |
返回值 |
1 |
新增用户 |
POST |
/users |
用户表单实体 |
无 |
2 |
删除用户 |
DELETE |
/users/{id} |
用户id |
无 |
3 |
根据id查询用户 |
GET |
/users/{id} |
用户id |
用户VO |
4 |
根据id批量查询 |
GET |
/users |
用户id集合 |
用户VO集合 |
首先,我们在项目中引入几个依赖:
<!--swagger--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId> <version>4.1.0</version> </dependency> <!--web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
然后需要配置swagger信息:
knife4j: enable: true openapi: title: 用户管理接口文档 description: "用户管理接口文档" email: zhanghuyi@itcast.cn concat: 虎哥 url: https://www.itcast.cn version: v1.0.0 group: default: group-name: default api-rule: package api-rule-resources: - com.itheima.mp.controller
然后,接口需要两个实体:
- UserFormDTO:代表新增时的用户表单
- UserVO:代表查询的返回结果
首先是UserFormDTO:
package com.itheima.mp.domain.dto; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(description = "用户表单实体") public class UserFormDTO { @ApiModelProperty("id") private Long id; @ApiModelProperty("用户名") private String username; @ApiModelProperty("密码") private String password; @ApiModelProperty("注册手机号") private String phone; @ApiModelProperty("详细信息,JSON风格") private String info; @ApiModelProperty("账户余额") private Integer balance; }
然后是UserVO:
package com.itheima.mp.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(description = "用户VO实体") public class UserVO { @ApiModelProperty("用户id") private Long id; @ApiModelProperty("用户名") private String username; @ApiModelProperty("详细信息") private String info; @ApiModelProperty("使用状态(1正常 2冻结)") private Integer status; @ApiModelProperty("账户余额") private Integer balance; }
最后,按照Restful风格编写Controller接口方法:
package com.itheima.mp.controller; import cn.hutool.core.bean.BeanUtil; import com.itheima.mp.domain.dto.UserFormDTO; import com.itheima.mp.domain.po.User; import com.itheima.mp.domain.vo.UserVO; import com.itheima.mp.service.IUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @Api(tags = "用户管理接口") @RequiredArgsConstructor @RestController @RequestMapping("users") public class UserController { private final IUserService userService; @PostMapping @ApiOperation("新增用户") public void saveUser(@RequestBody UserFormDTO userFormDTO){ // 1.转换DTO为PO User user = BeanUtil.copyProperties(userFormDTO, User.class); // 2.新增 userService.save(user); } @DeleteMapping("/{id}") @ApiOperation("删除用户") public void removeUserById(@PathVariable("id") Long userId){ userService.removeById(userId); } @GetMapping("/{id}") @ApiOperation("根据id查询用户") public UserVO queryUserById(@PathVariable("id") Long userId){ // 1.查询用户 User user = userService.getById(userId); // 2.处理vo return BeanUtil.copyProperties(user, UserVO.class); } @GetMapping @ApiOperation("根据id集合查询用户") public List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids){ // 1.查询用户 List<User> users = userService.listByIds(ids); // 2.处理vo return BeanUtil.copyToList(users, UserVO.class); } }
可以看到上述接口都直接在controller即可实现,无需编写任何service代码,非常方便。
不过,一些带有业务逻辑的接口则需要在service中自定义实现了。例如下面的需求:
- 根据id扣减用户余额
这看起来是个简单修改功能,只要修改用户余额即可。但这个业务包含一些业务逻辑处理:
- 判断用户状态是否正常
- 判断用户余额是否充足
这些业务逻辑都要在service层来做,另外更新余额需要自定义SQL,要在mapper中来实现。因此,我们除了要编写controller以外,具体的业务还要在service和mapper中编写。
首先在UserController中定义一个方法:
@PutMapping("{id}/deduction/{money}") @ApiOperation("扣减用户余额") public void deductBalance(@PathVariable("id") Long id, @PathVariable("money")Integer money){ userService.deductBalance(id, money); }
然后是UserService接口:
package com.itheima.mp.service; import com.baomidou.mybatisplus.extension.service.IService; import com.itheima.mp.domain.po.User; public interface IUserService extends IService<User> { void deductBalance(Long id, Integer money); }
最后是UserServiceImpl实现类:
package com.itheima.mp.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itheima.mp.domain.po.User; import com.itheima.mp.mapper.UserMapper; import com.itheima.mp.service.IUserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public void deductBalance(Long id, Integer money) { // 1.查询用户 User user = getById(id); // 2.判断用户状态 if (user == null || user.getStatus() == 2) { throw new RuntimeException("用户状态异常"); } // 3.判断用户余额 if (user.getBalance() < money) { throw new RuntimeException("用户余额不足"); } // 4.扣减余额 baseMapper.deductMoneyById(id, money); } }
最后是mapper:
@Update("UPDATE user SET balance = balance - #{money} WHERE id = #{id}") void deductMoneyById(@Param("id") Long id, @Param("money") Integer money);