瑞吉外卖知识点总结

Posted 硅谷工具人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瑞吉外卖知识点总结相关的知识,希望对你有一定的参考价值。

文章目录

1. 手机验证码功能实现

1.1 业务流程:

(1)业务端输入手机号,点击发送
(2)后台接收请求,验证手机号,生成验证码。
这里要注意验证码是在后台生成好的。我原来一直以为手机里的验证码是运营商生成的,原来是错误的。
(3)将生成验证码并通过阿里云接口向指定的手机号发送。
(4)手机接收到验证码后,填写到前端,登录
(5)后台根据前端填写的验证码和手机号和后端去匹配,如果一致就通过,否则,返回错误信息。

1.2 依赖包

        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.16</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>2.1.0</version>
        </dependency>

1.3 工具类

阿里短信的工具类,最后一个param就是传入后台生成的验证吗。

package com.guigutool.reggie.utils;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;

/**
 * 短信发送工具类
 */
public class SMSUtils 

	/**
	 * 发送短信
	 * @param signName 签名
	 * @param templateCode 模板
	 * @param phoneNumbers 手机号
	 * @param param 参数
	 */
	public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param)
		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");
		IAcsClient client = new DefaultAcsClient(profile);

		SendSmsRequest request = new SendSmsRequest();
		request.setSysRegionId("cn-hangzhou");
		request.setPhoneNumbers(phoneNumbers);
		request.setSignName(signName);
		request.setTemplateCode(templateCode);
		request.setTemplateParam("\\"code\\":\\""+param+"\\"");
		try 
			SendSmsResponse response = client.getAcsResponse(request);
			System.out.println("短信发送成功");
		catch (ClientException e) 
			e.printStackTrace();
		
	



1.4 登录案例实现

(1) 点击发送验证码按钮,后端的处理

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/sendMsg")
    public R<String> sendMsg(@RequestBody User user, HttpSession session)
        //获取手机号
        String phone = user.getPhone();
        if(StringUtils.isNotEmpty(phone))
            //生成随机的4位验证吗
            String code = ValidateCodeUtils.generateValidateCode(4).toString();
            log.info("code:", code);
            //调用阿里云提供的短信API完成发送短信
            SMSUtils.sendMessage("Reggie","",phone,code);
            //需要将生成的验证码保存到Session
            //session.setAttribute(phone,code);
            //将生成的验证码保存到Redis中,并且设置有效期为5分钟
            redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
            return R.success("验证码发送成功");
        
        return R.error("验证码发送失败");

    

(2) 填写验证码后,登录处理

 /**
     * 移动端用户登录
     * @param map
     * @param session
     * @return
     */
    @PostMapping("/login")
    public R<User> login(@RequestBody Map map, HttpSession session)
        String phone = map.get("phone").toString();
        String code = map.get("code").toString();

//        Object codeInSession = session.getAttribute(phone);
        //从redis中获取缓存的验证码
        Object codeInSession = redisTemplate.opsForValue().get(phone);
        if(Objects.nonNull(codeInSession) && codeInSession.equals(code))

            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getPhone,phone);
            User user = userService.getOne(queryWrapper);
            if(Objects.isNull(user))
                user = new User();
                user.setPhone(phone);
                user.setStatus(1);
                userService.save(user);
            

            //登录成功
            session.setAttribute(SystemConstant.MOBILE_USER_ID,user.getId());
            //如果用户登录成功,则删除Redis中缓存的验证码
            redisTemplate.delete(phone);
            return R.success(user);
        

        return R.error("登录失败");

    

2. 缓存

2.1 Cache缓存

SpringCache是一个基于注解的缓存功能,只要简单的加一个注解,就能实现缓存功能。
SpringCache也提供了一层抽象接口,底层可以切换不同的cache实现类,接口名称是CacheManager。
CacheManager是Spring提供的各种缓存技术抽象接口。
以下是一些一些不同的实现类:

CacheManager描述
EhCacheCacheManager使用EhCache作为缓存技术
GuavaCacheManager使用Google的GuavaCache作为缓存技术
RedisCacheManager使用Redis作为缓存技术

2.2 SpringCache缓存使用

(1)默认配置
只要加入spring-boot-starter-web,就会存在SpringCache的配置。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
        </dependency>

默认有以下4个实现类,所以可以不做任何改动。

(2) 在启动应用主程序添加@EnableCaching注解

(3) 注入

    //Ctrl+Alt+鼠标左点击,可查看该接口的实现类
    @Autowired
    private CacheManager cacheManager;

(4)注解说明

注解说明用途
@EnableCaching开启缓存注解功能全部配置,在启动app类上注解
@Cacheable在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中查询操作
@CachePut将方法的返回值放到缓存中保存或者修改操作
@CacheEvict将一条或者多条记录从缓存中删除删除操作

(5)使用案例
定义缓存的名称

private final String cacheName = "userCache";  

保存操作

    /**
     * cachePut:将方法返回值放入缓存
     * value: 缓存的名称,每个缓存名称下可以有多个key
     * key:缓存的key, 这个取自于方法的返回值
     * 例如:这里的key使用的是返回的user对象的id
     */
    @CachePut(value=cacheName, key = "#result.id")
    @PostMapping
    public User save(User user)
        userService.save(user);
        return user;
    

删除操作

    /**
     * 这里的key使用的是传入的参数
     * @param id
     */
    @CacheEvict(value = cacheName, key="#id")
    @DeleteMapping("/id")
    public void delete(@PathVariable Long id)
        userService.removeById(id);
    

修改操作

//    @CacheEvict(value = cacheName, key="#p0.id")       (1)根据接收的参数设置的key
//    @CacheEvict(value = cacheName, key="#user.id")     (2)根据接收的参数设置的key
//    @CacheEvict(value = cacheName, key="#root.args[0].id")  (3)根据接收的参数设置的key
//    @CacheEvict(value = cacheName, key="#result.id")   (4)根据返回的值设置的key
    @CacheEvict(value = cacheName, key="#result.id")
    @PutMapping
    public User update(User user)
        userService.updateById(user);
        return user;
    

查询操作
condition 满足条件时,才缓存

    /**
     * condition: 条件,满足条件时,才缓存数据
     * unless: 满足条件,不缓存  #注意这里会发生缓存穿透,就是当用户查询的数据不存在时,会一直调用sql,如果有太多的请求请数据库发送sql语句,也会加重数据库的负载
     */
    @Cacheable(value = cacheName,key="#id", condition = "#result != null")
    @GetMapping("/id")
    public User getById(@PathVariable Long id)
        User user = userService.getById(id);
        return user;
    

unless: 满足条件时,不缓存

    /**
     * condition: 条件,满足条件时,才缓存数据
     * unless: 满足条件,不缓存  #注意这里会发生缓存穿透,就是当用户查询的数据不存在时,会一直调用sql,如果有太多的请求请数据库发送sql语句,也会加重数据库的负载
     */
    @Cacheable(value = cacheName,key="#id", unless = "#result == null")
    @GetMapping("/id")
    public User getById(@PathVariable Long id)
        User user = userService.getById(id);
        return user;
    

    @Cacheable(value = cacheName, key = "#user.id+':'+#user.name")
    @GetMapping("/list")
    public List<User> list(User user)
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Objects.nonNull(user.getName()),User::getName, user.getName());
        List<User> userList = userService.list(wrapper);
        return userList;
    

2.3 SpringRedis缓存

添加依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

yml添加:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
  cache:
    redis:
      time-to-live: 1800000 #设置缓存有效期

从SpringCache缓存切换到Redis缓存,只需要修改配置即可。

3. 接口文档Swagger

3.1 增强版本

使用增强功能knife4j
(1) Pom配置

        <!--  增强swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

(2) WebMvc配置

/**
 * @Author: KingWang
 * @Date: 2023/3/7
 * @Desc:
 **/
@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport 

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) 
        log.info("开始静态资源映射..");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");

        //swagger文档需要添加下面2行
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    


    @Bean
    public Docket createRestApi()
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.guigutool.reggie.controller"))
                .paths(PathSelectors.any())
                .build();
    

    public ApiInfo apiInfo()
        return new ApiInfoBuilder()
                .title("瑞吉外卖")
                .version("1.0")
                .description("瑞吉外卖接口文档")
                .build();
    


(3) 过滤中放行静态资源访问权限
LoginCheckFilter中的doFilter方法,如果不放行,则需要登录后才可以查看doc.html。

@Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException 

        log.info("拦截到请求:", request.getRequestURI());
        //1. 获取本次请求的URI
        String requestURI = request.getRequestURI();

        //2.定义不需要处理的请求路径
        String[] urls = new String[]
                "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**",
                "/common/**",
                "/user/sendMsg", //移动端发送短信
                "/user/login", //移动端登录
               
                "/doc.html",  //生成swagger api文件,这里不放行,在登录后,也可以查看
                "/webjars/**",
                "/swagger-resources",
                "/v2/api-docs"
        ;
        
        //其他内容省略...
     

    

(4) 接口文档查看
地址:http://localhost:8080/doc.html#/home

3.2 常用Swagger注解

注解说明
@Api用于请求的类上,例如Controller,表示对类的说明
@ApiModel用在类上,通常是实体类,表示一个返回响应数据的信息
@ApiModelProperty用在属性上,描述响应类的属性
@ApiOperation用在请求的方法上,说明方法的用途,作用
@ApiImplicitParams用在请求的方法上,表示一组参数说明
@ApiImplicitParam用在@ApiImplicitParams注解中,指定一个请求参数的各个方面

3.3 Swagger注解实例

(1)实体类注解

/**
 * 套餐
 */
@Data
@ApiModel("套餐")
public class Setmeal implements Serializable 

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("主键Id")
    private Long id;


    @ApiModelProperty("分类Id")
    private Long categoryId;


    @ApiModelProperty("套餐名称")
    private String name;


    @ApiModelProperty("套餐价格")
    private BigDecimal price;


    @ApiModelProperty("状态 0:停用 1:启用")
    private Integer status;


    @ApiModelProperty("编码")
    private String code;


    @ApiModelProperty("描述信息")
    private String description;


    @ApiModelProperty("图片")
    private String image;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;

(2)Controller注解

/**
 * @Author: KingWang
 * @Date: 2023/3/14
 * @Desc:
 **/
@RequestMapping("/setmeal")
@Slf4j
@RestController
@Api(tags="套餐相关接口")
public class SetmealController 

    private final String cacheName = "setmealCache";

    @Autowired
    private SetmealDishService setmealDishService;
    @Autowired
    private SetmealService setmealService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 新增套餐
     * @param setmealDto
     * @return
     */
    @ApiOperation(value = "新增套餐")
    @PostMapping
    @CacheEvict(value = cacheName, allEntries = true)
    public R<String> save(@RequestBody SetmealDto setmealDto)

        setmealService.saveWithDish(setmealDto);
        Set keys = redisTemplate.keys("setmeal:*");
        redisTemplate.delete(keys)

黑马瑞吉外卖——

黑马瑞吉外卖项目部分知识总结,对项目中的难点、不熟悉内容、项目亮点以及bug进行记录与分享。以及项目中用到的设计思想进行总结
黑马瑞吉外卖项目部分知识总结,对项目中的难点、不熟悉内容、项目亮点以及bug进行记录与分享。以及项目中用到的设计思想进行总结

以上是关于瑞吉外卖知识点总结的主要内容,如果未能解决你的问题,请参考以下文章

瑞吉外卖知识点总结

瑞吉外卖(个人记录)

登录功能和退出功能(瑞吉外卖)

黑马Java笔记+踩坑汇总JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud/SpringCloudAlibaba+黑马旅游+谷粒商城

瑞吉外卖笔记

Java项目瑞吉外卖保姆级学习笔记(改项目名称+改邮件验证码登录+功能补充)