苍穹外卖-day02 新增员工 代码完善

目前,程序存在的问题主要有两个:

  • 录入的用户名已存,抛出的异常后没有处理

  • 新增员工时,创建人id和修改人id设置为固定值

接下来,我们对上述两个问题依次进行分析和解决。

1.4.1 问题一

描述:录入的用户名已存,抛出的异常后没有处理

分析:

新增username=zhangsan的用户,若employee表中之前已存在。

后台报错信息:

java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'zhangsan' for key 'employee.idx_username'

查看employee表结构:

发现,username已经添加了唯一约束,不能重复。

解决:

通过全局异常处理器来处理。

进入到sky-server模块,com.sky.hander包下,GlobalExceptionHandler.java添加方法

    /**
     * 处理SQL异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        //Duplicate entry 'zhangsan' for key 'employee.idx_username'
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] split = message.split(" ");
            String username = split[2];
            String msg = username + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }

/**
 * 处理SQL异常
 *
 * @param ex
 * @return contains:包含
 * Duplicate entry:重复的健值对
 */
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {


    //Duplicate entry 'zhangsan' for key 'employee.idx_username'
    //获取异常信息
    String message = ex.getMessage();
    /**
     * 如果包含Duplicate entry
     * 就可以确认输出的日志信息就是Duplicate entry 'zhangsan' for key 'employee.idx_username'
     * 这个时候 我们希望给前端一个提示
     * 提示zhangsan用户名已经存在  应该返回一个提示信息
     * 所以我们这个就要动态的把'zhangsan'提出出来
     * 我们观察这个信息Duplicate entry 'zhangsan' for key 'employee.idx_username'是通过空格进行分隔
     分隔完之后   我们发现zhangsan是在第三个



     */
    //判断是否包含Duplicate entry
    if (message.contains("Duplicate entry")) {
        //根据空格"" 进行分隔  得到一个数组对象
        String[] split = message.split("");
        //zhangsan是在数组对象里面的第三个  所以就取到用户名
        String username = split[2];
        //用户名已经存地
        String msg = username + MessageConstant.ALREADY_EXISTS;
        //把msg 用户名已存在封装到Result返回
        return Result.error(msg);
    }else {
        return Result.error(MessageConstant.UNKNOWN_ERROR);
    }


}

进入到sky-common模块,在MessageConstant.java添加

public static final String ALREADY_EXISTS = "已存在";

再次,接口测试:

控制台就不会有异常信息

因为数据库抛出异常之后   被我们的异常处理方法给捕获了    捕获之后  经过正常的处理 

给前端返回一个提示“用户名已存在”数据

1.4.2 问题二

描述:新增员工时,创建人id和修改人id设置为固定值

分析:

    /**
     * 新增员工
     *
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        //................
        //当前设置的id为固定值10//
        employee.setCreateUser(10L);
        employee.setUpdateUser(10L);
        //
        //.................................

        employeeMapper.insert(employee);//后续步骤定义
    }

解决:

通过某种方式动态获取当前登录员工的id。

员工登录成功后会生成JWT令牌并响应给前端:

前端发起请求  把用户名和密码发给后端        后端就可以进行校验

比如进行密码的比对   假设比对成功了  这个时候就会生成一个令牌

也就是JWT的一个token ,然后把token返回给我们的客户端

客户端就会把token保存下来 ,后续的请求都会在请求头携带token

请求过来之后   首先被我们的拦截器  也就是我们进行token校验的一个拦截器

给拦截到  然后在这个地方来检查token 

检查之后    来嘛通过  要嘛不通过

如果通过 就放行  去正常执行 我们的业务逻辑 如果不通过   我们程序就会返回错误信息

直接返回一个401的状态码,401的状态码就是没有授权,然后把状态码返回给我们前端

前端在去展示相对应的错误信息 并且跳转到登录页面

在sky-server模块

package com.sky.controller.admin;
/**
 * 员工管理
 */
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "员工相关接口")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        //.........

        //登录成功后,生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        //............

        return Result.success(employeeLoginVO);
    }

}

后续请求中,前端会携带JWT令牌,通过JWT令牌可以解析出当前登录员工id:

JwtTokenAdminInterceptor.java

package com.sky.interceptor;

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       
        //..............
        
        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }
}

思考:解析出登录员工id后,如何传递给Service的save方法?

通过ThreadLocal进行传递。

一次请求一个线程

客户端每一次发请的请求都是单独的线程

  • 23
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值