使用dubbo仿猫眼微服务架构实战 第二天

用户模块开发

dao层代码生成

guns为我们提供了自动的dao接口代码生成器。到user模块的test文件夹中找到generator包中的EntityGeneragtor。然后对其中的信息进行修改。主要是一些目录和数据库的配置信息。目录信息就配置为工程的java目录。


gc.setOutputDir("D:\\IDEA_project_new\\guns\\guns-user\\src\\main\\java");//这里写你自己的java目录

  dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("961212");
        dsc.setUrl("jdbc:mysql://127.0.0.1:3306/guns_rest?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8");
        mpg.setDataSource(dsc);

        pc.setEntity("com.stylefeng.guns.rest.common.persistence.model");
        pc.setMapper("com.stylefeng.guns.rest.common.persistence.dao");
        pc.setXml("com.stylefeng.guns.rest.common.persistence.dao.mapping");

修改完成之后执行这个文件,就会自动生成用户模块的数据实体bean。

可以看到我们在gateway模块中也是添加了两个模块的。但是gateway中的模块是用于和其他模块之间进行信息交互使用的。而user中的只是自己在用的实体。
关系如下:

注册功能实现

    @Override
    public boolean register(UserModel userModel) {
        //获取注册信息

        //将注册信息实体转换为数据实体【mooc_user_t】
        MoocUserT moocUserT = new MoocUserT();
        //将数据实体存入数据库
        moocUserT.setUserName(userModel.getUsername());

        moocUserT.setEmail(userModel.getEmail());
        moocUserT.setAddress(userModel.getAddress());
        moocUserT.setUserPhone(userModel.getPhone());
        //创建时间和修改时间

        //数据加密[MD5数据加密+salt]就是指两次md5
        String md5Password = MD5Util.encrypt(userModel.getPassword());

        moocUserT.setUserPwd(md5Password);
        //将数据插入到数据库当中
        Integer insert = moocUserTMapper.insert(moocUserT);
        if(insert>0){
            return true;
        }else return false;
    }

注册功能很简单,无非就是调用方获取到注册信息。传递到服务提供方。然后服务提供方执行如上的几部操作。
注意这里的加密。一般我们使用的应该是两次MD5加密,但是这里为了简单一点,只使用了一次。要学习更加安全的加密可以参考shior的加密方式。更加的安全。

登录,检验功能的实现

    @Override
    public int login(String username, String password) {
        //根据登录账号获取数据库
        MoocUserT moocUserT = new MoocUserT();
        moocUserT.setUserName(username);
        MoocUserT result = moocUserTMapper.selectOne(moocUserT);
        //将获取到的结果来与加密后的password进行比较
        if(result!=null&&result.getUuid()>0){
            String p = MD5Util.encrypt(password);
            if(result.getUserPwd().equals(p)){
                return result.getUuid();
            }
        }
        return 1;
    }
    @Override
    public boolean checkUsername(String username) {
        EntityWrapper<MoocUserT> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("user_name",username);
        Integer result = moocUserTMapper.selectCount(entityWrapper);
        if(result!=null && result>0){
            return false;
        }else{
            return true;
        }
    }

查询和改变用户信息

    private UserInfoModel do2UserInfo(MoocUserT moocUserT){
        UserInfoModel userInfoModel = new UserInfoModel();

        userInfoModel.setUuid(moocUserT.getUuid());
        userInfoModel.setHeadAddress(moocUserT.getHeadUrl());
        userInfoModel.setPhone(moocUserT.getUserPhone());
        userInfoModel.setUpdateTime(moocUserT.getUpdateTime().getTime());
        userInfoModel.setEmail(moocUserT.getEmail());
        userInfoModel.setUsername(moocUserT.getUserName());
        userInfoModel.setNickname(moocUserT.getNickName());
        userInfoModel.setLifeState(""+moocUserT.getLifeState());
        userInfoModel.setBirthday(moocUserT.getBirthday());
        userInfoModel.setAddress(moocUserT.getAddress());
        userInfoModel.setSex(moocUserT.getUserSex());
        userInfoModel.setBeginTime(moocUserT.getBeginTime().getTime());
        userInfoModel.setBiography(moocUserT.getBiography());

        return userInfoModel;
    }
    @Override
    public UserInfoModel getUserInfo(int uuid) {
        // 根据主键查询用户信息 [MoocUserT]
        MoocUserT moocUserT = moocUserTMapper.selectById(uuid);
        // 将MoocUserT转换UserInfoModel
        UserInfoModel userInfoModel = do2UserInfo(moocUserT);
        // 返回UserInfoModel
        return userInfoModel;
    }

    @Override
    public UserInfoModel updateUserInfo(UserInfoModel userInfoModel) {
        // 将传入的参数转换为DO 【MoocUserT】
        MoocUserT moocUserT = new MoocUserT();
        moocUserT.setUuid(userInfoModel.getUuid());
        moocUserT.setNickName(userInfoModel.getNickname());
        moocUserT.setLifeState(Integer.parseInt(userInfoModel.getLifeState()));
        moocUserT.setBirthday(userInfoModel.getBirthday());
        moocUserT.setBiography(userInfoModel.getBiography());
        moocUserT.setBeginTime(null);
        moocUserT.setHeadUrl(userInfoModel.getHeadAddress());
        moocUserT.setEmail(userInfoModel.getEmail());
        moocUserT.setAddress(userInfoModel.getAddress());
        moocUserT.setUserPhone(userInfoModel.getPhone());
        moocUserT.setUserSex(userInfoModel.getSex());
        moocUserT.setUpdateTime(null);

        // DO存入数据库
        Integer integer = moocUserTMapper.updateById(moocUserT);
        if(integer>0){
            // 将数据从数据库中读取出来
            UserInfoModel userInfo = getUserInfo(moocUserT.getUuid());
            // 将结果返回给前端
            return userInfo;
        }else{
            return null;
        }
    }

gateway模块的各个接口的实现

再gateway模块当中,所有的业务实现都在package com.stylefeng.guns.rest.modular.user的UserController当中。实际上这个controller就是最开始接受前端请求的位置了。这个controller的主要通过调用user模块提供的service来实现。实现代码如下:

package com.stylefeng.guns.rest.modular.user;

import com.alibaba.dubbo.config.annotation.Reference;

import com.stylefeng.guns.rest.common.CurrentUser;
import com.stylefeng.guns.rest.modular.vo.ResponseVO;
import com.stylefeng.guns.user.UserApi;
import com.stylefeng.guns.user.vo.UserInfoModel;
import com.stylefeng.guns.user.vo.UserModel;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/user/")
@RestController
public class UserController {

    @Reference(interfaceClass = UserApi.class,check = false)
    private UserApi userAPI;


    @RequestMapping(value="register",method = RequestMethod.POST)
    public ResponseVO register(UserModel userModel){
        if(userModel.getUsername() == null || userModel.getUsername().trim().length()==0){
            return ResponseVO.serviceFail("用户名不能为空");
        }
        if(userModel.getPassword() == null || userModel.getPassword().trim().length()==0){
            return ResponseVO.serviceFail("密码不能为空");
        }

        boolean isSuccess = userAPI.register(userModel);
        if(isSuccess){
            return ResponseVO.success("注册成功");
        }else{
            return ResponseVO.serviceFail("注册失败");
        }
    }

    @RequestMapping(value="check",method = RequestMethod.POST)
    public ResponseVO check(String username){
        if(username!=null && username.trim().length()>0){
            // 当返回true的时候,表示用户名可用
            boolean notExists = userAPI.checkUsername(username);
            if (notExists){
                return ResponseVO.success("用户名不存在");
            }else{
                return ResponseVO.serviceFail("用户名已存在");
            }

        }else{
            return ResponseVO.serviceFail("用户名不能为空");
        }
    }

    @RequestMapping(value="logout",method = RequestMethod.GET)
    public ResponseVO logout(){
        /*
            应用:
                1、前端存储JWT 【七天】 : JWT的刷新
                2、服务器端会存储活动用户信息【30分钟】
                3、JWT里的userId为key,查找活跃用户
            退出:
                1、前端删除掉JWT
                2、后端服务器删除活跃用户缓存
            现状:
                1、前端删除掉JWT
         */


        return ResponseVO.success("用户退出成功");
    }


    @RequestMapping(value="getUserInfo",method = RequestMethod.GET)
    public ResponseVO getUserInfo(){
        // 获取当前登陆用户
        String userId = CurrentUser.getCurrentUser();
        if(userId != null && userId.trim().length()>0){
            // 将用户ID传入后端进行查询
            int uuid = Integer.parseInt(userId);
            UserInfoModel userInfo = userAPI.getUserInfo(uuid);
            if(userInfo!=null){
                return ResponseVO.success(userInfo);
            }else{
                return ResponseVO.appFail("用户信息查询失败");
            }
        }else{
            return ResponseVO.serviceFail("用户未登陆");
        }
    }

    @RequestMapping(value="updateUserInfo",method = RequestMethod.POST)
    public ResponseVO updateUserInfo(UserInfoModel userInfoModel){
        // 获取当前登陆用户
        String userId = CurrentUser.getCurrentUser();
        if(userId != null && userId.trim().length()>0){
            // 将用户ID传入后端进行查询
            int uuid = Integer.parseInt(userId);
            // 判断当前登陆人员的ID与修改的结果ID是否一致
            if(uuid != userInfoModel.getUuid()){
                return ResponseVO.serviceFail("请修改您个人的信息");
            }

            UserInfoModel userInfo = userAPI.updateUserInfo(userInfoModel);
            if(userInfo!=null){
                return ResponseVO.success(userInfo);
            }else{
                return ResponseVO.appFail("用户信息修改失败");
            }
        }else{
            return ResponseVO.serviceFail("用户未登陆");
        }
    }

}

到这里呢我们user模块的业务层就完成了。

业务总结

  1. 验证忽略URL列表
    ignore-url: /user/register,/user/check #忽略列表配置

  2. 申请JWT

  3. 使用JWT访问其他的权限功能

在测试的时候我遇到了这样的一个问题。对register接口进行测试的时候。回报出无法访问的错误。首先我们要知道。dubbo是一款RPC框架。在进行方法远程调用的时候,会将方法中的参数首先进行序列化,然后在远端进行反序列化。报这个错的原因就是作为参数类型的实体类没有实现序列化接口。加上之后报错就没有了。

你可能感兴趣的:(java)