Spring 是一个开源的 Java 开发框架,它提供了一系列功能强大的特性,用于简化企业级应用开发。Spring 的核心特性包括:
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>5.3.20version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.3.20version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>5.3.20version>
dependency>
dependencies>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example"/>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/dbname"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
bean>
beans>
@Configuration
@ComponentScan("com.example")
public class AppConfig {
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dbname");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
@After("execution(* com.example.service.*.*(..))")
public void afterMethod(JoinPoint joinPoint) {
System.out.println("After method: " + joinPoint.getSignature().getName());
}
}
@Service
@Transactional
public class UserService {
@Transactional(rollbackFor = Exception.class)
public void transferMoney(String from, String to, BigDecimal amount) {
// 转账逻辑
}
}
@Controller
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
return ResponseEntity.ok(userService.save(user));
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new Object[]{id},
(rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
return user;
}
);
}
}
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User findById(@Param("id") Long id);
@Insert("INSERT INTO users(name) VALUES(#{name})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(User user);
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
getAuthorities(user)
);
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/dbname
username: root
password: password
jpa:
hibernate:
ddl-auto: update
show-sql: true
server:
port: 8080
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testCreateUser() {
User user = new User();
user.setName("Test User");
User saved = userService.save(user);
assertNotNull(saved.getId());
assertEquals("Test User", saved.getName());
}
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void testGetUser() {
ResponseEntity<User> response = restTemplate.getForEntity(
"/api/users/1",
User.class
);
assertEquals(HttpStatus.OK, response.getStatusCode());
}
}
// 服务提供者
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
// 服务消费者
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
@Configuration
public class LoadBalancerConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
public class UserService {
@Autowired
private RestTemplate restTemplate;
public User getUser(Long id) {
return restTemplate.getForObject(
"http://user-service/api/users/{id}",
User.class,
id
);
}
}
@Service
public class UserService {
@HystrixCommand(fallbackMethod = "getUserFallback")
public User getUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
public User getUserFallback(Long id) {
return new User(id, "Fallback User");
}
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true)
private String email;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Order> orders;
// getters and setters
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByNameContaining(String name);
Optional<User> findByEmail(String email);
@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findUsersOlderThan(@Param("age") int age);
}
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
return userRepository.save(user);
}
public List<User> findUsersByName(String name) {
return userRepository.findByNameContaining(name);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new ConcurrentMapCache("users"),
new ConcurrentMapCache("products")
));
return cacheManager;
}
}
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
@CacheEvict(value = "users", key = "#user.id")
public User updateUser(User user) {
return userRepository.save(user);
}
@CachePut(value = "users", key = "#user.id")
public User createUser(User user) {
return userRepository.save(user);
}
}
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public Flux<User> getAllUsers() {
return userService.findAll();
}
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public Mono<User> createUser(@RequestBody User user) {
return userService.save(user);
}
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Flux<User> findAll() {
return userRepository.findAll();
}
public Mono<User> findById(Long id) {
return userRepository.findById(id);
}
public Mono<User> save(User user) {
return userRepository.save(user);
}
}
@Configuration
public class BatchConfig {
@Bean
public Job importUserJob(JobBuilderFactory jobs, StepBuilderFactory steps) {
return jobs.get("importUserJob")
.start(steps.get("step1")
.<User, User>chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build())
.build();
}
@Bean
public ItemReader<User> reader() {
return new FlatFileItemReaderBuilder<User>()
.name("userReader")
.delimited()
.names(new String[]{"id", "name", "email"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<User>() {{
setTargetType(User.class);
}})
.build();
}
}
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Scheduled(cron = "0 0 1 * * ?")
public void scheduledTask() {
// 执行定时任务
}
@Scheduled(fixedRate = 5000)
public void fixedRateTask() {
// 每5秒执行一次
}
}
# application.yml
spring:
data:
mongodb:
host: localhost
port: 27017
database: mydb
username: user
password: password
authentication-database: admin
@Document(collection = "users")
public class User {
@Id
private String id;
@Field("user_name")
private String name;
@Indexed(unique = true)
private String email;
@DBRef
private List<Order> orders;
@CreatedDate
private Date createdAt;
@LastModifiedDate
private Date updatedAt;
// getters and setters
}
@Repository
public interface UserRepository extends MongoRepository<User, String> {
// 基本CRUD方法由MongoRepository提供
// 自定义查询方法
List<User> findByNameContaining(String name);
Optional<User> findByEmail(String email);
@Query("{ 'age': { $gt: ?0 } }")
List<User> findUsersOlderThan(int age);
// 使用@Aggregation注解进行聚合查询
@Aggregation(pipeline = {
"{ $match: { age: { $gt: ?0 } } }",
"{ $group: { _id: '$city', count: { $sum: 1 } } }"
})
List<CityCount> countUsersByCity(int age);
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
return userRepository.save(user);
}
public List<User> findUsersByName(String name) {
return userRepository.findByNameContaining(name);
}
public void deleteUser(String id) {
userRepository.deleteById(id);
}
// 使用MongoTemplate进行复杂查询
@Autowired
private MongoTemplate mongoTemplate;
public List<User> findUsersByComplexQuery() {
Criteria criteria = new Criteria();
criteria.and("age").gt(18)
.and("city").in("Beijing", "Shanghai");
Query query = new Query(criteria);
query.with(Sort.by(Sort.Direction.DESC, "createdAt"));
return mongoTemplate.find(query, User.class);
}
}
@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
@Override
protected void configureClientMongoSettings(MongoClientSettings.Builder builder) {
builder.applyConnectionString(new ConnectionString("mongodb://localhost:27017/mydb"));
}
@Override
public Collection<String> getMappingBasePackages() {
return Collections.singleton("com.example");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoClient(), getDatabaseName());
}
}
@Service
@Transactional
public class OrderService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderRepository orderRepository;
public void createOrder(String userId, Order order) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User not found"));
order.setUserId(userId);
orderRepository.save(order);
user.getOrders().add(order);
userRepository.save(user);
}
}
@Component
public class UserChangeStreamListener {
@Autowired
private MongoTemplate mongoTemplate;
@PostConstruct
public void startChangeStream() {
ChangeStreamOptions options = ChangeStreamOptions.builder()
.returnFullUpdateDocument(true)
.build();
mongoTemplate.changeStream(
User.class,
options,
event -> {
System.out.println("Change detected: " + event.getOperationType());
System.out.println("Document: " + event.getBody());
}
).subscribe();
}
}
@Document(collection = "locations")
public class Location {
@Id
private String id;
private String name;
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private Point location;
// getters and setters
}
@Repository
public interface LocationRepository extends MongoRepository<Location, String> {
List<Location> findByLocationNear(Point location, Distance distance);
@Query("{ location: { $near: { $geometry: ?0, $maxDistance: ?1 } } }")
List<Location> findNearbyLocations(Point location, double maxDistance);
}
@Service
public class UserAnalyticsService {
@Autowired
private MongoTemplate mongoTemplate;
public List<UserAnalytics> getUserAnalytics() {
Aggregation aggregation = Aggregation.newAggregation(
// 匹配条件
Aggregation.match(Criteria.where("age").gt(18)),
// 分组统计
Aggregation.group("city")
.count().as("userCount")
.avg("age").as("averageAge")
.sum("orders").as("totalOrders"),
// 排序
Aggregation.sort(Sort.Direction.DESC, "userCount"),
// 限制结果
Aggregation.limit(10)
);
return mongoTemplate.aggregate(
aggregation,
"users",
UserAnalytics.class
).getMappedResults();
}
// 复杂聚合示例
public List<OrderAnalytics> getOrderAnalytics() {
Aggregation aggregation = Aggregation.newAggregation(
// 展开订单数组
Aggregation.unwind("orders"),
// 按用户分组
Aggregation.group("_id")
.push("orders").as("userOrders"),
// 计算订单统计
Aggregation.project()
.and("userId").as("_id")
.and("userOrders").as("orders")
.and(ArithmeticOperators.Average.avgOf("orders.amount")).as("averageOrderAmount")
.and(ArithmeticOperators.Sum.sumOf("orders.amount")).as("totalOrderAmount")
);
return mongoTemplate.aggregate(
aggregation,
"users",
OrderAnalytics.class
).getMappedResults();
}
}
@Service
public class UserBatchService {
@Autowired
private MongoTemplate mongoTemplate;
// 批量插入
public void batchInsert(List<User> users) {
mongoTemplate.insertAll(users);
}
// 批量更新
public void batchUpdate(List<User> users) {
BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, User.class);
for (User user : users) {
Update update = new Update()
.set("name", user.getName())
.set("email", user.getEmail())
.set("updatedAt", new Date());
bulkOps.updateOne(
Query.query(Criteria.where("_id").is(user.getId())),
update
);
}
bulkOps.execute();
}
// 批量删除
public void batchDelete(List<String> userIds) {
mongoTemplate.remove(
Query.query(Criteria.where("_id").in(userIds)),
User.class
);
}
// 批量查找
public List<User> batchFind(List<String> userIds) {
return mongoTemplate.find(
Query.query(Criteria.where("_id").in(userIds)),
User.class
);
}
}
@Document(collection = "articles")
public class Article {
@Id
private String id;
private String title;
@TextIndexed(weight = 2)
private String content;
@TextIndexed(weight = 1)
private List<String> tags;
// getters and setters
}
@Service
public class ArticleSearchService {
@Autowired
private MongoTemplate mongoTemplate;
// 全文搜索
public List<Article> searchArticles(String keyword) {
TextCriteria criteria = TextCriteria.forDefaultLanguage()
.matching(keyword)
.caseSensitive(false);
return mongoTemplate.find(
Query.query(criteria),
Article.class
);
}
// 高级全文搜索
public List<Article> advancedSearch(String keyword, int page, int size) {
TextCriteria criteria = TextCriteria.forDefaultLanguage()
.matching(keyword)
.caseSensitive(false);
Query query = Query.query(criteria)
.with(Sort.by(Sort.Direction.DESC, "score"))
.skip(page * size)
.limit(size);
return mongoTemplate.find(query, Article.class);
}
}
@Document(collection = "users")
public class User {
@Indexed(background = true)
private String email;
@CompoundIndex(name = "age_city_idx", def = "{'age': 1, 'city': 1}")
private Integer age;
private String city;
// 部分索引
@Indexed(partialFilter = "{'status': 'active'}")
private String status;
}
@Service
public class UserQueryService {
@Autowired
private MongoTemplate mongoTemplate;
// 使用投影减少数据传输
public List<UserDTO> findUserDTOs() {
return mongoTemplate.find(
Query.query(new Criteria()),
UserDTO.class,
"users"
);
}
// 使用游标处理大量数据
public void processLargeDataSet() {
try (CloseableIterator<User> iterator = mongoTemplate.stream(
Query.query(new Criteria()),
User.class
)) {
while (iterator.hasNext()) {
User user = iterator.next();
// 处理用户数据
}
}
}
// 使用批量操作
public void bulkUpdateUsers(List<User> users) {
BulkOperations bulkOps = mongoTemplate.bulkOps(
BulkOperations.BulkMode.UNORDERED,
User.class
);
for (User user : users) {
Update update = new Update()
.set("lastLogin", new Date());
bulkOps.updateOne(
Query.query(Criteria.where("_id").is(user.getId())),
update
);
}
bulkOps.execute();
}
}
# application.yml
spring:
data:
mongodb:
host: localhost
port: 27017
database: mydb
# 连接池配置
connection-pool:
max-size: 100
min-size: 10
max-wait-time: 5000
max-connection-life-time: 60000
max-connection-idle-time: 30000
@Configuration
public class MongoMetricsConfig {
@Bean
public MongoMetricsCollector mongoMetricsCollector() {
return new MongoMetricsCollector();
}
@Bean
public MongoEventListener<MongoCommandEvent> mongoEventListener(
MongoMetricsCollector metricsCollector) {
return new MongoEventListener<MongoCommandEvent>() {
@Override
public void onApplicationEvent(MongoCommandEvent event) {
metricsCollector.recordCommand(event);
}
};
}
}
# application.yml
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
listener:
simple:
acknowledge-mode: manual
prefetch: 1
@Service
public class MessageService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String message) {
rabbitTemplate.convertAndSend(
"exchange.name",
"routing.key",
message,
message -> {
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return message;
}
);
}
}
@Component
public class MessageListener {
@RabbitListener(queues = "queue.name")
public void handleMessage(Message message, Channel channel) {
try {
// 处理消息
processMessage(message);
// 确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
try {
// 消息处理失败,重新入队
channel.basicNack(
message.getMessageProperties().getDeliveryTag(),
false,
true
);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
@Configuration
@EnableIntegration
public class IntegrationConfig {
@Bean
public MessageChannel inputChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel outputChannel() {
return new DirectChannel();
}
@Bean
public IntegrationFlow fileFlow() {
return IntegrationFlows
.from(Files.inboundAdapter(new File("/input"))
.autoCreateDirectory(true)
.patternFilter("*.txt"))
.channel(inputChannel())
.handle(Files.outboundAdapter(new File("/output"))
.autoCreateDirectory(true)
.fileExistsMode(FileExistsMode.REPLACE))
.get();
}
}
@Configuration
public class MessageTransformConfig {
@Bean
public MessageTransformer transformer() {
return new GenericTransformer<Message<?>, Message<?>>() {
@Override
public Message<?> transform(Message<?> message) {
// 消息转换逻辑
return MessageBuilder
.withPayload(message.getPayload())
.copyHeaders(message.getHeaders())
.build();
}
};
}
}
# application.yml
spring:
data:
mongodb:
uri: mongodb://localhost:27017/mydb
sharding:
enabled: true
shard-key: { "userId": 1 }
chunksize: 64
cluster:
nodes:
- mongodb://shard1:27017
- mongodb://shard2:27017
- mongodb://shard3:27017
config-server: mongodb://config-server:27019
@Service
public class BackupService {
@Autowired
private MongoTemplate mongoTemplate;
public void backupDatabase(String backupPath) {
MongoClient mongoClient = mongoTemplate.getMongoClient();
MongoDatabase database = mongoClient.getDatabase("mydb");
// 创建备份
ProcessBuilder processBuilder = new ProcessBuilder(
"mongodump",
"--uri=mongodb://localhost:27017/mydb",
"--out=" + backupPath
);
try {
Process process = processBuilder.start();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
public void restoreDatabase(String backupPath) {
ProcessBuilder processBuilder = new ProcessBuilder(
"mongorestore",
"--uri=mongodb://localhost:27017/mydb",
backupPath
);
try {
Process process = processBuilder.start();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Configuration
public class MongoSecurityConfig {
@Bean
public MongoClient mongoClient() {
MongoCredential credential = MongoCredential.createCredential(
"user",
"admin",
"password".toCharArray()
);
ServerAddress serverAddress = new ServerAddress("localhost", 27017);
return MongoClients.create(MongoClientSettings.builder()
.credential(credential)
.applyToClusterSettings(builder ->
builder.hosts(Arrays.asList(serverAddress)))
.applyConnectionString(new ConnectionString(
"mongodb://localhost:27017/mydb?authSource=admin"))
.build());
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoClient(), "mydb");
}
}
@Configuration
public class MongoMonitoringConfig {
@Bean
public MongoEventListener<MongoCommandEvent> mongoEventListener() {
return new MongoEventListener<MongoCommandEvent>() {
@Override
public void onApplicationEvent(MongoCommandEvent event) {
// 监控慢查询
if (event.getDuration() > 1000) {
alertSlowQuery(event);
}
// 监控错误
if (event.getException() != null) {
alertError(event);
}
}
};
}
private void alertSlowQuery(MongoCommandEvent event) {
// 发送告警通知
System.out.println("Slow query detected: " + event.getCommand());
}
private void alertError(MongoCommandEvent event) {
// 发送错误通知
System.out.println("Error detected: " + event.getException());
}
}
@Configuration
public class MongoPerformanceConfig {
@Bean
public MongoClient mongoClient() {
return MongoClients.create(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(
"mongodb://localhost:27017/mydb"))
.applyToConnectionPoolSettings(builder -> builder
.maxSize(100)
.minSize(10)
.maxWaitTime(5000, TimeUnit.MILLISECONDS))
.applyToSocketSettings(builder -> builder
.connectTimeout(5000, TimeUnit.MILLISECONDS)
.readTimeout(5000, TimeUnit.MILLISECONDS))
.build());
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate template = new MongoTemplate(mongoClient(), "mydb");
// 设置批量写入
template.setWriteConcern(WriteConcern.MAJORITY);
// 设置读取偏好
template.setReadPreference(ReadPreference.secondaryPreferred());
return template;
}
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 设置消息代理的前缀
config.enableSimpleBroker("/topic", "/queue");
// 设置客户端发送消息的前缀
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册STOMP协议的节点,并指定使用SockJS协议
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
}
@Controller
public class WebSocketController {
@MessageMapping("/chat.send")
@SendTo("/topic/messages")
public ChatMessage send(ChatMessage message) {
return message;
}
@MessageMapping("/chat.private")
@SendToUser("/queue/private")
public ChatMessage privateMessage(ChatMessage message) {
return message;
}
@SubscribeMapping("/topic/status")
public String handleSubscribe() {
return "Connected successfully!";
}
}
public class ChatMessage {
private String sender;
private String content;
private String timestamp;
// getters and setters
}
// 连接WebSocket
const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);
// 连接配置
const connectHeaders = {
'Auth-Token': 'your-auth-token'
};
// 建立连接
stompClient.connect(connectHeaders,
// 连接成功回调
function(frame) {
console.log('Connected: ' + frame);
// 订阅公共消息
stompClient.subscribe('/topic/messages', function(message) {
showMessage(JSON.parse(message.body));
});
// 订阅私人消息
stompClient.subscribe('/user/queue/private', function(message) {
showPrivateMessage(JSON.parse(message.body));
});
},
// 连接错误回调
function(error) {
console.log('STOMP error: ' + error);
}
);
// 发送消息
function sendMessage() {
const message = {
sender: username,
content: messageInput.value,
timestamp: new Date().toISOString()
};
stompClient.send("/app/chat.send", {}, JSON.stringify(message));
}
// 发送私人消息
function sendPrivateMessage() {
const message = {
sender: username,
content: privateMessageInput.value,
recipient: recipientUsername,
timestamp: new Date().toISOString()
};
stompClient.send("/app/chat.private", {}, JSON.stringify(message));
}
@Configuration
@EnableWebSocketSecurity
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpDestMatchers("/app/**").authenticated()
.simpDestMatchers("/topic/**").authenticated()
.anyMessage().authenticated();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
@Configuration
public class WebSocketHeartbeatConfig {
@Bean
public TaskScheduler messageBrokerTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setThreadNamePrefix("ws-heartbeat-thread-");
scheduler.setErrorHandler(t ->
System.err.println("Heartbeat error: " + t.getMessage()));
return scheduler;
}
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) {
// 连接建立后的处理
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
// 处理消息
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
// 处理传输错误
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
// 连接关闭后的处理
}
@Override
public boolean supportsPartialMessages() {
return false;
}
};
}
}
@Component
public class WebSocketChannelInterceptor implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
// 处理连接请求
String token = accessor.getFirstNativeHeader("Auth-Token");
if (token != null && validateToken(token)) {
accessor.setUser(new UserPrincipal(token));
}
}
return message;
}
private boolean validateToken(String token) {
// 实现token验证逻辑
return true;
}
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketClusterConfig implements WebSocketMessageBrokerConfigurer {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue")
.setApplicationDestinationPrefixes("/app");
}
@Bean
public MessageBrokerRegistry messageBrokerRegistry() {
MessageBrokerRegistry registry = new MessageBrokerRegistry();
registry.enableSimpleBroker("/topic", "/queue")
.setApplicationDestinationPrefixes("/app");
return registry;
}
@Bean
public RedisMessageBrokerRegistry redisMessageBrokerRegistry() {
RedisMessageBrokerRegistry registry = new RedisMessageBrokerRegistry(redisTemplate);
registry.enableSimpleBroker("/topic", "/queue")
.setApplicationDestinationPrefixes("/app");
return registry;
}
}
@Configuration
public class WebSocketPerformanceConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.put(session.getId(), session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
// 使用线程池处理消息
CompletableFuture.runAsync(() -> {
try {
processMessage(session, message);
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
sessions.remove(session.getId());
}
private void processMessage(WebSocketSession session, WebSocketMessage<?> message) {
// 实现消息处理逻辑
}
};
}
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("ws-handler-");
executor.initialize();
return executor;
}
}
@Configuration
public class WebSocketReconnectConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.put(session.getId(), session);
scheduleHeartbeat(session);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
handleReconnect(session);
}
private void scheduleHeartbeat(WebSocketSession session) {
scheduler.scheduleAtFixedRate(() -> {
try {
if (session.isOpen()) {
session.sendMessage(new PingMessage());
}
} catch (Exception e) {
handleReconnect(session);
}
}, 0, 30, TimeUnit.SECONDS);
}
private void handleReconnect(WebSocketSession session) {
try {
if (!session.isOpen()) {
// 清理旧会话
cleanupSession(session);
// 创建新会话
createNewSession(session);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void cleanupSession(WebSocketSession session) {
sessions.remove(session.getId());
scheduler.shutdown();
}
private void createNewSession(WebSocketSession session) {
// 实现新会话创建逻辑
}
};
}
}
@Configuration
public class WebSocketCompressionConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String compressed = compressMessage(textMessage.getPayload());
session.sendMessage(new TextMessage(compressed));
}
}
private String compressMessage(String message) {
try {
byte[] input = message.getBytes(StandardCharsets.UTF_8);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(input);
gzipOutputStream.close();
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return message;
}
}
};
}
}
@Configuration
public class WebSocketPersistenceConfig {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private static final String MESSAGE_KEY_PREFIX = "ws:message:";
private static final String SESSION_KEY_PREFIX = "ws:session:";
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
// 持久化消息
persistMessage(session, message);
// 处理消息
processMessage(session, message);
}
private void persistMessage(WebSocketSession session, WebSocketMessage<?> message) {
String messageKey = MESSAGE_KEY_PREFIX + session.getId() + ":" + System.currentTimeMillis();
String sessionKey = SESSION_KEY_PREFIX + session.getId();
// 存储消息
redisTemplate.opsForValue().set(messageKey, message);
// 更新会话消息列表
redisTemplate.opsForList().rightPush(sessionKey, messageKey);
// 设置过期时间
redisTemplate.expire(messageKey, 24, TimeUnit.HOURS);
redisTemplate.expire(sessionKey, 24, TimeUnit.HOURS);
}
// 消息恢复
public void restoreMessages(WebSocketSession session) {
String sessionKey = SESSION_KEY_PREFIX + session.getId();
List<String> messageKeys = redisTemplate.opsForList().range(sessionKey, 0, -1);
if (messageKeys != null) {
for (String messageKey : messageKeys) {
WebSocketMessage<?> message = (WebSocketMessage<?>) redisTemplate.opsForValue().get(messageKey);
if (message != null) {
session.sendMessage(message);
}
}
}
}
};
}
}
@Configuration
public class WebSocketMonitoringConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private final Counter messageCounter = new Counter();
private final Timer messageLatencyTimer = new Timer();
private final Gauge activeConnectionsGauge = new Gauge();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
activeConnectionsGauge.increment();
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
messageCounter.increment();
long startTime = System.currentTimeMillis();
try {
processMessage(session, message);
} finally {
long latency = System.currentTimeMillis() - startTime;
messageLatencyTimer.record(latency);
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
activeConnectionsGauge.decrement();
}
// 性能指标导出
@Scheduled(fixedRate = 60000)
public void exportMetrics() {
Metrics metrics = new Metrics();
metrics.setMessageCount(messageCounter.getCount());
metrics.setAverageLatency(messageLatencyTimer.getAverage());
metrics.setActiveConnections(activeConnectionsGauge.getValue());
// 导出到监控系统
exportToMonitoringSystem(metrics);
}
private void exportToMonitoringSystem(Metrics metrics) {
// 实现指标导出逻辑
}
};
}
}
@Configuration
public class WebSocketRateLimitConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private final Map<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
// 为每个会话创建限流器
rateLimiters.put(session.getId(), RateLimiter.create(10.0)); // 每秒10条消息
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
RateLimiter limiter = rateLimiters.get(session.getId());
if (limiter != null && limiter.tryAcquire()) {
processMessage(session, message);
} else {
// 发送限流提示
session.sendMessage(new TextMessage("Rate limit exceeded"));
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
rateLimiters.remove(session.getId());
}
};
}
}
@Configuration
public class WebSocketFilterConfig {
@Bean
public WebSocketHandler webSocketHandler() {
return new WebSocketHandler() {
private final List<MessageFilter> filters = Arrays.asList(
new XssFilter(),
new ProfanityFilter(),
new LengthFilter()
);
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String content = textMessage.getPayload();
// 应用过滤器链
for (MessageFilter filter : filters) {
if (!filter.filter(content)) {
session.sendMessage(new TextMessage("Message filtered"));
return;
}
}
processMessage(session, message);
}
}
};
}
}