第三方接口对接微信登录(包括糊涂工具包)

微信登录的接口

我们来看一下微信官方给提供的这个接口,这个是用于微信登录的接口,链接如下:

https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html

这个文档中比较关键的部分就是:

  • 功能描述,查阅是否符合我们业务对接的需求

  • 调用方式,三方接口一般都是https居多,更加安全,包含了请求方式和请求地址

  • 请求参数,接口的入参,特别注意的是,必须要传的参数

  • 返回参数,查看返回的数据结构和内容,是否符合自己的返回预期

  • 错误码,当接口调用失败的时候,可以查阅以方便修正接口调用失败原因

  • HTTP客户端工具有很多

  • HttpClient 体量庞大,jdk11以上支持不好

  • OkHttp 学习成本较高

  • Spring提供的RestTemplate 后期课程feign会重点讲解

  • 糊涂工具包,使用说明地址:https://doc.hutool.cn/pages/http/

Hutool-http优点

  1. 根据URL自动判断是请求HTTP还是HTTPS,不需要单独写多余的代码。
  2. 表单数据中有File对象时自动转为multipart/form-data表单,不必单独做操作。
  3. 默认情况下Cookie自动记录,比如可以实现模拟登录,即第一次访问登录URL后后续请求就是登录状态。
  4. 自动识别304跳转并二次请求
  5. 自动识别页面编码,即根据header信息或者页面中的相关标签信息自动识别编码,最大可能避免乱码。
  6. 自动识别并解压Gzip格式返回内容

糊涂工具常见方法

1.添加单元测试依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>

2.

  • get请求

@Test
public void testGet() {
    // 最简单的HTTP请求,可以自动通过header等信息判断编码,不区分HTTP和HTTPS
    String result = HttpUtil.get("https://www.baidu.com");
    System.out.println(result);
}

@Test
public void testGetByParam() {
    //可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
    HashMap<String, Object> paramMap = new HashMap<>();
    paramMap.put("pageNum", 1);
    paramMap.put("pageSize", 10);
    String result = HttpUtil.get("http://localhost:9995/nursing_project", paramMap);
    System.out.println(result);
}

@Test
public void testCreateRequest() {
    String url = "http://localhost:9995/nursing_project";
    HashMap<String, Object> paramMap = new HashMap<>();
    paramMap.put("pageNum", 1);
    paramMap.put("pageSize", 10);
    HttpResponse response = HttpUtil.createRequest(Method.GET, url)
            .form(paramMap)
            .execute();
    if (response.getStatus() == 200) {
        System.out.println(response.body());
    }
}
  • post请求

@Test
public void testPost(){
    String url = "http://localhost:9995/nursing_project";
    HashMap<String, Object> paramMap = new HashMap<>();
    paramMap.put("name", "护理项目测试");
    paramMap.put("orderNo", 1);
    paramMap.put("unit", "次");
    paramMap.put("price", 10.00);
    paramMap.put("image", "https://yjy-slwl-oss.oss-cn-hangzhou.aliyuncs.com/ae7cf766-fb7b-49ff-a73c-c86c25f280e1.png");
    paramMap.put("nursingRequirement", "无特殊要求");
    paramMap.put("status", 1);
    String result = HttpUtil.post(url, JSONUtil.toJsonStr(paramMap));
    System.out.println(result);
}

@Test
public void testPost2(){
    String url = "http://localhost:9995/nursing_project";
    HashMap<String, Object> paramMap = new HashMap<>();
    paramMap.put("name", "护理项目测试2");
    paramMap.put("orderNo", 1);
    paramMap.put("unit", "次");
    paramMap.put("price", 10.00);
    paramMap.put("image", "https://yjy-slwl-oss.oss-cn-hangzhou.aliyuncs.com/ae7cf766-fb7b-49ff-a73c-c86c25f280e1.png");
    paramMap.put("nursingRequirement", "无特殊要求");
    paramMap.put("status", 1);
    HttpResponse response = HttpUtil.createRequest(Method.POST, url)
            .body(JSONUtil.toJsonStr(paramMap))
            .execute();
    if(response.getStatus() == 200){
        System.out.println(response.body());
    }
}

以上两个方法调用相对简单,如果请求参数中没有额外的条件设置,就可以使用上述的两个方法,但是,有的时候三方接口调用需要使用到header或者是文件上传,则不能使用上述两个方法

我们可以使用HttpUtil.createRequest方法来去构建更多的条件参数

查询天气预报

接口文档说明:https://market.aliyun.com/products/57096001/cmapi013828.html?spm=5176.730005.result.10.27823524RFEJhP&innerSource=search_%E5%A4%A9%E6%B0%94%E9%A2%84%E6%8A%A5#sku=yuncode782800000

使用糊涂工具调用天气预报接口:

 
@Test
public void testWeater() {
    String url = "https://aliv18.data.moji.com/whapi/json/alicityweather/forecast24hours";
    String appcode = "d0bbfea3151e8bc1b";
    Map<String, Object> param = new HashMap<String, Object>();
    param.put("cityId", "2");

    HttpResponse response = HttpUtil.createRequest(Method.POST, url)
            .header("Authorization", "APPCODE " + appcode)
            .form(param)
            .execute();
    if (response.getStatus() == 200) {
        System.out.println(response.body());
    }

}

响应的结果:

{
  "code": 0,
  "data": {
    "city": {
      "cityId": 2,
      "counname": "中国",
      "ianatimezone": "Asia/Shanghai",
      "name": "北京市",
      "pname": "北京市",
      "secondaryname": "北京市",
      "timezone": "8"
    },
    "hourly": [
      {
        "condition": "晴",
        "conditionId": "5",
        "date": "2024-01-04",
        "hour": "20",
        "humidity": "20",
        "iconDay": "0",
        "iconNight": "30",
        "pop": "0",
        "pressure": "1014",
        "qpf": "0",
        "realFeel": "1",
        "snow": "0",
        "temp": "7",
        "updatetime": "2024-01-04 20:12:16",
        "uvi": "1",
        "windDegrees": "0",
        "windDir": "N",
        "windSpeed": "22.284",
        "windlevel": "4"
      },
      {
        "condition": "晴",
        "conditionId": "5",
        "date": "2024-01-04",
        "hour": "21",
        "humidity": "39",
        "iconDay": "0",
        "iconNight": "30",
        "pop": "0",
        "pressure": "1022",
        "qpf": "0.0",
        "realFeel": "-1",
        "snow": "0",
        "temp": "5",
        "updatetime": "2024-01-04 20:12:16",
        "uvi": "1",
        "windDegrees": "315",
        "windDir": "WNW",
        "windSpeed": "24.08",
        "windlevel": "4"
      }
    ]
  },
  "msg": "success",
  "rc": {
    "c": 0,
    "p": "success"
  }
}

微信登录的流程

注意点:

  • 前端在小程序中集成微信相关依赖,当用户请求登录的同时,调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。

  • 后端服务器调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台账号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台账号) 和 会话密钥 session_key

  • 开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

  1. 表结构设计

从小程序端登录的用户主要有两类,第一类是参观预约的用户,第二类是,老人的家人(子女),方便查看老人信息、给老人下单、查看账单、查看合同等服务。

如果是老人的家人,需要跟入住的老人进行绑定,方便后期的更多服务,所以,在小程序端登录的用户,我们需要保存下来,保存到一张表中 member(客户表)

根据我们梳理的信息,我们现在可以大概知道,客户表中比如会有如下字段:

  • 主键、手机号、名称、头像、微信OpenID(个人微信唯一ID)、性别

然后再加上必要的字段:

  • 创建时间、更新时间、创建人、更新人、备注

最终的创建表的sql如下:

CREATE TABLE "member" (
  "id" bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  "phone" varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号',
  "name" varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '名称',
  "avatar" varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像',
  "open_id" varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'OpenID',
  "gender" int DEFAULT NULL COMMENT '性别(0:男,1:女)',
  "create_time" timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  "update_time" timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  "create_by" bigint DEFAULT NULL COMMENT '创建人',
  "update_by" bigint DEFAULT NULL COMMENT '更新人',
  "remark" varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
  PRIMARY KEY ("id") USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  1. 登录接口说明

这个接口跟我们平时开发的接口略有不同,这个需要参考微信开发者平台提供的流程来开发。

目前,小程序的代码已经开发完了,我们需要在后台提供接口就可以了

  • 接口路径(已固定):/customer/user/login

  • 请求方式(已固定):POST

    • 请求参数:(已固定)

      {

          "code": "0e36jkGa1ercRF0Fu4Ia1V3fPD06jkGW", //临时登录凭证code     "nickName": "微信用户",

          "phoneCode":"13fe315872a4fb9ed3deee1e5909d5af60dfce7911013436fddcfe13f55ecad3" }

        以上三个参数,都是前端开发人员调用wx.login()方法返回的数据

      • code:临时登录凭证code

      • nickName:微信用户昵称(现在微信统一返回为:微信用户)

      • phoneCode:详细用户信息code,后台根据此code可以获取用户手机号

      • 响应示例

  • {
      "code": 200,
      "msg": "操作成功",
      "data": {
        "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiLlpb3mn7_lvIDoirE4OTE1IiwiZXhwIjoxNDY1MjI3MTMyOCwidXNlcmlkIjoxfQ.nB6ElZbUywh-yiHDNMJS8WqUpcLWCszVdvAMfySFxIM",
        "nickName": "好柿开花8915"
      },
      "operationTime": null
    }

    微信登录后端接口实现

如图所视:我们对于wechat的接口服务有2个接口方法:

1.获取openId

2.获取手机号

我们可用参考微信小程序开发的文档:

可以确认在开发中的模板: 

        1.新增类CustomerUserController         

/**
 * <p>
 * 用户管理
 */
@Slf4j
@Api(tags = "客户管理")
@RestController
@RequestMapping("/customer/user")
public class CustomerUserController {

    @Autowired
    private MemberService memberService;

    /**
     * C端用户登录--微信登录
     * @param userLoginRequestDto 用户登录信息
     * @return 登录结果
     */
    @PostMapping("/login")
    @ApiOperation("小程序端登录")
    public ResponseResult<LoginVo> login(@RequestBody UserLoginRequestDto userLoginRequestDto){
        LoginVo loginVo = memberService.login(userLoginRequestDto);
        return ResponseResult.success(loginVo);
    }

}

        2.UserLoginRequestDto 

/**
 * C端用户登录
 */
@Data
public class UserLoginRequestDto {

    @ApiModelProperty("昵称")
    private String nickName;

    @ApiModelProperty("登录临时凭证")
    private String code;

    @ApiModelProperty("手机号临时凭证")
    private String phoneCode;
}

        3.返回类型:LoginVo

@Data
@ApiModel(value = "登录对象")
public class LoginVo {

    @ApiModelProperty(value = "JWT token")
    private String token;

    @ApiModelProperty(value = "昵称")
    private String nickName;
}

        4.mapper

@Mapper
public interface MemberMapper {

    @Select("SELECT * FROM member WHERE open_id = #{openId}")
    Member getByOpenId(String openId);

    void save(Member member);

    void update(Member member);
}

        5.mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zzyl.mapper.MemberMapper">
    <resultMap id="BaseResultMap" type="com.zzyl.entity.Member">
        <id column="id" property="id" />
        <result column="phone" property="phone" />
        <result column="name" property="name" />
        <result column="avatar" property="avatar" />
        <result column="open_id" property="openId" />
        <result column="gender" property="gender" />
        <result column="create_by" property="createBy"/>
        <result column="update_by" property="updateBy"/>
        <result column="remark" property="remark"/>
        <result column="create_time" property="createTime"/>
        <result column="update_time" property="updateTime"/>
    </resultMap>
    <insert id="save" parameterType="com.zzyl.entity.Member" keyProperty="id" useGeneratedKeys="true">
        INSERT INTO member ( phone, name, avatar, open_id, gender, create_by, create_time)
        VALUES ( #{phone}, #{name}, #{avatar}, #{openId}, #{gender}, #{createBy}, #{createTime})
    </insert>

    <update id="update" parameterType="com.zzyl.entity.Member">
        UPDATE member SET
                          phone = #{phone},
                          name = #{name},
                          avatar = #{avatar},
                          open_id = #{openId},
                          gender = #{gender},
                          update_by = #{updateBy},
                          update_time = #{updateTime}
        WHERE id = #{id}
    </update>

</mapper>

        

我们可以先分析微信开发者平台的接口,接口地址:

  1. 1.微信接口调用-单独封装

      新增WechatService

          

public interface WechatService {

    /**
     * 获取openid
     * @param code  登录凭证
     * @return
     * @throws IOException
     */
    public String getOpenid(String code) ;

    /**
     * 获取手机号
     * @param code  手机号凭证
     * @return
     * @throws IOException
     */
    public String getPhone(String code);

}

WechatService实现类

@Service
public class WechatServiceImpl implements WechatService {


    // 登录
    private static final String REQUEST_URL = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";

    // 获取token
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    // 获取手机号
    private static final String PHONE_REQUEST_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    @Value("${zzyl.wechat.appId}")
    private String appId;

    @Value("${zzyl.wechat.appSecret}")
    private String secret;


    /**
     * 获取openid
     *
     * @param code 登录凭证
     * @return
     * @throws IOException
     */
    @Override
    public String getOpenid(String code) throws IOException {

        //封装参数
        Map<String,Object> requestUrlParam = getAppConfig();
        requestUrlParam.put("js_code",code);

        String result = HttpUtil.get(REQUEST_URL, requestUrlParam);

        JSONObject jsonObject = JSONUtil.parseObj(result);
        // 若code不正确,则获取不到openid,响应失败
        if (ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))) {
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }

        return jsonObject.getStr("openid");
    }

    /**
     * 封装公共参数
     * @return
     */
    private Map<String, Object> getAppConfig() {

        Map<String, Object> requestUrlParam = new HashMap<>();
        requestUrlParam.put("appid",appId);
        requestUrlParam.put("secret",secret);
        return requestUrlParam;
    }

    /**
     * 获取手机号
     *
     * @param code 手机号凭证
     * @return
     * @throws IOException
     */
    @Override
    public String getPhone(String code) throws IOException {

        //获取access_token
        String token = getToken();
        //拼接请求路径
        String url = PHONE_REQUEST_URL + token;

        Map<String,Object> param = new HashMap<>();
        param.put("code",code);

        String result = HttpUtil.post(url, JSONUtil.toJsonStr(param));
        JSONObject jsonObject = JSONUtil.parseObj(result);
        if (jsonObject.getInt("errcode") != 0) {
            //若code不正确,则获取不到phone,响应失败
            throw new RuntimeException(jsonObject.getStr("errmsg"));

        }
        return jsonObject.getJSONObject("phone_info").getStr("purePhoneNumber");

    }

    public String getToken(){
        Map<String, Object> requestUrlParam = getAppConfig();

        String result = HttpUtil.get(TOKEN_URL, requestUrlParam);
        //解析
        JSONObject jsonObject = JSONUtil.parseObj(result);
        //如果code不正确,则失败
        if(ObjectUtil.isNotEmpty(jsonObject.getInt("errcode"))){
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }
        return jsonObject.getStr("access_token");

    }
}

由于上述代码需要读取配置来获取微信小程序的appid和appSecret ,所以需要在application.yml添加对应配置,这里大家注意,这个要跟微信开发者平台设置的相同,就是我们刚才自己申请的测试小程序的appid和appSecret

项目名称:
  wechat:
    appId: xxxxxxxxxxxxxxx
    appSecret: xxxxxxxxxxxxxxxxxxxxxx

注意,使用自己申请的appid和secret,不然小程序无法登录  

        2.微信登录业务开发

定义:MemberService

public interface MemberService {


    /**
     * 小程序端登录
     * @param userLoginRequestDto
     * @return
     */
    LoginVo login(UserLoginRequestDto userLoginRequestDto);
}

   定义:MemberService实现类MemberServiceImpl

@Service
public class MemberServiceImpl implements MemberService {

    @Autowired
    private WechatService wechatService;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;


    static ArrayList DEFAULT_NICKNAME_PREFIX = Lists.newArrayList(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );

    /**
     * 小程序端登录
     *
     * @param userLoginRequestDto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto userLoginRequestDto){

        //1.调用微信api,根据code获取openId
        String openId = wechatService.getOpenid(userLoginRequestDto.getCode());

        //2.根据openId查询用户
        Member member = memberMapper.getByOpenId(openId);

        //3.如果用户为空,则新增
        if (ObjectUtil.isEmpty(member)) {
            member = Member.builder().openId(openId).build();
        }

        //4.调用微信api获取用户绑定的手机号
        String phone = wechatService.getPhone(userLoginRequestDto.getPhoneCode());

        //5.保存或修改用户
        saveOrUpdate(member, phone);

        //6.将用户id存入token,返回
        Map<String, Object> claims = new HashMap<>();
        claims.put(Constants.JWT_USERID, member.getId());
        claims.put(Constants.JWT_USERNAME, member.getName());

        String token = JwtUtil.createJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), jwtTokenManagerProperties.getTtl(), claims);

        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(member.getName());
        return loginVo;

    }

    /**
     * 保存或修改客户
     *
     * @param member
     * @param phone
     */
    private void saveOrUpdate(Member member, String phone) {

        //1.判断取到的手机号与数据库中保存的手机号是否一样
        if(ObjectUtil.notEqual(phone, member.getPhone())){
            //设置手机号
            member.setPhone(phone);
        }
        //2.判断id存在
        if (ObjectUtil.isNotEmpty(member.getId())) {
            memberMapper.update(member);
            return;
        }
        //3.保存新的用户
        //随机组装昵称,词组+手机号后四位
        String nickName = DEFAULT_NICKNAME_PREFIX.get((int) (Math.random() * DEFAULT_NICKNAME_PREFIX.size()))
                + StringUtils.substring(member.getPhone(), 7);

        member.setName(nickName);
        memberMapper.save(member);
    }

}

其中jwt相关的配置,我们已经在application.yml文件中定义,主要有两个属性,一个是签名,一个是过期时间

项目:
  framework:
    jwt:
      base64-encoded-secret-key: $2a$10$PVtHnkj86mJgf6li/yron.LRx/cQAlaiZkBJ9BeogCNTryXJRT1YC
      ttl: 3600000

   读取配置文件的配置类

@Setter
@Getter
@NoArgsConstructor
@ToString
@Configuration
@ConfigurationProperties(prefix = "zzyl.framework.jwt")
public class JwtTokenManagerProperties implements Serializable {

    /**
     *  签名密码
     */
    private String base64EncodedSecretKey;

    /**
     *  有效时间
     */
    private Integer ttl;
}

      Threadlocal的使用

定义拦截器:

        1.前置拦截器: (1) 获取token (2) 解析token  (3) 将UserId传入到Threadlocal中共享

        2.后置拦截器:   (1)清除Threadlocal的数据

@Component
@Slf4j
public class UserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //如果不是映射到方法就放行,比如跨域验证请求、静态资源等不需要身份校验的请求
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        //获取header的参数
        String token = request.getHeader(Constants.USER_TOKEN);
        log.info("开始解析 customer user token:{}",token);
        if(ObjectUtil.isEmpty(token)){
            //token失效
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }
        Map<String,Object> claims = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), token);
        if (ObjectUtil.isEmpty(claims)) {
            //token失效
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }
        //获取用户ID
        Long userId = MapUtil.get(claims, Constants.JWT_USERID, Long.class);
        if (ObjectUtil.isEmpty(userId)) {
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }
        //存入当前请求的线程中
        UserThreadLocal.set(userId);
        //以上检查都没问题,一定返回true,这个请求才能继续
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //响应结束,需清理ThreadLocal中的数据,防止内存泄漏
        UserThreadLocal.remove();
    }
}
public static final String USER_TOKEN ="authorization";

 使拦截器生效: 要再webMvcConfig中配置 

@Configuration
@ComponentScan("springfox.documentation.swagger.web")
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private UserInterceptor userInterceptor;

    //拦截的时候过滤掉swagger相关路径和登录相关接口
    private static final String[] EXCLUDE_PATH_PATTERNS = new String[]{"/swagger-ui.html",
            "/webjars/**",
            "/swagger-resources",
            "/v2/api-docs",
            // 登录接口
            "/customer/user/login"};

    /**
     * @Description 拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 小程序端接口鉴权拦截器
        registry.addInterceptor(userInterceptor)
            .excludePathPatterns(EXCLUDE_PATH_PATTERNS)
            .addPathPatterns("/customer/**");
    }

   
}

我们对UserThreadLocal进行了封装:


/**
 * subjectContent.java
 *  用户主体对象
 */
@Slf4j
public class UserThreadLocal {


    /***
     *  创建线程局部userVO变量
     */
    public static ThreadLocal<String> subjectThreadLocal = new ThreadLocal<String>() {
        @Override
        protected String initialValue() {
            return null;
        }
    };


    // 提供线程局部变量set方法
    public static void setSubject(String subject) {

        subjectThreadLocal.set(subject);
    }
    // 提供线程局部变量get方法
    public static String getSubject() {

        return subjectThreadLocal.get();
    }

    //清空当前线程,防止内存溢出
    public static void removeSubject() {

        subjectThreadLocal.remove();
    }
    private static final ThreadLocal<Long> LOCAL = new ThreadLocal<>();

    private UserThreadLocal() {

    }

    /**
     * 将authUserInfo放到ThreadLocal中
     *
     * @param authUserInfo {@link Long}
     */
    public static void set(Long authUserInfo) {
        LOCAL.set(authUserInfo);
    }

    /**
     * 从ThreadLocal中获取authUserInfo
     */
    public static Long get() {
        return LOCAL.get();
    }

    /**
     * 从当前线程中删除authUserInfo
     */
    public static void remove() {
        LOCAL.remove();
    }

    /**
     * 从当前线程中获取前端用户id
     * @return 用户id
     */
    public static Long getUserId() {
        return LOCAL.get();
    }

    /**
     * 从当前线程中获取前端后端id
     * @return 用户id
     */
    public static Long getMgtUserId() {
        String subject = subjectThreadLocal.get();
        if (ObjectUtil.isEmpty(subject)) {
            return null;
        }
        BaseVo baseVo = JSONObject.parseObject(subject, BaseVo.class);
        return baseVo.getId() ;
    }

}

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值