Skip to main content

安卓上线流程

一、上线流程

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@RestControllerWebSocket 的@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 提供了更高层次的抽象,可以通过 @MessageMappingStomp 协议实现 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 是有效的,不需要额外验证过期时间。