接口开发流程
- 访问
controller
接口 controller
接口调用service
层实现具体业务逻辑的方法service
层方法调用dao
层实现数据库操作
controller/UserController.java
编写相关接口
// 设置接口访问的模块路径
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
// 设置注册的请求接口地址
@PostMapping("/register")
@ResponseBody
public Result register(String username, String password) {
// 1、查询用户
User user = userService.findByUsername(username);
if (user == null) {
// 2、注册
userService.register(username, password);
return Result.success();
} else {
return Result.error("用户已存在");
}
}
}
service
层接口和实现类
接口
public interface UserService {
// 根据名称查询用户
User findByUsername(String username);
// 注册用户
void register(String username,String password);
}
实现类
@Service
public class UserServiceImpl implements UserService {
// 用于查询数据库数据
@Autowired
private UserDao userDao;
// 查询用户
@Override
public User findByUsername(String username) {
// 使用mybatis-plus的条件构造器
LambdaQueryWrapper<User> qm = new LambdaQueryWrapper();
// 根据名称查询
qm.eq(User::getUsername, username);
User user = userDao.selectOne(qm);
System.out.println("user = " + user);
return user;
}
// 注册用户
@Override
public void register(String username, String password) {
User user = new User();
// 设置用户名、名称、创建时间、更新时间
user.setUsername(username);
user.setPassword(password);
LocalDateTime now = LocalDateTime.now();
user.setCreateTime(now);
user.setUpdateTime(now);
userDao.insert(user);
}
}
dao
层操作数据库
// 使用MybatisPlus提供的BaseMapper
@Mapper
public interface UserDao extends BaseMapper<User> {
}
Result.class
请求结果返回类型
**//统一响应结果
public class Result<T> {
private Integer code;//业务状态码 0-成功 1-失败
private String message;//提示信息
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private T data;//响应数据
public Result(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
//快速返回操作成功响应结果(带响应数据)
public static <E> Result<E> success(E data) {
return new Result<>(0, "操作成功", data);
}
//快速返回操作成功响应结果
public static Result success() {
return new Result(0, "操作成功", null);
}
public static Result error(String message) {
return new Result(1, message, null);
}
}
参数校验
Spring
提供的一个参数校验框架,使用预定义的注解完成参数校验
- 引入
Spring Validation
起步依赖 - 在参数前面添加
@Pattern
注解 - 在
Controller
类上添加@Validated
注解 - 在全局异常处理器中处理参数校验失败的异常
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
@Controller
@RequestMapping("/user")
@Validated
public class UserController {
@Autowired
private UserService userService;
// 设置注册的请求接口地址
@PostMapping("/register")
@ResponseBody
public Result register(@Pattern(regexp = "^[a-zA-Z0-9_-]{4,16}$", message = "用户名格式错误") String username,
@Pattern(regexp = "^[a-zA-Z0-9_-]{4,16}$", message = "密码格式错误") String password) {
// 1、查询用户
User user = userService.findByUsername(username);
if (user == null) {
// 2、注册
userService.register(username, password);
return Result.success();
} else {
return Result.error("用户已存在");
}
}
}
参数校验失败异常处理
当校验失败后,会抛出异常,需要对异常进行处理
创建一个全局异常处理类
exception/GlobalExceptionHandler.class
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
// 打印错误信息
e.printStackTrace();
return Result.error(StringUtils.hasLength(e.getMessage()) ? e.getMessage() : "操作失败");
}
}
xml格式编写sql进行查询数据
复杂查询一般无法使用mybatis-plus
,需要使用sql
语句进行查询
基本流程
基本上与使用mybatis-plus
开发的流程一致
- 访问
controller
接口 controller
接口调用service
层实现具体业务逻辑的方法service
层方法调用dao
层实现数据库操作- 在
xml
文件中编写sql
UserController.class
// 根据用户id查询用户信息
@GetMapping("/findById")
@ResponseBody
public Result findById(Integer id) {
User user = userService.findById(id);
return new Result(0,"查询成功",user);
}
UserService.class
public interface UserService {
// 根据名称查询用户
User findByUsername(String username);
// 注册用户
void register(String username,String password);
// 根据id查询用户
User findById(Integer id);
}
UserServiceImpl.class
@Override
public User findById(Integer id) {
return userDao.findById(id);
}
UserDao
@Mapper
public interface UserDao extends BaseMapper<User> {
User findById(Integer id);
}
配置
在application.yml
配置文件中配置mybatis
的sql
文件读取
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
在resources
目录下创建mapper
文件夹,存放对应的xml
文件,xml
文件命名一般是实体类+Mapper
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.dao.UserDao">
<select id="findById" resultType="org.example.domain.User">
SELECT *
FROM user
WHERE id = #{id}
</select>
</mapper>
namespace
的值是dao
层接口对应的类路径id
唯一标识,一般与对应的接口名保持一致resultType
返回值类型,值一般就是对应的实体类路径
常用查询语法
foreach
根据id
批量查询
@PostMapping("/findByIdList")
@ResponseBody
public Result findByIdList(@RequestBody ArrayList<Integer> idList) {
System.out.println(idList);
List<User> userList = userService.findByIdList(idList);
return new Result(0, "查询成功", userList);
}
<select id="findByIdList" resultType="org.example.domain.User">
SELECT *
FROM user
WHERE id IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
或者
只修改Controller
接口和请求入参
@PostMapping("/findByIdList")
@ResponseBody
public Result findByIdList(@RequestBody IdParam IdParam) {
List<Integer> idList = IdParam.getIdList();
System.out.println(idList);
List<User> userList = userService.findByIdList(idList);
return new Result(0, "查询成功", userList);
}
入参类
class IdParam {
private List<Integer> idList;
public List<Integer> getIdList() {
return idList;
}
public void setIdList(List<Integer> idList) {
this.idList = idList;
}
}
if
class UserParam {
private List<Integer> idList;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
public List<Integer> getIdList() {
return idList;
}
public void setIdList(List<Integer> idList) {
this.idList = idList;
}
}
@PostMapping("/findByIdList")
@ResponseBody
public Result findByIdList(@RequestBody UserParam userParam) {
List<Integer> idList = userParam.getIdList();
Integer age = userParam.getAge();
List<User> userList = userService.findByIdList(idList, age);
return new Result(0, "查询成功", userList);
}
Dao层或者Mapper层
直接操作数据层
List<User> findByIdList(@Param("idList") List<Integer> idList, @Param("age") Integer age);
多个参数时使用@Param
给参数起名,mapper xml
文件中会使用相应的参数
<select id="findByIdList" resultType="org.example.domain.User">
SELECT *
FROM user
WHERE 1=1
<if test="idList != null and idList.size() > 0">
AND id IN
<foreach item="item" index="index" collection="idList" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
WHERE 1=1
:
这是一个常用的技巧,用来确保至少有一个WHERE
子句存在,即使所有的条件都为null
或者空列表。<if test="idList != null and idList.size() > 0">
:
这个<if>
语句检查idList
是否非空且包含元素。只有在这种情况下才会添加AND id IN (...)
子句。<foreach>
:
如果idList
不为空,则使用 构建 IN 子句。<if test="age != null">
:
这个<if>
语句检查age
是否非空。只有在这种情况下才会添加AND age = #{age}
子句。