相关约定
- Content-Type:application/json
- 开发顺序:Dao --> Service --> Controller
- 单元测试:Service层
- MyBatis打印SQL语句
Service完成注册功能
IUserImpl.java:
{
@Autowired
private UserMapper userMapper;
@Override
public void register(User user) {
//username不能重复
int countByusername = userMapper.countByUsername(user.getUsername());
if(countByusername > 0) {
throw new RuntimeException("该username已注册");
}
//email不能重复
int countByEmail = userMapper.countByEmail(user.getEmail());
if(countByEmail > 0) {
throw new RuntimeException("该email已注册");
}
//MD5加密密码(spring自带了)
user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8)););
//写入数据库
int resultCount = userMapper.insertSelective(user);
if(resultCount == 0) {
//说明没有写进去
throw new RuntimeException("注册失败");
}
}
}
countByUsername、countByEmail:
<select id="countByUsername" parameterType="java.lang.String" resultType="java.lang.Integer">
select count(1)
from mall_user
where username = #{username,jdbcType=VARCHAR}
</select>
<select id="countByEmail" parameterType="java.lang.String" resultType="java.lang.Integer">
select count(1)
from mall_user
where email = #{email,jdbcType=VARCHAR}
</select>
service注册功能单测
package com.xiaoxin.mall.service.impl;
import com.xiaoxin.mall.MallApplicationTests;
import com.xiaoxin.mall.enums.RoleEnum;
import com.xiaoxin.mall.pojo.User;
import com.xiaoxin.mall.service.IUserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.*;
//在单测上面加Transactional注解就是起回滚的作用,因为是测试嘛,不需要真的往数据库写值
@Transactional
public class IUserServiceImplTest extends MallApplicationTests {
@Autowired
private IUserService userService;
@Test
public void register() {
User user = new User("xiaoxin", "915013255@qq.com", "123456", RoleEnum.ADMIN.getRole());
userService.register(user);
}
}
RoleEnum.java
package com.xiaoxin.mall.enums;
import lombok.Getter;
@Getter
public enum RoleEnum {
ADMIN(0),
CUSTOMER(1),
;
Integer role;
RoleEnum(Integer role) {
this.role = role;
}
}
MyBatis打印SQL语句
1、在application.yml中配置mybatis的log-impl属性:
mybatis:
configuration:
map-underscore-to-camel-case: true
# 控制台日志配置
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mappers/*.xml
这样就发现,在控制台打印出来了sql语句:
controller接收参数
package com.xiaoxin.mall.controller;
import com.xiaoxin.mall.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@PostMapping("/register")
public void register(@RequestBody User user) {
log.info("username={}", user.getUsername());
}
}
1、如果使用urlencoded方式传递参数,那么可以这样写
@PostMapping("/register")
public void register(User user) {
log.info("username={}", user.getUsername());
}
或者这样:
@PostMapping("/register")
public void register(@RequestParam String username) {
log.info("username={}", username);
}
2、如果使用json方式传递参数,那么user参数要使用@RequestBody注解
注意:@RestController 注解相当于@Controller和@ResponseBody注解的结合
Controller返回Json
1、创建一个新的类 ResponseVO
package com.xiaoxin.mall.service.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
@Data
@JsonInclude(value= JsonInclude.Include.NON_NULL)
public class ResponseVo<T> {
private Integer status;
private String msg;
private T data;
public ResponseVo(Integer status, String msg) {
this.status = status;
this.msg = msg;
}
public static <T> ResponseVo<T> success(String msg) {
return new ResponseVo<>(0, msg);
}
}
@JsonInclude(value= JsonInclude.Include.NON_NULL)这个注解的作用是,在将类返回成JSON格式的数据时,忽略掉那些为null的成员变量。
2、测试
package com.xiaoxin.mall.controller;
import com.xiaoxin.mall.pojo.User;
import com.xiaoxin.mall.service.vo.ResponseVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@PostMapping("/register")
public ResponseVo register(@RequestBody User user) {
log.info("username={}", user.getUsername());
return ResponseVo.success("注册成功");
}
}
错误状态码使用枚举
1、编写枚举类
package com.xiaoxin.mall.enums;
import lombok.Getter;
@Getter
public enum ResponseEnum {
ERROR(-1, "服务端异常"),
SUCCESS(0, "成功"),
PASSWORD_ERROR(1, "密码错误"),
USER_EXIST(2, "用户已存在"),
NEED_LOGIN(10, "用户未登录,请先登录"),
;
Integer code;
String desc;
ResponseEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
}
2、在ResponseVo类中使用:
package com.xiaoxin.mall.service.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.xiaoxin.mall.enums.ResponseEnum;
import lombok.Data;
@Data
@JsonInclude(value= JsonInclude.Include.NON_NULL)
public class ResponseVo<T> {
private Integer status;
private String msg;
private T data;
public ResponseVo(Integer status, String msg) {
this.status = status;
this.msg = msg;
}
public static <T> ResponseVo<T> success(String msg) {
return new ResponseVo<>(ResponseEnum.SUCCESS.getCode(), msg);
}
public static <T> ResponseVo<T> success() {
return new ResponseVo<>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getDesc());
}
public static <T> ResponseVo<T> fail() {
return new ResponseVo<>(ResponseEnum.PASSWORD_ERROR.getCode(), ResponseEnum.PASSWORD_ERROR.getDesc());
}
}
表单验证
1、创建类UserForm,这个类中只有username、password和email属性,因为验证时只需要验证这三个属性:
package com.xiaoxin.mall.form;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class UserForm {
//@NotBlank 用于String 判断空格
//@NotEmpty 用于集合
//@NotNULL
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
@NotBlank(message = "邮箱不能为空")
private String email;
}
@NotBlank注解的作用是,当该属性为空时会提示错误信息。
2、改写ResponseVo的error的方法:
public static <T> ResponseVo<T> error(ResponseEnum responseEnum) {
return new ResponseVo<>(responseEnum.getCode(), responseEnum.getDesc());
}
public static <T> ResponseVo<T> error(ResponseEnum responseEnum, String msg) {
return new ResponseVo<>(responseEnum.getCode(), msg);
}
public static <T> ResponseVo<T> error(ResponseEnum responseEnum, BindingResult bindingResult) {
return new ResponseVo<>(responseEnum.getCode(),
bindingResult.getFieldError().getField() + " " +
bindingResult.getFieldError().getDefaultMessage());
}
3、在Controller中使用:
@PostMapping("/register")
public ResponseVo register(@Valid @RequestBody UserForm userForm,
BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
log.info("注册提交的信息有误,{}",
bindingResult.getFieldError().getDefaultMessage());
return ResponseVo.error(ResponseEnum.PARAM_ERROR, bindingResult);
}
log.info("username={}", userForm.getUsername());
return ResponseVo.success();
}
4、使用postman进行验证: