史上最强项目实战(十三)——用户微服务功能实现(2)

在前面《史上最强项目实战(十一)——搭建用户微服务、短信微服务框架》我们已完成用户微服务的工程框架搭建,所以在这里我们直接开发业务代码即可。

1. Repository接口

持久层我们使用的是spring jpa,所以只需要提供一个接口继承CrudRepository接口即可。

public interface UserRepository extends CrudRepository<User, Long> {

    /**
     * 根据用户名查询用户
     *
     * @param username
     * @return
     */
    User findByUsername(String username);
}

2. Service实现

2.1 新增和修改

public User save(User entity) {
    User user = userRepository.findByUsername(entity.getUsername());
    if (entity.getId() == null) {
        // 新增时判断用户名是否已经存在,如果已经存在,则抛出异常由统一异常处理类处理
        if (user != null)
            LeyouExceptionCast.cast(UserResultCode.USER_IS_EXIST);
        // 如果不存在,则对密码加密再进行保存
        entity.setPassword(passwordEncoder.encode(entity.getPassword()));
    }
    return userRepository.save(entity);
}

2.2 根据id删除用户

public void deleteById(Long id) {
    // 判断id对应的实体是否存在
    boolean isExist = userRepository.existsById(id);
    if (isExist == false) {
        LeyouExceptionCast.cast(UserResultCode.USER_IS_NOT_EXIST);
    }
    userRepository.deleteById(id);
}

2.3 发送短信验证码

(1)定义短信验证码消息交换器名称:

private static final String KEY_PHONE_CODE_EXCHANGE = "leyou.user.sms.code.exchange";

(2)定义短信验证码消息路由键:

private static final String KEY_PHONE_CODE_ROUTING_KEY = "leyou.user.sms.code.routing.key";

(3)定义短信验证码在Redis中的key前缀:

private static final String KEY_PHONE_CODE_PREFIX = "leyou:user:code:phone:";

(4)实现

public void sendPhoneCode(String phone) {
    // 随机产生一个6位的字符串
    String code = RandomStringUtils.randomNumeric(6);
    // 将手机号和验证码使用Map封装
    Map<String, String> msgMap = new HashMap<>();
    msgMap.put("phone", phone);
    msgMap.put("code", code);
    // 发送至消息队列
    amqpTemplate.convertAndSend(KEY_PHONE_CODE_EXCHANGE, KEY_PHONE_CODE_ROUTING_KEY, msgMap);
    // 将验证码存入redis,时效5min
    redisTemplate.opsForValue().set(KEY_PHONE_CODE_PREFIX + phone, code, 5, TimeUnit.MINUTES);
}

2.4 根据用户名和密码查询用户

用于要根据用户名+密码实现登录。

public User findByUsernameAndPassword(String username, String password) {
    User user = userRepository.findByUsername(username);
    if (user != null && passwordEncoder.matches(password, user.getPassword())) {
        return user;
    }
    return null;
}

2.5 用户注册

public boolean register(User user, String code) {
    // 校验短信验证码
    String cacheCode = redisTemplate.opsForValue().get(KEY_PHONE_CODE_PREFIX + user.getPhone());
    if (!StringUtils.equals(code, cacheCode)) {
        return false;
    }

    // 强制设置不能指定的参数为null
    user.setId(null);
    // 添加到数据库
    save(user);
    // 注册成功,删除redis中的记录
    redisTemplate.delete(KEY_PHONE_CODE_PREFIX + user.getPhone());
    return true;
}

3. Controller实现

@Api(value = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController implements UserApi {

    @Autowired
    private UserService userService;

    @Override
    @GetMapping("/findByUP")
    @ApiOperation(value = "根据用户名密码查询用户", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String", paramType = "query")
    })
    public UserResponseResult findByUsernameAndPassword(@RequestParam("username") String username, @RequestParam("password") String password) {
        return new UserResponseResult(CommonResultCode.SUCCESS, userService.findByUsernameAndPassword(username, password));
    }

    @PostMapping
    @ApiOperation(value = "新增用户", httpMethod = "POST")
    @ApiImplicitParam(name = "entity", value = "用户实体", required = true, dataType = "User")
    public UserResponseResult save(@Valid @RequestBody User entity) {
        return new UserResponseResult(CommonResultCode.SUCCESS, userService.save(entity));
    }

    @PutMapping
    @ApiOperation(value = "编辑保存用户", httpMethod = "PUT")
    @ApiImplicitParam(name = "entity", value = "用户实体", required = true, dataType = "User")
    public ResponseResult update(@Valid @RequestBody User entity) {
        userService.save(entity);
        return new ResponseResult(CommonResultCode.SUCCESS);
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除用户", httpMethod = "DELETE")
    @ApiImplicitParam(name = "id", value = "用户id", required = true, dataType = "String", paramType = "path")
    public ResponseResult deleteById(@PathVariable("id") Long id) {
        userService.deleteById(id);
        return new ResponseResult(CommonResultCode.SUCCESS);
    }

    @GetMapping("/{phone}/code")
    @ApiOperation(value = "前台门户用户注册时发送手机验证码", httpMethod = "GET")
    @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "path")
    public ResponseResult sendPhoneCode(@PathVariable("phone") String phone) {
        userService.sendPhoneCode(phone);
        return new ResponseResult(CommonResultCode.SUCCESS);
    }

    @PostMapping("/register")
    @ApiOperation(value = "用户注册", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "user", value = "用户", required = true, dataType = "User", paramType = "body"),
            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String", paramType = "query")
    })
    public ResponseResult register(@Valid @RequestBody User user, @RequestParam("code") String code) {
        boolean success = userService.register(user, code);
        return new ResponseResult(success ? CommonResultCode.SUCCESS : UserResultCode.SMS_CODE_IS_ERROR);
    }
}

4. SwaggerConfig配置类

因为我们在工程中使用了Swagger,所以需要添加Swagger配置类使其自动生成接口文档。

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)//
                .apiInfo(getApiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.basePackage("com.leyou.server.user"))// 这里指定需要生成swagger接口的包路径
                .paths(PathSelectors.any())//
                .build();
    }

    private ApiInfo getApiInfo() {
        return new ApiInfoBuilder().title("用户微服务").version("1.0.0").build();
    }
}

5. WebSecurityConfig配置类

我们在添加了Spring Security依赖后,所有的地址都被Spring Security控制了。目前只是需要用到BCrypt密码加密的部分,所以我们要添加一个配置类,配置为所有地址都可以匿名访问。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated().and().csrf().disable();
    }
}

至此,ly-server-user-provider的业务代码已经实现了。但因为注册需要发送手机短信验证码,所以该部分的功能测试等下一阶段的短信微服务开发完成后一块测试。

——End——
更多详情,可扫码关注微信公众号哦。

在这里插入图片描述

发布了142 篇原创文章 · 获赞 29 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览