SSM 框架 个人使用习惯 详细
SpringMVC主要是controller、service、dao(mapper)层交互
controller:处理数据请求的接口
service:处理请求的数据
dao(mapper):对数据进行持久化
下面我将对controller和service.impl进行讲解
1.controller层 (代码讲解):
对于需要返回的数据:比如登录、获取用户信息等操作都是直接返回数据的
对于不需要返回数据:比如进行注册、注销、修改密码等操作,这些只需要知道是否执行成功即可,不需要返回的数据,需要对其结果进行布尔值判断,如果成功则返回Result.ok,失败则返回Result.fail的结果。
你会发现我使用的是@RequiredArgsConstructor,
而不是@Autowired,其实两种方式可以提供依赖注入,但是我个人习惯于使用@RequiredArgsConstructor
的方式进行依赖注入。
@RequiredArgsConstructor
通过构造函数为不可变字段提供依赖注入,适用于需要final字段的情况。@Autowired
则提供更灵活的注入方式,可以用于字段、构造函数或方法,不需要字段是final。
具体详细的过程如下所示:
@Tag(name = "用户接口管理")
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final IUserService userService;
@Operation(summary = "用户密码验证登录")
@PostMapping("/login")
public Result<String> login(@RequestBody UserLoginForm userLoginForm){
return Result.ok(userService.login(userLoginForm));
}
@Operation(summary = "用户短信验证登录")
@PostMapping("/loginBySms")
public Result<String> loginBySms(@RequestBody UserLoginSmsForm userLoginSmsForm){
return Result.ok(userService.loginBySms(userLoginSmsForm));
}
@Operation(summary = "用户注册")
@PostMapping("/register")
public Result<Void> register(@RequestBody UserRegisterForm userRegisterForm){
if(userService.register(userRegisterForm)){
return Result.fail();
}
return Result.ok();
}
@Operation(summary = "用户修改密码")
@PutMapping("/modifyPassword")
public Result<Void> modifyPassword(@RequestBody UserModifyPasswordForm userModifyPasswordForm){
if(!userService.modifyPassword(userModifyPasswordForm)){
return Result.fail();
}
return Result.ok();
}
@Operation(summary = "用户注销")
@DeleteMapping("/logout")
public Result<Void> logout(){
if(!userService.logout()){
return Result.fail();
}
return Result.ok();
}
@Operation(summary = "获取用户信息")
@GetMapping("/info")
public Result<UserInfoVo> info(){
return Result.ok(userService.info());
}
}
2.service层:
service层一般的写法是先写service的接口类,再写对应的实现类进行实现,如下所示:
service接口:
public interface IUserService extends IService<User> {
String login(UserLoginForm userLoginForm);
String loginBySms(UserLoginSmsForm userLoginSmsForm);
boolean register(UserRegisterForm userRegisterForm);
UserInfoVo info();
boolean modifyPassword(UserModifyPasswordForm userModifyPasswordForm);
boolean logout();
}
service接口实现类(service.impl)中的代码:
观察下面的代码:
对于不正确的数据,我会选择抛出自定义异常BusinessRuntimeException进行处理,
对于需要返回布尔类型直接对返回的结果行rows==1进行判断即可,
对于注销用户操作,不要直接删除数据中的数据,需要进行逻辑删除,而不是直接真正的删除数据库中的数据
对于用户的密码相关操作,因为这里的密码是用MD5进行加密的,所以对于密码的校验操作需要考虑MD5的转换
对于用户登录操作,需要返回token值,这样便于操作请求时进行校验操作
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
private final UserMapper userMapper;
private final RedisTemplate<String,Object> redisTemplate;
@Override
public String login(UserLoginForm userLoginForm) {
User user = selectUserByName(userLoginForm.getUsername());
//用户不存在
if(user == null){
throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_ERROR);
}
//密码不正确
if(!user.getPassword().equals(MD5.encrypt(userLoginForm.getPassword()))){
throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);
}
//账号已经被注销了
if(user.getIsDelete()==1){
throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_STOP);
}
Map<String,Object> claims = new HashMap<>();
claims.put("id",user.getId());
claims.put("username",user.getUsername());
claims.put("profile",user.getProfile());
//生成token
String token = JwtUtils.generateJwt(claims);
redisTemplate.opsForValue().set(RedisConstant.USER_CHECK_TOKEN,token,2, TimeUnit.HOURS);
return token;
}
public User selectUserByName(String username){
return userMapper.selectOne(new LambdaQueryWrapper<User>()
.eq(User::getUsername,username));
}
@Override
public String loginBySms(UserLoginSmsForm userLoginSmsForm) {
User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
.eq(User::getUsername,userLoginSmsForm.getPhone()));
//用户不存在
if(user == null){
throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_ERROR);
}
//账号已经被注销了
if(user.getIsDelete()==1){
throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_STOP);
}
//未输入验证码
if(StringUtils.isEmpty(userLoginSmsForm.getVerifyCode())){
throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_EMPTY);
}
String verifyCode = (String) redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_SMS_CODE);
//验证码过期或未发送验证码
if(StringUtils.isEmpty(verifyCode)){
throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_EXPIRED);
}
//验证码错误
if(!verifyCode.equals(userLoginSmsForm.getVerifyCode())){
throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_ERROR);
}
Map<String,Object> claims = new HashMap<>();
claims.put("id",user.getId());
claims.put("username",user.getUsername());
claims.put("profile",user.getProfile());
//生成token
String token = JwtUtils.generateJwt(claims);
redisTemplate.opsForValue().set(RedisConstant.USER_CHECK_TOKEN,token,2, TimeUnit.HOURS);
return token;
}
@Override
public boolean register(UserRegisterForm userRegisterForm) {
String username = userRegisterForm.getUsername();
String password = userRegisterForm.getPassword();
//输入的密码为空
if(StringUtils.isEmpty(password) || StringUtils.isEmpty(userRegisterForm.getPasswordAgain())){
throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);
}
//两次输入的密码不一致
if(!password.equals(userRegisterForm.getPasswordAgain())){
throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);
}
//注册的用户名不存在
if(selectUserByName(username) == null){
User user = new User();
user.setGender(0);
user.setRole(0);
user.setUsername(username);
user.setPassword(MD5.encrypt(password));
user.setIsDelete(0);
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
int rows = userMapper.insert(user);
return rows == 1;
}
return false;
}
@Override
public UserInfoVo info() {
Long userId = UserHolder.getUserId();
User user = userMapper.selectById(userId);
return BeanUtil.copyProperties(user, UserInfoVo.class);
}
@Override
public boolean modifyPassword(UserModifyPasswordForm userModifyPasswordForm) {
Long userId = UserHolder.getUserId();
User user = userMapper.selectById(userId);
String password = userModifyPasswordForm.getPassword();
String newPassword = userModifyPasswordForm.getNewPassword();
//校验密码
if(!user.getPassword().equals(MD5.encrypt(password))){
throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);
}
user.setPassword(MD5.encrypt(newPassword));
int rows = userMapper.updateById(user);
return rows == 1;
}
@Override
public boolean logout() {
Long userId = UserHolder.getUserId();
User user = userMapper.selectById(userId);
//设置逻辑删除状态
user.setIsDelete(1);
user.setUpdateTime(new Date());
UserHolder.removeUserId();
return true;
}
}
3.dao(mapper)层:
如果你学过Mybatis-plus,你就会发现原来,我使用的是Mybatis-plus进行操作,非常便利
public interface UserMapper extends BaseMapper<User> {
}