🚀 添加websocket和task,aop切面示例
This commit is contained in:
parent
7762d8f9fa
commit
d1e9baa15a
|
@ -0,0 +1,11 @@
|
|||
package cn.bunny.common.constant;
|
||||
|
||||
/**
|
||||
* 数据库中自动填充字段
|
||||
*/
|
||||
public class SQLAutoFillConstant {
|
||||
public static final String SET_CREATE_TIME = "setCreateTime";
|
||||
public static final String SET_UPDATE_TIME = "setUpdateTime";
|
||||
public static final String SET_CREATE_USER = "setCreateUser";
|
||||
public static final String SET_UPDATE_USER = "setUpdateUser";
|
||||
}
|
|
@ -9,8 +9,6 @@ import java.util.List;
|
|||
|
||||
@Component
|
||||
public class SnowflakeIdGenerator {
|
||||
|
||||
|
||||
// 数据中心id
|
||||
private final long datacenterId;
|
||||
// 数据中心id位数
|
||||
|
@ -47,8 +45,6 @@ public class SnowflakeIdGenerator {
|
|||
private long lastTimestamp = -1L;
|
||||
|
||||
public SnowflakeIdGenerator(SnowflakeProperties properties) {
|
||||
|
||||
|
||||
// 数据中心id
|
||||
this.datacenterId = properties.getDatacenterId();
|
||||
// 数据中心id位数
|
||||
|
@ -76,56 +72,37 @@ public class SnowflakeIdGenerator {
|
|||
// 单次批量生成id的最大数量
|
||||
this.maxBatchCount = properties.getMaxBatchCount();
|
||||
|
||||
|
||||
// 校验datacenterId和workerId是否超出最大值
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
|
||||
|
||||
throw new IllegalArgumentException(String.format("数据中心Id不能大于%d或小于0", maxDatacenterId));
|
||||
}
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
|
||||
|
||||
throw new IllegalArgumentException(String.format("机器Id不能大于%d或小于0", maxWorkerId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* id生成方法(单个)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
|
||||
|
||||
// 获取当前时间的毫秒数
|
||||
long timestamp = currentTime();
|
||||
|
||||
// 判断时钟是否回拨
|
||||
if (timestamp < lastTimestamp) {
|
||||
|
||||
|
||||
throw new RuntimeException(String.format("时钟回拨,回拨毫秒数:%d", lastTimestamp - timestamp));
|
||||
}
|
||||
|
||||
// 设置序列号
|
||||
if (lastTimestamp == timestamp) {
|
||||
|
||||
|
||||
// 设置序列号递增,如果当前毫秒内序列号已经达到最大值,则直到下一毫秒在重新从0开始计算序列号
|
||||
sequence = (sequence + 1) & maxSequence;
|
||||
if (sequence == 0) {
|
||||
|
||||
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
sequence = 0L;
|
||||
}
|
||||
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
// 计算id
|
||||
|
@ -138,22 +115,13 @@ public class SnowflakeIdGenerator {
|
|||
|
||||
/**
|
||||
* id生成方法(批量)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public synchronized List<Long> nextIds(int count) {
|
||||
|
||||
|
||||
if (count > maxBatchCount || count < 0) {
|
||||
|
||||
|
||||
throw new IllegalArgumentException(String.format("批量生成id的数量不能大于%d或小于0", maxBatchCount));
|
||||
}
|
||||
|
||||
List<Long> ids = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
|
||||
ids.add(nextId());
|
||||
}
|
||||
return ids;
|
||||
|
@ -164,13 +132,9 @@ public class SnowflakeIdGenerator {
|
|||
* 确保生成的时间戳总是向前移动的,即使在相同的毫秒内请求多个ID时也能保持唯一性。
|
||||
*/
|
||||
private long tilNextMillis(long lastTimestamp) {
|
||||
|
||||
|
||||
long timestamp = currentTime();
|
||||
// 循环等待直至获取到新的毫秒时间戳
|
||||
while (timestamp <= lastTimestamp) {
|
||||
|
||||
|
||||
timestamp = currentTime();
|
||||
}
|
||||
return timestamp;
|
||||
|
@ -180,9 +144,6 @@ public class SnowflakeIdGenerator {
|
|||
* 获取当前时间的毫秒数
|
||||
*/
|
||||
private long currentTime() {
|
||||
|
||||
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
|
@ -2,16 +2,20 @@ package cn.bunny.security.config;
|
|||
|
||||
import cn.bunny.security.custom.CustomPasswordEncoder;
|
||||
import cn.bunny.security.handelr.*;
|
||||
import cn.bunny.security.service.UserDetailsService;
|
||||
import cn.bunny.security.service.MyUserDetailsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
@ -25,7 +29,7 @@ public class WebSecurityConfig {
|
|||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
private MyUserDetailsService myUserDetailsService;
|
||||
@Autowired
|
||||
private CustomPasswordEncoder customPasswordEncoder;
|
||||
@Autowired
|
||||
|
@ -53,7 +57,7 @@ public class WebSecurityConfig {
|
|||
// 后登录的账号会使先登录的账号失效
|
||||
.sessionManagement(session -> {
|
||||
// 禁用session
|
||||
// session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
// 最大登录数为1
|
||||
session.maximumSessions(1)
|
||||
// 可以获取到所有登录的用户,以及登录状态,设置session状态
|
||||
|
@ -67,8 +71,6 @@ public class WebSecurityConfig {
|
|||
httpSecurity.csrf(AbstractHttpConfigurer::disable);
|
||||
// 跨域访问权限
|
||||
httpSecurity.cors(withDefaults());
|
||||
// 自定义用户认证和密码
|
||||
httpSecurity.userDetailsService(userDetailsService).passwordManagement(customPasswordEncoder);
|
||||
// 记住我
|
||||
httpSecurity.rememberMe(e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey"));
|
||||
// 自定义过滤器
|
||||
|
@ -79,6 +81,15 @@ public class WebSecurityConfig {
|
|||
return httpSecurity.build();
|
||||
}
|
||||
|
||||
// 自定义用户认证和密码
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
provider.setPasswordEncoder(customPasswordEncoder);
|
||||
provider.setUserDetailsService(myUserDetailsService);
|
||||
return new ProviderManager(provider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionRegistry sessionRegistry() {
|
||||
return new SessionRegistryImpl();
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package cn.bunny.security.custom;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CustomAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
|
||||
@Override
|
||||
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ import org.springframework.util.DigestUtils;
|
|||
*/
|
||||
@Configuration
|
||||
public class CustomPasswordEncoder implements PasswordEncoder, Customizer<PasswordManagementConfigurer<HttpSecurity>> {
|
||||
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
|
||||
|
|
|
@ -2,11 +2,8 @@ package cn.bunny.security.service;
|
|||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public interface UserDetailsService extends org.springframework.security.core.userdetails.UserDetailsService {
|
||||
|
||||
public interface MyUserDetailsService extends org.springframework.security.core.userdetails.UserDetailsService {
|
||||
/**
|
||||
* 根据用户名获取用户对象(获取不到直接抛异常)
|
||||
*/
|
|
@ -0,0 +1,8 @@
|
|||
package cn.bunny.enums;
|
||||
|
||||
/**
|
||||
* 数据库操作类型
|
||||
*/
|
||||
public enum OperationType {
|
||||
UPDATE, INSERT
|
||||
}
|
13
pom.xml
13
pom.xml
|
@ -34,6 +34,7 @@
|
|||
<jwt.version>0.9.1</jwt.version>
|
||||
<easyexcel.version>3.3.3</easyexcel.version>
|
||||
<jodatime.version>2.10.1</jodatime.version>
|
||||
<aspectj>1.9.21</aspectj>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
@ -91,6 +92,18 @@
|
|||
<artifactId>easyexcel</artifactId>
|
||||
<version>${easyexcel.version}</version>
|
||||
</dependency>
|
||||
<!-- aspectj -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
<!-- aspectj -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
|
|
|
@ -42,6 +42,20 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<!-- websocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<!-- asp 切面 -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
package cn.bunny.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = {"cn.bunny"})
|
||||
@MapperScan("cn.bunny.service.mapper")
|
||||
@EnableScheduling// 定时任务
|
||||
@EnableCaching// 开启缓存注解
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
public class ServiceApplication {
|
||||
public static void main(String[] args) {
|
||||
log.info("ServiceApplication启动...");
|
||||
SpringApplication.run(ServiceApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package cn.bunny.service.annotation;
|
||||
|
||||
import cn.bunny.enums.OperationType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AutoFill {
|
||||
// 数据库操作类型
|
||||
OperationType value();
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package cn.bunny.service.aspect;
|
||||
|
||||
import cn.bunny.common.constant.SQLAutoFillConstant;
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.enums.OperationType;
|
||||
import cn.bunny.service.annotation.AutoFill;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoFillAspect {
|
||||
@Pointcut("execution(* cn.bunny.service.*.*(..))")
|
||||
public void autoFillPointcut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 之前操作
|
||||
*
|
||||
* @param joinPoint 参数
|
||||
*/
|
||||
@Before("autoFillPointcut()")
|
||||
public void autoFill(JoinPoint joinPoint) {
|
||||
log.info("开始进行自动填充");
|
||||
// 获取当前被拦截数据库操作
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
|
||||
OperationType operationType = autoFill.value();
|
||||
// 获取实体对象
|
||||
Object[] args = joinPoint.getArgs();
|
||||
if (args == null || args.length == 0) {
|
||||
return;
|
||||
}
|
||||
Object entity = args[0];
|
||||
// 准备赋值数据
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
Long id = BaseContext.getUserId();
|
||||
// 根据当前不同的操作类型,为对应属性来反射赋值
|
||||
if (operationType == OperationType.INSERT) {
|
||||
try {
|
||||
Method setCreateTime = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
|
||||
Method setCreateUser = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_CREATE_USER, Long.class);
|
||||
Method setUpdateTime = entity.getClass().getMethod(SQLAutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
|
||||
Method setUpdateUser = entity.getClass().getMethod(SQLAutoFillConstant.SET_UPDATE_USER, Long.class);
|
||||
|
||||
setCreateTime.invoke(entity, localDateTime);
|
||||
setCreateUser.invoke(entity, id);
|
||||
setUpdateTime.invoke(entity, localDateTime);
|
||||
setUpdateUser.invoke(entity, id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (operationType == OperationType.UPDATE) {
|
||||
try {
|
||||
Method setUpdateTime = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
|
||||
Method setUpdateUser = entity.getClass().getDeclaredMethod(SQLAutoFillConstant.SET_UPDATE_USER, Long.class);
|
||||
|
||||
setUpdateTime.invoke(entity, localDateTime);
|
||||
setUpdateUser.invoke(entity, id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@ import cn.bunny.common.service.exception.BunnyException;
|
|||
import cn.bunny.entity.system.SysRole;
|
||||
import cn.bunny.entity.system.SysUser;
|
||||
import cn.bunny.security.custom.CustomUser;
|
||||
import cn.bunny.security.service.UserDetailsService;
|
||||
import cn.bunny.service.mapper.SysUserMapper;
|
||||
import cn.bunny.service.service.SysRoleService;
|
||||
import cn.bunny.service.service.SysUserService;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
@ -17,15 +17,15 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class MyUserDetailsService implements UserDetailsService {
|
||||
public class MyUserDetailsService implements cn.bunny.security.service.MyUserDetailsService {
|
||||
@Autowired
|
||||
private SysUserService sysUserService;
|
||||
private SysUserMapper sysUserMapper;
|
||||
@Autowired
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
SysUser sysUser = sysUserService.getByUsername(username);
|
||||
SysUser sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, username));
|
||||
if (sysUser == null) {
|
||||
throw new UsernameNotFoundException(MessageConstant.USER_DOES_NOT_EXIST);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class MyUserDetailsService implements UserDetailsService {
|
|||
}
|
||||
|
||||
List<SysRole> sysRoleList = sysRoleService.list();
|
||||
List<String> roleAuthoritieList = sysRoleList.stream().map(SysRole::getRoleName).toList();
|
||||
List<String> roleAuthoritieList = sysRoleList.stream().map(SysRole::getRoleCode).toList();
|
||||
return new CustomUser(sysUser, AuthorityUtils.createAuthorityList(roleAuthoritieList));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,9 @@ import cn.bunny.common.constant.MessageConstant;
|
|||
import cn.bunny.common.service.exception.BunnyException;
|
||||
import cn.bunny.common.utils.SnowflakeIdGenerator;
|
||||
import cn.bunny.entity.system.Login;
|
||||
import cn.bunny.entity.system.SysRole;
|
||||
import cn.bunny.entity.system.SysUser;
|
||||
import cn.bunny.entity.system.SysUserinfo;
|
||||
import cn.bunny.service.mapper.SysUserMapper;
|
||||
import cn.bunny.service.service.SysRoleService;
|
||||
import cn.bunny.service.service.SysUserService;
|
||||
import cn.bunny.vo.system.LoginVo;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
@ -17,13 +15,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户表 服务实现类
|
||||
|
@ -34,12 +31,12 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
@Service
|
||||
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
|
||||
@Autowired
|
||||
private SysRoleService sysRoleService;
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private SnowflakeIdGenerator snowflakeIdGenerator;
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
|
@ -73,13 +70,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
throw new BunnyException(MessageConstant.PASSWORD_ERROR);
|
||||
}
|
||||
|
||||
List<String> roleList = sysRoleService.list().stream().map(SysRole::getRoleCode).collect(Collectors.toList());
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("sysUser", sysUser);
|
||||
map.put("roleList", roleList);
|
||||
|
||||
redisTemplate.opsForValue().set(String.valueOf(snowId), map);
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(vo.getUsername(), vo.getPassword());
|
||||
Authentication authenticate = authenticationManager.authenticate(authentication);
|
||||
redisTemplate.opsForValue().set(String.valueOf(snowId), authenticate);
|
||||
// 添加token
|
||||
return Login.builder().token(String.valueOf(snowId)).build();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package cn.bunny.service.task;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
@Slf4j
|
||||
public class TemplateTask {
|
||||
@Scheduled(cron = "0/1 * * * * ?")
|
||||
public void templateTask() {
|
||||
log.warn("TemplateTask...");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package cn.bunny.service.websocket;
|
||||
|
||||
import jakarta.websocket.OnClose;
|
||||
import jakarta.websocket.OnMessage;
|
||||
import jakarta.websocket.OnOpen;
|
||||
import jakarta.websocket.Session;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WebSocket服务
|
||||
*/
|
||||
@Component
|
||||
@ServerEndpoint("/ws/{sid}")
|
||||
public class WebSocketServer {
|
||||
|
||||
// 存放会话对象
|
||||
private static final Map<String, Session> sessionMap = new HashMap();
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("sid") String sid) {
|
||||
System.out.println("客户端:" + sid + "建立连接");
|
||||
sessionMap.put(sid, session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, @PathParam("sid") String sid) {
|
||||
System.out.println("收到来自客户端:" + sid + "的信息:" + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*
|
||||
* @param sid 请求id
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose(@PathParam("sid") String sid) {
|
||||
System.out.println("连接断开:" + sid);
|
||||
sessionMap.remove(sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public void sendToAllClient(String message) {
|
||||
Collection<Session> sessions = sessionMap.values();
|
||||
for (Session session : sessions) {
|
||||
try {
|
||||
// 服务器向客户端发送消息
|
||||
session.getBasicRemote().sendText(message);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue