- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
-
创建socket处理类
@Component
@Slf4j
@ServerEndpoint("/websocket/{id}")
public class MyWebSocket implements SocketHandle {
private static Map<String ,Session> onlineClientMap = new ConcurrentHashMap<>();
@Override
@OnOpen
public void onOpen(Session session, @PathParam("id") String id) {
onlineClientMap.put(session.getId(),session);//添加当前连接的session
log.info("时间[{}]:与用户[{}]的连接成功,当前连接编号[{}]",
new Date().toLocaleString(),
id,
session.getId());
System.out.println("连接成功");
}
@Override
@OnClose
public void onClose(Session session,@PathParam("id") String id) {
onlineClientMap.remove(session.getId());//移除当前连接的session
log.info("时间[{}]:与用户[{}]的连接关闭,当前连接编号[{}]",
new Date().toLocaleString(),
id,
session.getId());
}
@Override
@OnError
public void onError(Throwable error, Session session,@PathParam("id") String id) {
error.printStackTrace();
}
@Override
@OnMessage
public void onMsg(Session session, String message, @PathParam("id") String id) throws IOException {
log.info("时间[{}]:来自连接编号为[{}]的消息:[{}]",
new Date().toLocaleString(),
session.getId(),
message);
}
public static void sendMessageById(String id,String message){
Session session = onlineClientMap.get(id);
session.getAsyncRemote().sendText(message);
}
}
根据大多数网上的介绍到这一步已经可以了,谁能想到这些该天杀的掉了一个配置😤,我自己到这一步就死活连不上。
3. 创建socket的连接点配置
@Configuration
public class WebSocketConfiguration {
/**
* 注入ServerEndpointExporter,
* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
- 还有一个问题就是如果加入了安全组件,security或者shiro需要排除websocket的接入链接
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AdminAuthenticationProcessingFilter adminAuthenticationProcessingFilter;
@Autowired
private IPiPermissionService iPiPermissionService;
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/login.html","/component/**","/admin/**","/file/**","/websocket/**");// 忽略websocket的链接
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.formLogin()
.loginPage("/login.html").permitAll();
httpSecurity.authorizeRequests()
.mvcMatchers("/login","/piMenu/getAllMenu","/websocket/**").permitAll()// 忽略websocket的链接
.anyRequest().authenticated();
httpSecurity.csrf().disable(); // CRSF禁用,因为不使用session 可以预防CRSF攻击
httpSecurity.cors().configurationSource(corsConfigurationSource());
// 允许iframe访问
httpSecurity.headers().frameOptions().disable();
httpSecurity.userDetailsService(userDetailsService);
httpSecurity.addFilterAt(adminAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class);
}
/**
* 跨域支持
* @return CorsConfigurationSource
*/
@Bean
protected CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.addExposedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}