苍穹外卖的学习心得

苍穹外卖心得

对于数据库的理解:

员工数据库:结构为

苍穹外卖的学习心得_第1张图片

苍穹外卖的学习心得_第2张图片

day01

员工登陆的实现,登陆后生成一个token,用户携带这个token就能访问登陆之后的界面

定义了一个Result用作返回的数据类型

由于和前端页面联调后端的Employee类中字段名过多,而前端需要回显的字段名少,所以又创建了EmployeeDTO类用于封装数据传输对象(将数据库中的数据转换为前端需要的格式,方便前后端之间的数据交互)以及EmployeeVO类用于封装值对象(方便前端页面的显示和交互)。

Controller层:

@PostMapping("/login")
​
@ApiOperation(value = "员工登录")
​
public Result login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
     //传进来一个json对象
     //返回数据是什么类型,泛型就是什么类型
     log.info("员工登录:{}", employeeLoginDTO);
     //日志级别:等级由低到高:debug claims = new HashMap<>();
•    claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
•    String token = JwtUtil.createJWT(
•            jwtProperties.getAdminSecretKey(),
•            jwtProperties.getAdminTtl(),
•            claims);
​
•    EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
•            .id(employee.getId())
•            .userName(employee.getUsername())
•            .name(employee.getName())
•            .token(token)
•            .build();
​
•    return Result.success(employeeLoginVO);
}

service层:

public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();
        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);
        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        //密码比对
        //对前端传过来的明文密码进行md5加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }
        //3、返回实体对象
        return employee;
    }
​
public static String createJWT(String secretKey, long ttlMillis, Map claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
​
        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);
​
        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);
​
        return builder.compact();
    }
​
    /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }
​

进行md5加密为了密码不在前端页面明文显示以及设置数字签名。

生成jwt令牌是为了避免多次查询数据库,通过设置拦截器可以更方便的让用户访问管理端允许访问的资源。(token包含了所需要的信息)即用户在登录后得到一个token,之后用户每次访问其他资源时都要带上这个token验证身份,所以需要检查token是否存在。

day02

controller:

@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
    log.info("新增员工:{}",employeeDTO);
    employeeService.save(employeeDTO);
    return Result.success();
}

分页查询运用了分页查询PageHelper

day03

新增员工或修改员工数据的时候,会设置修改时间和修改人的数据,故设置一个公共字段自动填充的功能方便自动填充

在这之前科普一下AOP


AOP:面向切面编程

相关概念:

Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。 Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。 Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。 Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。 Target(目标对象):织入 Advice 的目标对象.。 Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

苍穹外卖的学习心得_第3张图片


首先要创建一个AutoFill的annotation注解,并且添加相应的Target注解和Retention注解来说明这个自定义的注解用在什么地方以及在什么时候生效。

//自定义注解,用于标识某个方法需要进行功能字段自动填充处理
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //数据库操作类型:UPDATE INSERT
    OperationType value();
}

然后再创建一个自定义Aspect,

//自定义切面,实现公共字段自动填充处理逻辑
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    //切入点
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)") 
    public void autoFillPointCut(){}
    //前置通知,在通知中进行公共字段的赋值
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进行公共字段自动填充...");
    }
}

切入点:对哪些类的哪些方法进行拦截。@Pointcut里面写的是对哪些方法进行拦截,要满足2点:①必须是mapper下的所有类的方法,②还要有AutoFill这个注解。

day04略

day05

Redis入门一些简单的Redis使用方法和介绍。

day06

HttpClient:

HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http协议的),提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

day07

由于菜品和套餐存储在数据库中,而mysql数据库在短期内有大量的人查询会导致数据库压力过大,对于数据的回显响应太慢,是用户体验不佳,所以使用redis技术将数据存入到redis中,因为redis的数据是存放在内存中的,内存操作的性能比磁盘IO性能更高。而且redis的性能极高。

实现缓存:

springCache封装了RedisTemplate。

运用了springCache,springboot的启动类上加上EnableCaching注解来开启springboot的启动,用Cacheable来根据请求的参数对其进行缓存,指定缓存的类型和对象。

@Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。

day08

微信支付略

day09

day10

springTask(定时任务框架):

在启动类加上注解@EnableScheduling开启定时任务功能

运用@Scheduled自定义定时任务(cron表达式有在线生成网站)

webSocket;

实现实时接收用户信息的功能--点单退单等操作。

相关概念:

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;

  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

你可能感兴趣的:(java,spring,maven,spring,boot,ide,git,github)