> 文章列表 > 亿级高并发电商项目-- 实战篇 --万达商城项目 十二(编写用户服务、发送短信功能、发送注册验证码功能、手机号验证码登录功能、单点登录等模块)

亿级高并发电商项目-- 实战篇 --万达商城项目 十二(编写用户服务、发送短信功能、发送注册验证码功能、手机号验证码登录功能、单点登录等模块)

亿级高并发电商项目-- 实战篇 --万达商城项目 十二(编写用户服务、发送短信功能、发送注册验证码功能、手机号验证码登录功能、单点登录等模块)

 

 

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者
📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人 

专栏:高并发项目 

编写用户服务接口

在通用模块编写用户服务接口:

/**
* 商城用户服务
*/
public interface ShoppingUserService {// 注册时向redis保存手机号+验证码void saveRegisterCheckCode(String phone,String checkCode);// 注册时验证手机号void registerCheckCode(String phone,String checkCode);// 用户注册void register(ShoppingUser shoppingUser);// 用户名密码登录String loginPassword(String username,String password);// 登录时向redis保存手机号+验证码void saveLoginCheckCode(String phone,String checkCode);// 手机号验证码登录String loginCheckCode(String phone, String checkCode);   // 获取登录用户名String getName(String token);// 获取登录用户ShoppingUser getLoginUser(String token);
}

创建网站用户服务模块

1、创建名为 shopping_user_service 的SpringBoot工程,添加相关依赖。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- MyBatisPlus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.0</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.itbaizhan</groupId><artifactId>shopping_common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- dubbo --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version></dependency><!-- 操作zookeeper --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
</dependencies>

 2、设置该工程的父工程为 shopping 。

<parent><groupId>com.ittxc</groupId><artifactId>shopping</artifactId><version>1.0-SNAPSHOT</version>
</parent>

3、给 shopping 工程设置子模块

<!-- 子模块 -->
<modules><!-- 用户服务 --><module>shopping_user_service</module>
</modules>

4、编写配置文件 application.yml

# 端口号
server:port: 9006# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
#配置mybatis-plus
mybatis-plus:global-config:db-config:# 表名前缀table-prefix: bz_# 主键生成策略为自增id-type: autoconfiguration:# 关闭列名自动驼峰命名规则映射map-underscore-to-camel-case: falselog-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
spring:# 数据源datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql:///baizhanshopping?serverTimezone=UTCusername: rootpassword01: 123456# redisredis:host: 192.168.100.131port: 6379timeout: 30000jedis:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0
dubbo:application:name: shopping_user_service # 项目名registry:address: zookeeper://192.168.100.131 #注册中心地址port: 2181       # 注册中心的端口timeout: 10000 # 注册到zk上超时时间,msprotocol:name: dubbo # dubbo使用的协议port: -1 # dubbo自动分配端口scan:base-packages: com.ittxc.shopping_user_service.service # 包扫描

创建网站用户Api模块

1、创建名为 shopping_user_customer_api 的SpringBoot工程,添加相关依赖。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- dubbo --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version></dependency><!-- 操作zookeeper --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><dependency><groupId>com.itbaizhan</groupId><artifactId>shopping_common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

 2、设置该工程的父工程为 shopping 。

<parent><groupId>com.ittxc</groupId><artifactId>shopping</artifactId><version>1.0-SNAPSHOT</version>
</parent>

3、给 shopping 工程设置子模块

<!-- 子模块 -->
<modules><!-- 用户业务的api --><module>shopping_user_customer_api</module>
</modules>

4、编写配置文件 application.yml

# 端口号
server:port: 8003
# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
dubbo:application:name: shopping_user_customer_api # 项目名registry:address: zookeeper://192.168.100.131 #注册中心地址port: 2181       # 注册中心的端口timeout: 10000 # 注册到zk上超时时间,msprotocol:name: dubbo # dubbo使用的协议port: -1 # dubbo自动分配端口

5、启动类忽略数据源自动配置

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ShoppingUserCustomerApiApplication {public static void main(String[] args){SpringApplication.run(ShoppingUserCustomerApiApplication.class, args);}
}

用户注册的步骤

在用户注册时,我们要保证用户输入的手机号就是他本人使用的手 机号,方便后期的广告推送、安全认证等。所以在注册前,会向用 户手机发送一个四位随机数验证码,如果用户能获取到该验证码, 证明该手机就是用户本人使用。用户注册的步骤如下:

申请阿里短信服务 

1、访问阿里云 https://www.aliyun.com/,完成登录

2、进入短信服务 

3、开通短信服务 

4、购买短信条数 

 5、购买完成进入阿里云短信控制台https://dysms.console.aliyun.c om/overview

6、绑定测试手机号 

 7、点击调用API发送短信,可以看到发送短信的JAVA代码。

8、申请阿里云秘钥,该秘钥在发送短信时会作为参数传入 

编写发送短信功能 

1、创建名为 shopping_message_service 的SpringBoot工程,添加相关依赖。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>
<dependency><groupId>com.ittxc</groupId><artifactId>shopping_common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- 阿里短信平台 --><dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.9</version></dependency><!-- dubbo --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version></dependency><!-- 操作zookeeper --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

2、设置该工程的父工程为 shopping 。

<parent><groupId>com.ittxc</groupId><artifactId>shopping</artifactId><version>1.0-SNAPSHOT</version>
</parent>

3、给 shopping 工程设置子模块

<!-- 子模块 -->
<modules><!-- 短信服务 --><module>shopping_message_service</module>
</modules>

4、编写配置文件 application.yml

# 端口号
server:port: 9007
# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread]
%cyan(%-50logger{50}):%msg%n'
dubbo:application:name: shopping_message_service # 项目名registry:address: zookeeper://192.168.100.131 #注册中心地址port: 2181       # 注册中心的端口timeout: 10000 # 注册到zk上超时时间,msprotocol:name: dubbo # dubbo使用的协议port: -1 # dubbo自动分配端口scan:base-packages: com.ittxc.shopping_message_service.service # 包扫描
message:accessKeyId: LTAI5tBUnRMTgKmRR92yxrFfaccessKeySecret: RN7umfy3mMA2xlGa8rP0IzwQdTc6Pb

5、启动类忽略数据源自动配置

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ShoppingMessageServiceApplication {public static void main(String[] args){SpringApplication.run(ShoppingMessageServiceApplication.class, args);}
}

6、在通用模块编写发送短信服务接口

/**
* 短信服务
*/
public interface MessageService {/*** 发送短信* @param phoneNumber 手机号* @param code 验证码* @return 返回结果*/BaseResult sendMessage(String phoneNumber,String code);
}

7、在短信服务模块编写发送短信实现类

@DubboService
public class MessageServiceImpl implements
MessageService {@Value("${message.accessKeyId}")private String accessKeyId;@Value("${message.accessKeySecret}")private String accessKeySecret;/*** 使用AK&SK初始化账号Client* @param accessKeyId* @param accessKeySecret* @return Client* @throws Exception*/@SneakyThrowsprivate Client createClient(String accessKeyId, String accessKeySecret) {Config config = new Config().setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret);// 访问的域名config.endpoint = "dysmsapi.aliyuncs.com";return new Client(config);}@SneakyThrows@Overridepublic BaseResult sendMessage(String phoneNumber,String code) {Client client = createClient(accessKeyId,accessKeySecret);SendSmsRequest sendSmsRequest = new SendSmsRequest().setSignName("阿里云短信测试").setTemplateCode("SMS_154950909").setPhoneNumbers(phoneNumber).setTemplateParam("{\\"code\\":\\""+code+"\\"}");RuntimeOptions runtime = new RuntimeOptions();// 复制代码运行请自行打印API的返回值SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest,
runtime);SendSmsResponseBody body = sendSmsResponse.getBody();if ("OK".equals(body.getCode())){return new BaseResult(200,body.getCode(),body.getMessage());}else{return new BaseResult(500,body.getCode(),body.getMessage());}}
}

8、测试该方法

编写发送注册验证码功能

1、在通用模块编写生成随机数的工具类

public class RandomUtil {/*** 生成验证码* @param digit 位数* @return*/public static String buildCheckCode(int digit){String str = "0123456789";StringBuilder sb = new StringBuilder();Random random = new Random();for (int i = 0; i < digit; i++) {char ch = str.charAt(random.nextInt(str.length()));sb.append(ch);}return sb.toString();}
}

2、在用户服务模块编写用户服务接口实现类

@DubboService
public class ShoppingUserServiceImpl implements ShoppingUserService {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate ShoppingUserMapper shoppingUserMapper;@Overridepublic void saveRegisterCheckCode(String phone, String checkCode) {ValueOperations valueOperations = redisTemplate.opsForValue();// redis键为手机号,值为验证码,过期时间5分钟valueOperations.set("registerCode:" + phone, checkCode, 300, TimeUnit.SECONDS);}
}

3、在用户API模块编写控制器

/**
* 商城用户
*/
@RestController
@RequestMapping("/shoppingUser")
public class ShoppingUserController {@DubboReferenceprivate ShoppingUserService shoppingUserService;/*** 发送注册短信* @param phone 注册手机号* @return 操作结果*/@GetMapping("/sendMessage")public BaseResult sendMessage(String phone){// 1.生成随机四位数String checkCode = RandomUtil.buildCheckCode(4);// 2.发送短信BaseResult result = messageService.sendMessage(phone,checkCode);// 3.发送成功,将验证码保存到redis中,发送失败,返回发送结果if (200 == result.getCode()) {shoppingUserService.saveRegisterCheckCode(phone, checkCode);return BaseResult.ok();} else {return result;}}
}

4、测试控制器

编写验证注册验证码功能

1、在用户服务模块编写用户服务接口实现类

@Override
public void registerCheckCode(String phone, String checkCode) {// 验证验证码ValueOperations valueOperations = redisTemplate.opsForValue();Object checkCodeRedis = valueOperations.get("registerCode:" + phone);if (!checkCode.equals(checkCodeRedis)){throw new BusException(CodeEnum.REGISTER_CODE_ERROR);}
}

2、在用户API模块编写控制器

/*** 验证用户注册验证码* @param phone 手机号* @param checkCode 验证码* @return 200验证成功,605验证码不正确*/
@GetMapping("/registerCheckCode")
public BaseResult register(String phone,String checkCode){shoppingUserService.registerCheckCode(phone,checkCode);return BaseResult.ok();
}

3、测试控制器

编写用户注册功能

1、在通用模块编写MD5加密工具类,用于给用户密码进行加密和验证

public class Md5Util {public final static String md5key = "BAIZHAN"; // 秘钥/*** 加密* @param text 明文* @return 密文*/public static String encode(String text){return DigestUtils.md5Hex(text + md5key);}/*** 验证** @param text 明文* @param cipher 密文* @return true/false*/public static boolean verify(String text, String cipher){// 将明文转为密文进行比对String md5Text = encode(text);if (md5Text.equalsIgnoreCase(cipher)) {return true;}return false;}
}

2、在用户服务模块编写用户服务接口实现类

@Override
public void register(ShoppingUser
shoppingUser) {// 1.验证手机号是否存在String phone = shoppingUser.getPhone();QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("phone", phone);List<ShoppingUser> shoppingUsers = shoppingUserMapper.selectList(queryWrapper);if (shoppingUsers != null && shoppingUsers.size() > 0) {throw new BusException(CodeEnum.REGISTER_REPEAT_PHONE_ERROR);}// 2.验证用户名是否存在String username = shoppingUser.getUsername();QueryWrapper<ShoppingUser> queryWrapper1 = new QueryWrapper();queryWrapper1.eq("username",username);List<ShoppingUser> shoppingUsers1 = shoppingUserMapper.selectList(queryWrapper1);if (shoppingUsers1 != null && shoppingUsers1.size() > 0) {throw new BusException(CodeEnum.REGISTER_REPEAT_NAME_ERROR);}// 3.新增用户shoppingUser.setStatus("Y");shoppingUser.setPassword(Md5Util.encode(shoppingUser.getPassword()));shoppingUserMapper.insert(shoppingUser);
}

3、在用户API模块编写控制器

/*** 用户注册* @param shoppingUser 用户信息* @return 注册结果*/
@PostMapping("/register")
public BaseResult register(@RequestBody ShoppingUser shoppingUser){shoppingUserService.register(shoppingUser);return BaseResult.ok();
}

4、测试控制器

编写用户名密码登录功能

1、在用户服务模块编写用户服务接口实现类

@Override
public String loginPassword(String username, String password) {QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("username", username);ShoppingUser shoppingUser = shoppingUserMapper.selectOne(queryWrapper);// 验证用户名if (shoppingUser == null) {throw new BusException(CodeEnum.LOGIN_NAME_PASSWORD_ERROR);}// 验证密码boolean verify = Md5Util.verify(password,shoppingUser.getPassword());if (!verify) {throw new BusException(CodeEnum.LOGIN_NAME_PASSWORD_ERROR);}// 返回用户名return username;
}

2、在用户API模块编写控制器

/*** 用户名密码登录* @param shoppingUser 用户对象* @return 登录结果*/
@PostMapping("/loginPassword")
public BaseResult loginPassword(@RequestBody ShoppingUser shoppingUser){shoppingUserService.loginPassword(shoppingUser.getUsername(),shoppingUser.getPassword());return BaseResult.ok();
}

3、测试控制器

编写手机号验证码登录功能

手机号验证码登录的流程为:用户先输入手机号,向手机号发送随 机验证码,并将验证码保存到redis中。用户收到短信后将验证码输入,如果验证码和redis中的验证码匹配成功,证明登录者就是使用 该手机的用户,登录成功。

向用户发送登录验证码 

1、在用户服务模块编写用户服务接口实现类

// 保存登录验证码到redis
@Override
public void saveLoginCheckCode(String phone, String checkCode) {ValueOperations valueOperations = redisTemplate.opsForValue();// redis键为手机号,值为验证码,过期时间5分钟valueOperations.set("loginCode:" + phone, checkCode, 300, TimeUnit.SECONDS);
}

2、在用户API模块编写控制器

/*** 发送登录短信验证码** @param phone 手机号* @return 操作结果*/
@GetMapping("/sendLoginCheckCode")
public BaseResult sendLoginCheckCode(String phone) {// 1.生成随机四位数String checkCode = RandomUtil.buildCheckCode(4);// 2.发送短信BaseResult result = messageService.sendMessage(phone,checkCode);// 3.发送成功,将验证码保存到redis中,发送失败,返回发送结果if (200 == result.getCode()) {shoppingUserService.saveLoginCheckCode(phone, checkCode);return BaseResult.ok();} else {return result;}
}

3、测试控制器

验证登录验证码

1、在用户服务模块编写用户服务接口实现类

// 验证登录验证码
@Override
public String loginCheckCode(String phone, String checkCode) {ValueOperations valueOperations = redisTemplate.opsForValue();Object checkCodeRedis = valueOperations.get("loginCode:" + phone);if (!checkCode.equals(checkCodeRedis)){throw new BusException(CodeEnum.LOGIN_CODE_ERROR);}// 登录成功,查询用户QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("phone", phone);ShoppingUser shoppingUser = shoppingUserMapper.selectOne(queryWrapper);// 返回用户名return shoppingUser.getUsername();
}

2、在用户API模块编写控制器

/*** 手机号验证码登录* @param phone 手机号* @param checkCode 验证码* @return 登录结果*/
@PostMapping("/loginCheckCode")
public BaseResult loginCheckCode(String phone, String checkCode){shoppingUserService.loginCheckCode(phone,checkCode);return BaseResult.ok();
}

3、测试控制器

单点登录的概念

目前登录成功后我们并没有保存用户信息,也没有在访问接口前验 证用户信息。如果使用传统的session保存用户信息,使用filter验证 用户是否登录。存在一个问题:session保存在服务器中,而我们的 系统存在诸多子系统,这些子系统是分别部署在不同的服务器中,互相无法访问(登录后的session保存在用户模块,搜索模块无法访问用户模块的session,无法验证用户是否登录)。此时我们需要使用单点登录技术解决这一问题。

单点登录 

单点登录(Single Sign On)简称为 SSO。即在多个应用系统中, 用户只需要登录一次就可以访问所有相互信任的应用系统。JWT是一种常用的单点登录解决方案。

JWT 

JWT是Json Web Token的简称,是一种令牌生成算法。使用JWT能 够保证Token的安全性,且能够进行Token时效性的检验。 使用JWT时,登录成功后将用户信息生成一串令牌字符串。将该字 符串返回给客户端,客户端每次请求时都在请求头携带该令牌字符串。在其他模块验证令牌,通过则证明用户处于登录状态,并拿到 解析后的用户信息,未通过证明用户处于未登录状态。

编写单点登录功能 

1、在通用模块引入JWT依赖

<!-- JWT -->
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version>
</dependency>

2、在通用模块编写JWT工具类

public class JWTUtil {//token过期时间,一天private static final Long EXPIRE_DATE = 1000*60*60*24L;// 秘钥private static final String SECRET = "txc";// 签发者private static final String ISSUER = "TXC";/*** 签名生成* @param shoppingUser* @return*/public static String sign(ShoppingUser shoppingUser){String token = JWT.create().withIssuer(ISSUER) // 签发者.withIssuedAt(new Date())// 签发时间.withExpiresAt(new Date(new Date().getTime() + EXPIRE_DATE))// 过期时间.withSubject(shoppingUser.getUsername())// 保存用户名.sign(Algorithm.HMAC256(SECRET)); // 秘钥return token;}/*** 签名解析* @param token 签名字符串* @return 解析得出的用户名*/public static String verify(String token){try {String username = JWT.require(Algorithm.HMAC256(SECRET)).withIssuer(ISSUER).build().verify(token).getSubject();return username;} catch (Exception e){throw new BusException(CodeEnum.VERIFY_TOKEN_ERROR);}}
}

3、登录后生成令牌

@Override
public String loginPassword(String
username, String password) {// 1.验证用户名QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("username",username);ShoppingUser shoppingUser = shoppingUserMapper.selectOne(queryWrapper);if (shoppingUser == null){throw new BusException(CodeEnum.LOGIN_NAME_PASSWORD_ERROR);}// 2.验证密码boolean verify = Md5Util.verify(password, shoppingUser.getPassword());if (!verify){throw new BusException(CodeEnum.LOGIN_NAME_PASSWORD_ERROR);}// 3.生成JWT令牌,返回令牌String sign = JWTUtil.sign(shoppingUser);return sign;
}
@Override
public String loginCheckCode(String phone,String checkCode) {ValueOperations valueOperations = redisTemplate.opsForValue();Object checkCodeRedis = valueOperations.get("loginCode:" + phone);if (!checkCode.equals(checkCodeRedis)){throw new BusException(CodeEnum.LOGIN_CODE_ERROR);}// 登录成功,查找用户,返回用户名QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("phone",phone);ShoppingUser shoppingUser = shoppingUserMapper.selectOne(queryWrapper);// 生成JWT令牌,返回令牌String sign = JWTUtil.sign(shoppingUser);return sign;
}

4、将令牌返回给客户端

/*** 用户名密码登录* @param shoppingUser 用户对象* @return 登录结果*/
@PostMapping("/loginPassword")
public BaseResult loginPassword(@RequestBody ShoppingUser shoppingUser){String sign = shoppingUserService.loginPassword(shoppingUser.getUsername(),shoppingUser.getPassword());return BaseResult.ok(sign);
}
/**
* 手机号验证码登录
* @param phone 手机号
* @param checkCode 验证码
* @return 登录结果
*/
@PostMapping("/loginCheckCode")
public BaseResult loginCheckCode(Stringphone,String checkCode){String sign = shoppingUserService.loginCheckCode(phone,checkCode);return BaseResult.ok(sign);
}

编写拦截器验证令牌

在通用模块编写JWT拦截器

// 拦截器,验证令牌
public class JWTInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Objecthandler) throws Exception {// 获取请求头中的tokenString token = request.getHeader("token");// 验证tokenJWTUtil.verify(token);return true;}
}

注:请求时要在请求头添加token=令牌数据

配置拦截的接口 

在不同API模块都要配置拦截的接口

1、配置用户API模块拦截的接口

// 拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/**") //拦截的接口.excludePathPatterns("/user/shoppingUser/sendMessage","/user/shoppingUser/registerCheckCode","/user/shoppingUser/register","/user/shoppingUser/loginPassword","/user/shoppingUser/sendLoginCheckCode","/user/shoppingUser/loginCheckCode"); //放行的接口}
}

2、配置搜索API模块拦截的接口

// 拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/**") //拦截的接口.excludePathPatterns("/user/goodsSearch/autoSuggest"); //放行的接口}
}

3、广告用户API模块不拦截

编写获取用户名功能

1、在用户服务模块编写用户服务接口实现类

@Override
public String getName(String token) {String name = JWTUtil.verify(token);return name;
}
@Override
public ShoppingUser getLoginUser(String token) {String username = JWTUtil.verify(token);QueryWrapper<ShoppingUser> queryWrapper = new QueryWrapper();queryWrapper.eq("username", username);ShoppingUser shoppingUser = shoppingUserMapper.selectOne(queryWrapper);return shoppingUser;
}

2、在用户API模块编写控制器

/*** 获取登录的用户名* @param token 令牌* @return 用户名*/
@GetMapping("/getName")
public BaseResult<String> getName(@RequestHeader("token") String token){String name = shoppingUserService.getName(token);return BaseResult.ok(name);
}

3、使用Postman测试控制器

编写退出登录功能

后端无需编写退出登录功能,前端删除令牌即可退出登录。