eclipse下,项目结构图:
SocketController类:
package com.iflytek.controller;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.socket.TextMessage;
import com.iflytek.socket.SocketHandler;
/**
* @desp Socket控制器
*
*/
@Controller
@RequestMapping(value="/main")
public class SocketController{
private static final Logger logger = LoggerFactory.getLogger(SocketController.class);
@Autowired
private SocketHandler socketHandler;
@RequestMapping(value="/login")
public String login(HttpSession session){
logger.info("用户登录了建立连接啦");
session.setAttribute("user", "yy");
return "home";
}
@RequestMapping(value = "/message", method = RequestMethod.GET)
public String sendMessage(){
socketHandler.sendMessageToUser("yy", new TextMessage("这是一条测试的消息"));
return "message";
}
}
SocketHandler类:
package com.iflytek.socket;
import java.io.IOException;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* @desp Socket处理类
*
*/
@Service
public class SocketHandler implements WebSocketHandler{
private static final Logger logger;
private static final ArrayList<WebSocketSession> users;
static{
users = new ArrayList<WebSocketSession>();
logger = LoggerFactory.getLogger(SocketHandler.class);
}
@Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
logger.info("成功建立socket连接");
users.add(session);
String username = session.getAttributes().get("user").toString();
if(username != null){
session.sendMessage(new TextMessage("我们已经成功建立socket通信了"));
}
}
@Override
public void handleMessage(WebSocketSession arg0, WebSocketMessage<?> arg1)
throws Exception {
}
@Override
public void handleTransportError(WebSocketSession session, Throwable error)
throws Exception {
if(session.isOpen()){
session.close();
}
logger.error("连接出现错误:"+error.toString());
users.remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus arg1)
throws Exception {
logger.debug("连接已关闭");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(String userName, TextMessage message) {
for (WebSocketSession user : users) {
if (user.getAttributes().get("user").equals(userName)) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
//break;
}
}
}
}
WebSocketConfig类:
package com.iflytek.socket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
* @Configuration @Component
* 只有一个实例对象,哪怕手动创建也只有一个; 系统会创建对象,如果手动创建,这两个不同
*
* @EnableWebMvc 需要以编程的方式指定视图文件相关配置
*
* @EnableWebSocket
*
*/
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
@Autowired
private SocketHandler socketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//注册处理拦截器,拦截url为socketServer的请求
registry.addHandler(socketHandler, "/socketServer").addInterceptors(new WebSocketInterceptor());
//注册SockJs的处理拦截器,拦截url为/sockjs/socketServer的请求
registry.addHandler(socketHandler, "/sockjs/socketServer").addInterceptors(new WebSocketInterceptor()).withSockJS();
}
}
WebSocketInterceptor类:
package com.iflytek.socket;
import java.util.Map;
import javax.servlet.http.HttpSession;
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.HandshakeInterceptor;
/**
* @desp websocket拦截器
*
* HandshakeInterceptor
* WebSocket握手请求的拦截器. 检查握手请求和响应, 对WebSocketHandler传递属性
*/
public class WebSocketInterceptor implements HandshakeInterceptor{
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler handler, Exception exception) {
}
/**
* @desp 将HttpSession中对象放入WebSocketSession中
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler handler,
Map<String, Object> map) throws Exception {
if(request instanceof ServerHttpRequest){
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession();
if(session != null){
//区分socket连接以定向发送消息
map.put("user", session.getAttribute("user"));
}
}
return true;
}
}
servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/static/**" location="/static/" />
<resources mapping="/js/**" location="/js/" />
<resources mapping="/css/**" location="/css/" />
<resources mapping="/img/**" location="/img/" />
<resources mapping="/images/**" location="/images/" />
<resources mapping="/fonts/**" location="/fonts/" />
<resources mapping="/i18n/**" location="/i18n/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- AOP 配置需要和MVC置于一个Context中,否则将不能生效,这是一个大坑!-->
<!-- <aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"></aop:config> -->
<!-- <context:component-scan base-package="com.iflytek" /> -->
</beans:beans>
application-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="com.iflytek" />
</beans>
log4j.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- Application Loggers -->
<logger name="com.iflytek">
<level value="info" />
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="info" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
home.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
String wsPath = "ws://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world! This is a WebSocket demo!
<div id="message">
</div>
</h1>
<script type="text/javascript" src="<%=path%>/static/js/jquery-1.12.2.min.js"></script>
<script type="text/javascript" src="<%=path%>/static/js/sockjs.min.js"></script>
<script type="text/javascript">
$(function(){
//建立socket连接
var sock;
if ('WebSocket' in window) {
sock = new WebSocket("ws://localhost:8080/websocket/socketServer");
} else if ('MozWebSocket' in window) {
sock = new MozWebSocket("<%=wsPath%>socketServer");
} else {
sock = new SockJS("<%=basePath%>sockjs/socketServer");
}
sock.onopen = function (e) {
console.log(e);
};
sock.onmessage = function (e) {
console.log(e)
$("#message").append("<p><font color='red'>"+e.data+"</font>")
};
sock.onerror = function (e) {
console.log(e);
};
sock.onclose = function (e) {
console.log(e);
}
});
</script>
</body>
</html>
message.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>message</title>
</head>
<body>
<h1>已经发送消息了</h1>
</body>
</html>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3.1.xsd http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-config.xml</param-value>
</context-param>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ifly</groupId>
<artifactId>websocket</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>websocket Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- 远程仓库列表,它是Maven用来填充构建系统本地仓库所使用的一组远程项目。 -->
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<finalName>websocket</finalName>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<org.springframework.version>4.1.2.RELEASE</org.springframework.version>
<org.slf4j.version>1.6.6</org.slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Spring WebSocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
</dependencies>
</project>