@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableScheduling // 设定定时任务
@EnableCaching //开启缓存
以上功能的实现应该都不陌生吧
应用场景也十分长见
在启动类上开启事务之后,关于事务所需要的Bean就会注入容器,
使用事物的时候只需要在方法或者类上加
@Transactional
即可,加方法上方法中的代码,就会拥有开启事物的特性
但是如果在方法中的事务进行使用,在进行aop切面编程,事务回滚失效,需要把事务注解写在类上,这样每一个方法都拥有了事务
此时事务还有定向回滚,和传播级别
定向回滚:事务默认是运行时错误会回滚,编译器错误不会回滚
@Transactional(rollbackFor = Exception.class)
写为此模式的事务注解,效果是无论什么错误都可以回滚
传播级别:一个事务方法调用了另外一个事务方法 ,默认是并为一个事务,但是如果两个事务不支持存在融入关系,想在主事务中拥有自己独立的事务,就需要写为
@Transactional( propagation =Propagation.REQUIRES_NEW)
使用定时任务需要再启动类上声明,装载需要的Bean
@EnableScheduling // 设定定时任务
之后只需要新建一个类用来做方法定时任务实现,都是固定写法
@Component
@Slf4j
public class Tack {
@Scheduled(cron = "0 * * * * ?")
public void upStatus(){}
首先注入IOC,其次写表达式
开启缓存功能就是使用redis啦
@EnableCaching //开启缓存
启动类声明之后,在
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
日常使用就记住两种
当我们写着这种注解的时候脑子里要第一时间想到 ,想要写入redis中需要满足
第一是外层包裹文件 第二个是 唯一的key 第三个才是存入的数据 (存入的数据可以是任意数据)
然而我们不需要管数据怎么存入的,方法返回值会默认自动存入,
我们需要做的就是给这个主键根据返回值,找到唯一的key
@CachePut(value = "userCache",key = "#p0.id", unless = "#p0 != null ")
这个就是典型语法,如果为空就不会写入
还有一个小技巧,用参数表示key的时候可以写为#p0,#a0,#reslt都可以
@Cacheabe 和@CachePut的用法一样,开发中常用的是@Cacheabe ,命中缓存就不会进入方法!!!!
还有一个区别是@CachePut功能是持续存缓存,所有key是一句方法返回值找唯一键
@Cacheabe是根据方法形参判断的,所以建议key写为方法形参
@CacheEvict(value = "userCache" , key = "#p0")
这种就是出现数据更该的时候,根据单一的key,进行删除
@CacheEvict(value = "userCache", allEntries = true)
这种写法就跟厉害啦,可以删除文件包下的所有缓存,防止数据出错
某种意义体现出了上讲redis是mysql从库
长连接,就是三个注解,加一个方法
首先因为没有适合使用的注入注解,所以需要手动注入一个Bean来使用
/**
* WebSocket配置类,用于注册WebSocket的Bean
*/
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
接下来就可以接受请求了,连接之后,进行通信了
/**
* WebSocket服务
*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
//存放会话对象
private static 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
*/
@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();
}
}
}
}
主要的就是这几个方法上的注解使用之后,
注解就是别启动的标识,触发标识后就会运行方法
session.getBasicRemote().sendText(message);
这也是固定的写法,这句代码是,这里是支持多对一通信的,所以有很多的session
拿到某一个之后,调用方法,写入数据就完成通信啦