第十二章 企业级微信点餐项目(卖家登陆)

卖家登陆

标签(空格分隔): springboot java wechat


分布式session

  • 登陆(验证身份,存储信息)

  • 登出(失效浏览状态)

  • 分布式
    特点:多节点、消息通信、不共享内存

    概念:分布式系统、集群、分布式计算

    分布式: 不同节点,相会组合应用,集群:相同节点,相会组合应用。

    本视频的分布式session通过redis库来做用户验证。

  • 卖家表

create table `seller_info`(
    `seller_id` varchar(32) not null,
    `username` varchar(32) not null,
    `password` varchar(32) not null,
    `openid` varchar(64) not null comment '微信openid',
    `create_time` timestamp not null default current_timestamp comment '创建时间',
    `update_time` timestamp not null default current_timestamp on update current_timestamp comment '更新时间',
    primary key(`seller_id`)
) comment '卖家信息表';
  • dao层创建并测试

这里就不过多描述,model创建,jpa继承,插入和查询单元测试。

  • service层的开发

简单的一个openid查询获取用户信息,别忘了单元测试

扫码登陆

  • 扫码获取用户openid
@Autowired
private WechatAccountConfig wechatAccountConfig;

/**
* 配置设置
* @return
*/
@Bean
public WxMpService wxOpenMpService(){
    WxMpService wxOpenService = new WxMpServiceImpl();
    wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage());
    return wxOpenService;
}

/**
* 返回参数
* @return
*/
@Bean
public WxMpConfigStorage wxOpenConfigStorage(){
    WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
    wxMpInMemoryConfigStorage.setAppId(wechatAccountConfig.getOpenAppid());
    wxMpInMemoryConfigStorage.setSecret(wechatAccountConfig.getOpenSecret());
    return wxMpInMemoryConfigStorage;
}
/**
* 微信开放平台重定向
* @param returnUrl
* @return
*/
@GetMapping("/qrAuthrize")
public String qrAuthrize(@RequestParam("returnUrl") String returnUrl){
    String url = projectUrl.getWechatOpenAuthrize() + "/sell/wechat/qruserinfo";
    String rediectUrl = wxOpenMpService.buildQrConnectUrl(url,WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, URLEncoder.encode(returnUrl));
    return "redirectUrl:" + rediectUrl;
}

/**
* 微信开放平台重定向
* @param code
* @param returnUrl
* @return
*/
@GetMapping("/qruserinfo")
public String qruserinfo(@RequestParam("code") String code,
    @RequestParam("state") String returnUrl){
    WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
    try {
        wxMpOAuth2AccessToken = wxOpenMpService.oauth2getAccessToken(code);
    }catch (WxErrorException e){
        log.error("【微信网页授权】 e={}",e);
        throw new SellException(ResultEnum.WECHAT_WEB_ERROR.getCode(),e.getError().getErrorMsg());
    }
    String openid = wxMpOAuth2AccessToken.getOpenId();

    return "redirectUrl:"+ returnUrl + "?openid="+openid;
}
  • redis和cookie用户身份缓存设置登陆操作
@RequestMapping("/login")
public ModelAndView login(@RequestParam("openid")String openid,HttpServletResponse response,Map map){
    //openid数据匹配
    SellerInfo sellerInfo = sellerService.findBySellerInfoOpenid(openid);
    if(sellerInfo == null){
        map.put("msg", ResultEnum.SELLER_USER_LOGIN.getMessage());
        map.put("url","/sell/seller/order/list");
        return new ModelAndView("common/error",map);
    }

    // 设置token至redis
    String token = UUID.randomUUID().toString();
    Integer maxAge = RedisConstant.EXPIRE;
    redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX,token),
                openid,maxAge, TimeUnit.SECONDS);
    //设置token至cookie
    CookieUtil.set(response, CookieConstant.NAME,token,maxAge);
    return new ModelAndView("redirect:" + "/seller/order/list");
}
  • 登出操作
//通过便利cookie并找到浏览器的存储值,通过重新设置为控制,过期时间为0
/**
* 登出成功
* @param request
* @param response
* @param map
* @return
*/
@GetMapping("/logout")
public ModelAndView logout(HttpServletRequest request,HttpServletResponse response,Map map){
    // 获取cookie内容
    Cookie cookie = CookieUtil.get(request,CookieConstant.NAME);
    if(cookie != null){
        // 清楚redis数据库中的值
        redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue()));

        // 清除cookie 的值
        CookieUtil.set(response,CookieConstant.NAME,null,0);
    }
    map.put("msg",ResultEnum.SELLER_SUCCESS_LOGOUT);
    map.put("url","/sell/seller/order/list");
    return new ModelAndView("common/success",map);
}
/**
* cookie匹配返回
* @param request
* @param name
* @return
*/
public static Cookie get(HttpServletRequest request,String name){
    Map map =  getCookieMap(request);
    if(map.containsKey(name)){
        return map.get(name);
    }else{
        return null;
    }
}

/**
* cookie 集合转换map
* @param request
* @return
*/
private static Map getCookieMap(HttpServletRequest request){
    Map mapResult = new HashMap();
    Cookie[] cookies = request.getCookies();
    for(Cookie cookie:cookies){
        mapResult.put(cookie.getName(),cookie);
    }
    return mapResult;
}

AOP身份验证

  • 切片认证
@Autowired
private StringRedisTemplate redisTemplate;

/**
* 拦截规则
*/
@Pointcut(value = "execution(public * com.xiaojinzi.controller.Seller*.*(..))" +
    "&& !execution(public * com.xiaojinzi.controller.SellerUserController.*(..))")
public void verify(){
}
    
/**
*拦截处理
*/
@Before("verify()")
public void doverify(){
    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = requestAttributes.getRequest();
    Cookie cookie = CookieUtil.get(request, CookieConstant.NAME);
    if(cookie==null){
        log.trace("【登陆验证】 cookie不存在");
        throw new SellerAuthorizeException();
    }
    String token = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue()));
    if(token==null){
        log.trace("【登陆验证】 redis数据库token不存在");
    }
}
  • 拦截后处理
 //拦截处理
@ExceptionHandler(value = SellerAuthorizeException.class)
public ModelAndView handlerException(){
    return new ModelAndView("redirect:"
        .concat(projectUrl.getWechatMpAuthrize())
        .concat("/seller/wehcat/qrAuthrize")
        .concat("?returnUrl=")
        .concat(projectUrl.getSell())
        .concat("/sell/seller/order/list"));
}

webSocke消息推送

  • 客户端
//js

<#--弹窗-->

<#--播放音乐-->



  • 服务端
//websocketConfig
@Component
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
//消息通信
@Component
@ServerEndpoint("/websocket")
@Slf4j
public class WebSocket {
    /** session 对象. */
    private Session session;

    private static CopyOnWriteArrayList webSocketSet = new CopyOnWriteArrayList<>();
    
    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        webSocketSet.add(this);
        log.info("【WebSocke通信】开始链接 通信数量={}",webSocketSet.size());
    }

    @OnClose
    public void onClose(){
        webSocketSet.remove(this);
        log.info("【WebSocke通信】连接关闭 通信数量={}",webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message){
        log.info("【WebSocke通信】收到消息发送 消息内容={}",message);
    }

    /**
     * 发送消息
     * @param message
     */
    public void sendMessage(String message){
        for(WebSocket webSocket:webSocketSet){
            try {
                webSocket.session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

//下订单触发消息发送
webSocket.sendMessage(orderId);


  • 原视频UP主慕课网(SpringBoot企业级微信点餐项目)
  • 本篇博客撰写人: XiaoJinZi 转载请注明出处
  • 学生能力有限 附上邮箱: [email protected] 不足以及误处请大佬指责

你可能感兴趣的:(第十二章 企业级微信点餐项目(卖家登陆))