spring boot websocket + thy模版

本文介绍如何使用SpringBoot搭建WebSocket应用,实现简单的消息推送及一对一聊天功能。文章详细配置了pom.xml依赖、application.properties参数、Java启动类、WebSocket配置类、控制器以及前端页面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、pom.xml文件配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.hxkj</groupId>
	<artifactId>waychat</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- Inherit defaults from Spring Boot -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.0.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<!-- Add typical dependencies for a web application -->
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--Mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<!--spring-mybatis包 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.1.1</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- websocket -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<!-- 单元测试 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- spring热部署 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>

	<!-- Package as an executable jar -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<dependencies>
				</dependencies>
			</plugin>
		</plugins>
	</build>

	<packaging>war</packaging>
</project>


二、application.properties配置

#jdbc datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/waychat?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50000
spring.datasource.tomcat.test-on-borrow=true

# EMBEDDED SERVER CONFIGURATION (ServerProperties)
server.port=8080

# JACKSON (JacksonProperties)
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

# thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.check-template-location=false
spring.thymeleaf.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML5
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

# SPRING RESOURCES HANDLING (ResourceProperties)
spring.resources.chain.cache=false

三、application.java配置启动容器

package com.hxkj.waychat;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
@SpringBootApplication
@MapperScan(basePackages={"com.hxkj.waychat.dao"})
@ServletComponentScan
public class Application extends SpringBootServletInitializer {
	
	
	private static Logger logger = Logger.getLogger(Application.class);

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
		return builder.sources(Application.class);
	}

	@Bean
	@ConfigurationProperties(prefix = "spring.datasource")
	public DataSource dataSource() {
		return new org.apache.tomcat.jdbc.pool.DataSource();
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactoryBean() throws Exception {

		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dataSource());

		PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

		sqlSessionFactoryBean.setConfigLocation(resolver.getResource("classpath:/mybatis/config.xml"));
		sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/com/hxkj/waychat/mapper/*Mapper.xml"));
		sqlSessionFactoryBean.setTypeAliasesPackage("com.hxkj.waychat.entity,com.hxkj.waychat.entity.query,com.hxkj.waychat.entity.result");
		return sqlSessionFactoryBean.getObject();
	}

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
		logger.info("============= SpringBoot Start Success =============");
	}
}

四、WebSocketConfig.java配置

package com.hxkj.websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

	@Override    
    public void registerStompEndpoints(StompEndpointRegistry registry) {        
        registry.addEndpoint("/socket").withSockJS()
        .setInterceptors( new ChatHandlerShareInterceptor())
        .setStreamBytesLimit(512 * 1024)
        .setHttpMessageCacheSize(1000)
        .setDisconnectDelay(30 * 1000);;       
    }    
	
    @Override    
    public void configureMessageBroker(MessageBrokerRegistry registry) {  
        registry.enableSimpleBroker("/topic","/user");  
        registry.setApplicationDestinationPrefixes("/app"); 
        //registry.setPathMatcher(new AntPathMatcher("."));
    }

}


websocket拦截器配置,读取session


package com.hxkj.websocket.config;

import java.util.Map;

import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

public class ChatHandlerShareInterceptor extends HttpSessionHandshakeInterceptor {

	private static Logger logger = LoggerFactory.getLogger(ChatHandlerShareInterceptor.class);
	
	@Override
	public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
			Exception ex) {
		// TODO Auto-generated method stub
		super.afterHandshake(request, response, wsHandler, ex);
	}

	@Override
	public boolean beforeHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2,
			Map<String, Object> arg3) throws Exception {
		
		if(arg0 instanceof ServletServerHttpRequest){
			ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) arg0;  
            HttpSession session = servletRequest.getServletRequest().getSession(false);  
            if (session != null) {  
                //使用userName区分WebSocketHandler,以便定向发送消息  
                String httpSessionId = session.getId();
                logger.info(httpSessionId);  
                arg3.put("HTTP_SESSION_ID",httpSessionId);  
            }else{  
            }  
		}
		
		return true;
	}

}


五、websocket访问连接配置

package com.hxkj.websocket.controller;

import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.websocket.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class GreetingController {

	@Autowired
    private SimpMessagingTemplate simpMessagingTemplate;  
	
	@RequestMapping("getSession") 
	@ResponseBody
	public String getSession(HttpSession session){
		System.out.println(session.getId());
		return "index";
	}
	
	@RequestMapping("index") 
	public String index(HttpSession session){
		System.out.println(session.getId());
		return "index";
	}
	
    @RequestMapping("/helloSocket")    
    public String helloSocket(){        
        return "hello/index";    
    }  
    
    @RequestMapping("/oneToOne")    
    public String oneToOne(){        
        return "oneToOne";    
    }  
    
    @MessageMapping(value="/change-notice")    
    //@SendToUser(value="/topic/notice")
    //@SendTo(value="/topic/notice")
    public void greeting(SimpMessageHeaderAccessor headerAccessor,String value){
    	System.out.println(headerAccessor.getSessionAttributes());
    	Map<String,Object> map = headerAccessor.getSessionAttributes();
    	System.out.println("HTTP_SESSION_ID:"+map.get("HTTP_SESSION_ID"));
    	System.out.println("session:"+headerAccessor.getSessionId()+"		value:"+value);
        this.simpMessagingTemplate.convertAndSend("/topic/notice", value);    
    	//return value;
    }
    
    @MessageMapping(value="/change-notice-greetingToOne")    
    //@SendToUser(value="/topic/greetingToOne")
    public void greetingToOne(SimpMessageHeaderAccessor headerAccessor,String value){
    	System.out.println(headerAccessor.getSessionAttributes());
    	Map<String,Object> map = headerAccessor.getSessionAttributes();
    	System.out.println("HTTP_SESSION_ID:"+map.get("HTTP_SESSION_ID"));
    	System.out.println("session:"+headerAccessor.getSessionId()+"		value:"+value);
    	this.simpMessagingTemplate.convertAndSendToUser(headerAccessor.getSessionId(), "/greetingToOne/", value);
    	//return value;
    }
    
}


六、前台页面设计

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Insert title here</title>
</head>
<body>
<h1>this is websocket</h1>
<div>    
    <div>        
        <button id="connect" onclick="connect();">Connect</button> 
       <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>    
    </div>    
    <div id="conversationDiv">        
        <p>            
            <label>notice content?</label>        
        </p>        
        <p>            
              <textarea id="name" rows="5"></textarea>        
        </p>        
        <button id="sendName" onclick="sendName();">Send</button>        
        <p id="response"></p>    
    </div>
    
    <div id="">
    	<h4>聊天区域</h4>
    	<div id="chat-center" style="height: 100px;width: 100%;overflow: auto;">
    	</div>
    </div>
</div>
<script type="text/javascript" src="jquery/jquery.min.js"></script>
<script type="text/javascript" src="websocket/sockjs-1.1.1.min.js"></script>
<script type="text/javascript" src="websocket/stomp.min.js"></script>
<script>    
    var stompClient = null;    
    function setConnected(connected) {        
        document.getElementById('connect').disabled = connected;        
        document.getElementById('disconnect').disabled = !connected;        
        document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';        
        document.getElementById('response').innerHTML = '';    
    }    
    // 开启socket连接
    function connect() {        
        var socket = new SockJS('/socket');        
        stompClient = Stomp.over(socket);        
        stompClient.connect({}, function (frame) {            
             setConnected(true);  
             showMsg();
        });    
    }    
    // 断开socket连接
    function disconnect() {        
        if (stompClient != null) {            
            stompClient.disconnect();        
        }        
        setConnected(false);        
        console.log("Disconnected");    
    }    
    // 向‘/app/change-notice’服务端发送消息
    function sendName() {        
        var value = document.getElementById('name').value;            
        stompClient.send("/app/change-notice", {}, value);    
    }    
    //数据显示
    function showMsg() {
    	stompClient.subscribe('/topic/notice', function (data) {    
    		console.log(data);
    	      $('#chat-center').append(data.body+'<hr></hr>');        
    	    }); 
    }
    connect();
</script>
</body>
</html>


one to one配置聊天

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Insert title here</title>
</head>
<body>
<h1>this is websocket</h1>
<div>    
    <div>        
        <button id="connect" onclick="connect();">Connect</button> 
       <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>    
    </div>    
    <div id="conversationDiv">        
        <p>            
            <label>notice content?</label>        
        </p>        
        <p>            
              <textarea id="name" rows="5"></textarea>        
        </p>        
        <button id="sendName" onclick="sendName();">Send</button>        
        <p id="response"></p>    
    </div>
    
    <div id="">
    	<h4>聊天区域</h4>
    	<div id="chat-center" style="height: 100px;width: 100%;overflow: auto;">
    	</div>
    </div>
</div>
<script type="text/javascript" src="jquery/jquery.min.js"></script>
<script type="text/javascript" src="websocket/sockjs-1.1.1.min.js"></script>
<script type="text/javascript" src="websocket/stomp.min.js"></script>
<script>    
    var stompClient = null;    
    function setConnected(connected) {        
        document.getElementById('connect').disabled = connected;        
        document.getElementById('disconnect').disabled = !connected;        
        document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';        
        document.getElementById('response').innerHTML = '';    
    }    
    // 开启socket连接
    function connect() {        
        var socket = new SockJS('/socket');        
        stompClient = Stomp.over(socket);        
        stompClient.connect({}, function (frame) {            
             setConnected(true);  
             showMsg();
        });    
    }    
    // 断开socket连接
    function disconnect() {        
        if (stompClient != null) {            
            stompClient.disconnect();        
        }        
        setConnected(false);        
        console.log("Disconnected");    
    }    
    // 向‘/app/change-notice’服务端发送消息
    function sendName() {    
    	getSession();
        var value = document.getElementById('name').value;            
        stompClient.send("/app/change-notice-greetingToOne", {}, value);    
    }    
    //数据显示
    function showMsg() {
    	stompClient.subscribe('/user/001/greetingToOne/', function (data) {    
    		console.log(data);
    	      $('#chat-center').append(data.body+'<hr></hr>');        
    	    }); 
    }
    connect();
    
    function getSession(){
    	$.ajax({
    		url:'../getSession',
    		type:'POST',
    		data:{},
    		success:function(data){
    			console.log(data);
    		}
    	});
    }
</script>
</body>
</html>

 

转载于:https://my.oschina.net/fellowtraveler/blog/731261

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值