安卓上线流程
一、上线流程
1.调用登录接口
src/main/java/com/gbcom/wvp/controller/LoginController.java
@ApiOperation(value = "用户登录", notes = "POST用户登录返回JWT")
@PostMapping("/login")
public RS userLogin(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
Map<String, String> params = RequestResponseUtil.getRequestBodyMap(request);
String username = params.get("username");
//新增获取设备的deviceId 同时获取用户信息 判断是否锁定app 如果锁定了, 就不能登陆其它设备
String deviceId = params.get("deviceId");
GbUser gbUser = gbUserMapper.selectByUserName(username);
Integer isLockApp = gbUser.getIsLockApp();
if(isLockApp!=null) {
if (isLockApp == 1) {
//说明该用户已经锁定了app
if (!StringUtils.isEmpty(deviceId)) {
//从app 登陆的
String deviceInfo = gbUser.getDeviceInfo();
if(!StringUtils.isEmpty(deviceInfo)) {
JSONObject jsonObject = JSONObject.parseObject(deviceInfo);
if (jsonObject != null) {
String deviceIdSave = jsonObject.getString("deviceId");
if (deviceIdSave.equals(deviceId)) {
//唯一标识相同 放行给与登陆
map = gbUserService.login(request);
} else {
map.put("messageInfo", "该用户已经锁定了固定设备,不能登陆其它设备");
}
} else {
//处理异常数据的,登录
map = gbUserService.login(request);
}
}else{
//说明是空锁APP 不进行标识校验 //直接放行登录app
map = gbUserService.login(request);
}
} else {
//web登陆直接不给登
map.put("messageInfo", "该用户已经锁定了固定设备,不能登陆网页系统");
}
} else {
map = gbUserService.login(request);
}
}else{
map = gbUserService.login(request);
}
return new RS().ok().addResult("maps",map);
}
二、Q & A
(1.用户已经锁定了app是什么意思?
(2.websocket的入口在哪里,和http的入口有什么不一样的吗
@ServerEndpoint("/websocket/{token}/{loginType}")
是 Java WebSocket API 的注解,用于定义一个 WebSocket 服务端的入口路径。它与传统的 HTTP 请求(由 Spring MVC 的 @Controller
或 @RestController
处理)有本质区别。
以下是对 @ServerEndpoint
和其与传统 HTTP 请求的区别、工作机制的详细分析:
1. 什么是 @ServerEndpoint
?
- 定义 :
@ServerEndpoint
是 Java WebSocket API 中的一个注解,用于声明一个 WebSocket 端点(Endpoint)。它表示服务器会监听指定的 WebSocket 路径,并处理客户端的连接、消息、关闭等事件。 - 路径参数 :像
/websocket/{token}/{loginType}
这样的路径支持动态占位符{token}
和{loginType}
,类似于 Spring MVC 中的路径变量。可以通过@PathParam
注解获取这些参数。
2. WebSocket 和 HTTP 请求的区别
特性 | HTTP 请求 (Spring MVC) | WebSocket (@ServerEndpoint ) |
---|---|---|
协议 | 基于 HTTP 协议 | 基于 WebSocket 协议 |
通信方式 | 单向请求-响应模型 | 全双工通信(服务器和客户端可以随时互相发送消息) |
连接状态 | 无状态(每次请求独立) | 有状态(建立持久连接,直到关闭) |
适用场景 | 适合短时间、单次交互的任务 | 适合长时间、实时交互的任务(如聊天、推送通知) |
入口 | Spring MVC 的@Controller 或@RestController | WebSocket 的@ServerEndpoint |
3. @ServerEndpoint
的工作机制
(1) 定义 WebSocket 端点
通过 @ServerEndpoint
注解定义一个 WebSocket 服务端点:
@ServerEndpoint("/websocket/{token}/{loginType}")
public class WebSocketProcessorObserver {
// WebSocket 生命周期方法
}
- 路径
/websocket/{token}/{loginType}
表示客户端需要通过类似ws://<host>:<port>/websocket/<token>/<loginType>
的 URL 连接到这个 WebSocket 端点。 {token}
和{loginType}
是动态路径参数,可以通过@PathParam
获取。
(2) 生命周期方法
WebSocket 提供了几个关键的生命周期方法:
@OnOpen
:当客户端成功连接时触发。
@OnOpen
public void onOpen(Session session, @PathParam("token") String token) {
System.out.println("WebSocket opened with token: " + token);
}
@OnMessage
:当客户端发送消息时触发。
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Received message: " + message);
}
@OnClose
:当客户端断开连接时触发。
@OnClose
public void onClose(Session session) {
System.out.println("WebSocket closed");
}
@OnError
:当发生错误时触发。
@OnError
public void onError(Session session, Throwable error) {
System.err.println("WebSocket error: " + error.getMessage());
}
(3) 持久连接
WebSocket 的核心特点是 全双工通信 和 持久连接 :
- 一旦客户端与服务器建立 WebSocket 连接,双方可以随时发送消息,无需每次都重新建立连接(不像 HTTP 每次都需要三次握手)。
- 服务器也可以主动向客户端推送消息,而不需要客户端发起请求。
4. 为什么不是 Spring MVC 的 @Controller
?
- WebSocket 不是 HTTP 请求 :WebSocket 是一种独立的协议,虽然初始握手阶段使用 HTTP 协议,但握手完成后会升级为 WebSocket 协议(
Upgrade: websocket
)。 - Spring MVC 的局限性 :Spring MVC 主要用于处理传统的 HTTP 请求-响应模型,无法直接支持 WebSocket 的全双工通信需求。
- WebSocket 的注解 :Java 提供了专门的 WebSocket API(JSR 356),并使用
@ServerEndpoint
注解来定义 WebSocket 端点。
5. Spring 对 WebSocket 的支持
尽管 @ServerEndpoint
是 Java 标准 API,Spring 也提供了对 WebSocket 的支持,主要包括以下两种方式:
(1) 使用 @ServerEndpoint
可以直接使用标准的 @ServerEndpoint
注解,但需要注意以下几点:
-
依赖注入问题 :
@ServerEndpoint
不是 Spring 管理的 Bean,因此无法直接使用
@Autowired
注入 Spring Bean。
- 解决方案:使用
SpringContextHolder
或将 WebSocket 类注册为 Spring Bean(通过serverEndpointExporter
配置)。
- 解决方案:使用
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
(2) 使用 Spring 的 @MessageMapping
Spring 提供了更高层次的抽象,可以通过 @MessageMapping
和 Stomp
协议实现 WebSocket 功能:
- 优点 :与 Spring MVC 更加集成,支持依赖注入和消息代理。
- 缺点 :需要额外引入 STOMP 协议,增加了复杂性。
6. 示例对比
(1) HTTP 请求(Spring MVC)
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping("/hello")
public String hello(@RequestParam String name) {
return "Hello, " + name;
}
}
- 客户端通过
GET /api/hello?name=John
发起请求,服务器返回响应。
(2) WebSocket(@ServerEndpoint
)
@ServerEndpoint("/websocket/{name}")
public class MyWebSocket {
@OnOpen
public void onOpen(Session session, @PathParam("name") String name) {
System.out.println(name + " connected!");
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Received: " + message);
try {
session.getBasicRemote().sendText("Echo: " + message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 客户端通过
ws://<host>:<port>/websocket/John
建立连接,之后可以随时发送消息,服务器也会实时响应。
7. 总结
@ServerEndpoint
是 Java WebSocket API 的注解,用于定义 WebSocket 服务端点。- 它与 Spring MVC 的
@Controller
不同,适用于全双工、持久化的实时通信场景。 - 如果需要在 Spring 中使用 WebSocket,可以选择标准的
@ServerEndpoint
或 Spring 提供的@MessageMapping
和 STOMP 协议。 - 在实际开发中,选择合适的通信方式(HTTP 或 WebSocket)取决于业务需求。
(3.为什么socket请求中不需要验证token的过期时间
安卓客户端在登录接口中刚刚获取到新生成的 JWT Token,并紧接着调用 WebSocket 接口,那么在这种情况下,确实可以认为 Token 是有效的,不需要额外验证过期时间。