一、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>