增加 spring websocket 用例
This commit is contained in:
		@@ -0,0 +1,11 @@
 | 
			
		||||
package com.heibaiying.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description :
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
public interface Constant {
 | 
			
		||||
 | 
			
		||||
    String USER_NAME="username";
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
package com.heibaiying.controller;
 | 
			
		||||
 | 
			
		||||
import com.heibaiying.constant.Constant;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpSession;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description : 简单登录
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
@Controller
 | 
			
		||||
public class LoginController {
 | 
			
		||||
 | 
			
		||||
    @PostMapping("login")
 | 
			
		||||
    public String login(String username, HttpSession session){
 | 
			
		||||
        session.setAttribute(Constant.USER_NAME,username);
 | 
			
		||||
        return "chat";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
package com.heibaiying.webconfig;
 | 
			
		||||
 | 
			
		||||
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description : 等价于 web.xml 中配置前端控制器
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 | 
			
		||||
 | 
			
		||||
    protected Class<?>[] getRootConfigClasses() {
 | 
			
		||||
        return new Class[0];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Class<?>[] getServletConfigClasses() {
 | 
			
		||||
        return new Class[]{ServletConfig.class};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected String[] getServletMappings() {
 | 
			
		||||
        return new String[]{"/"};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
package com.heibaiying.webconfig;
 | 
			
		||||
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.ComponentScan;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.servlet.ViewResolver;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 | 
			
		||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 | 
			
		||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description : 主配置类
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
@EnableWebMvc
 | 
			
		||||
@ComponentScan(basePackages = {"com.heibaiying.*"})
 | 
			
		||||
public class ServletConfig implements WebMvcConfigurer {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 配置视图解析器
 | 
			
		||||
     */
 | 
			
		||||
    @Bean
 | 
			
		||||
    public ViewResolver viewResolver() {
 | 
			
		||||
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
 | 
			
		||||
        internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
 | 
			
		||||
        internalResourceViewResolver.setSuffix(".jsp");
 | 
			
		||||
        internalResourceViewResolver.setExposeContextBeansAsAttributes(true);
 | 
			
		||||
        return internalResourceViewResolver;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 配置静态资源处理器
 | 
			
		||||
     */
 | 
			
		||||
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
 | 
			
		||||
        configurer.enable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
package com.heibaiying.webconfig;
 | 
			
		||||
 | 
			
		||||
import org.springframework.web.filter.CharacterEncodingFilter;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.annotation.WebFilter;
 | 
			
		||||
import javax.servlet.annotation.WebInitParam;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description : 编码过滤器 防止乱码
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
@WebFilter(filterName = "characterEncodingFilter", urlPatterns = "/*",
 | 
			
		||||
        initParams = {
 | 
			
		||||
                @WebInitParam(name = "encoding", value = "UTF-8"),
 | 
			
		||||
                @WebInitParam(name = "forceEncoding", value = "true")
 | 
			
		||||
        }
 | 
			
		||||
)
 | 
			
		||||
public class characterEncodingFilter extends CharacterEncodingFilter {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
package com.heibaiying.websocket;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.ServerHttpRequest;
 | 
			
		||||
import org.springframework.http.server.ServerHttpResponse;
 | 
			
		||||
import org.springframework.web.socket.WebSocketHandler;
 | 
			
		||||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : heibaiying
 | 
			
		||||
 * @description : 可以按照需求实现权限拦截等功能
 | 
			
		||||
 */
 | 
			
		||||
public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
 | 
			
		||||
        InetSocketAddress remoteAddress = request.getRemoteAddress();
 | 
			
		||||
        InetAddress address = remoteAddress.getAddress();
 | 
			
		||||
        System.out.println(address);
 | 
			
		||||
        /*
 | 
			
		||||
         * 最后需要要显示调用父类方法,父类的beforeHandshake方法
 | 
			
		||||
         * 把ServerHttpRequest 中session中对应的值拷贝到WebSocketSession中。
 | 
			
		||||
         * 如果我们没有实现这个方法,我们在最后的handler处理中 是拿不到 session中的值
 | 
			
		||||
         * 作为测试 可以注释掉下面这一行 可以发现自定义处理器中session的username总是为空
 | 
			
		||||
         */
 | 
			
		||||
        return super.beforeHandshake(request, response, wsHandler, attributes);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,60 @@
 | 
			
		||||
package com.heibaiying.websocket;
 | 
			
		||||
 | 
			
		||||
import com.heibaiying.constant.Constant;
 | 
			
		||||
import org.springframework.web.socket.CloseStatus;
 | 
			
		||||
import org.springframework.web.socket.TextMessage;
 | 
			
		||||
import org.springframework.web.socket.WebSocketSession;
 | 
			
		||||
import org.springframework.web.socket.handler.TextWebSocketHandler;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URLDecoder;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : heibaiying
 | 
			
		||||
 * @description : 自定义消息处理类
 | 
			
		||||
 */
 | 
			
		||||
public class CustomerHandler extends TextWebSocketHandler {
 | 
			
		||||
 | 
			
		||||
    private Map<String, WebSocketSession> nameAndSession = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
    // 建立连接时候触发
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterConnectionEstablished(WebSocketSession session)  {
 | 
			
		||||
        String username = getNameFromSession(session);
 | 
			
		||||
        nameAndSession.putIfAbsent(username, session);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // 关闭连接时候触发
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
 | 
			
		||||
        String username = getNameFromSession(session);
 | 
			
		||||
        nameAndSession.remove(username);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 处理消息
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
 | 
			
		||||
        // 防止中文乱码
 | 
			
		||||
        String msg = URLDecoder.decode(message.getPayload(), "utf-8");
 | 
			
		||||
        String username = getNameFromSession(session);
 | 
			
		||||
        // 简单模拟群发消息
 | 
			
		||||
        TextMessage reply = new TextMessage(username + " : " + msg);
 | 
			
		||||
        nameAndSession.forEach((s, webSocketSession)
 | 
			
		||||
                -> {
 | 
			
		||||
            try {
 | 
			
		||||
                webSocketSession.sendMessage(reply);
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private String getNameFromSession(WebSocketSession session) {
 | 
			
		||||
        Map<String, Object> attributes = session.getAttributes();
 | 
			
		||||
        return (String) attributes.get(Constant.USER_NAME);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
package com.heibaiying.websocket;
 | 
			
		||||
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
 | 
			
		||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
 | 
			
		||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : 罗祥
 | 
			
		||||
 * @description :websocket 配置
 | 
			
		||||
 * @date :create in 2018/12/27
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
@EnableWebSocket
 | 
			
		||||
public class WebSocketConfig implements WebSocketConfigurer {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
 | 
			
		||||
        registry.addHandler(new CustomerHandler(), "/socket").addInterceptors(new CustomHandshakeInterceptor());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <title>${sessionScope.get("username")}您好!欢迎进入群聊大厅!</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<input id="message" type="text">
 | 
			
		||||
<button id="btn">发送消息</button>
 | 
			
		||||
<div id="show">
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
<script>
 | 
			
		||||
    let btn = document.getElementById("btn");
 | 
			
		||||
    let message = document.getElementById("message");
 | 
			
		||||
    let show = document.getElementById("show");
 | 
			
		||||
    let ws = new WebSocket("ws://localhost:8080/socket");
 | 
			
		||||
    ws.onmessage = function (evt) {
 | 
			
		||||
        let node = document.createElement("div");
 | 
			
		||||
        node.innerHTML = "<h5>" + evt.data + "</h5>";
 | 
			
		||||
        show.appendChild(node);
 | 
			
		||||
    };
 | 
			
		||||
    btn.addEventListener("click", function () {
 | 
			
		||||
        let data = message.value;
 | 
			
		||||
        console.log(data);
 | 
			
		||||
        if (data) {
 | 
			
		||||
            ws.send(encodeURI(data));
 | 
			
		||||
        } else {
 | 
			
		||||
            alert("请输入消息后发送");
 | 
			
		||||
        }
 | 
			
		||||
        message.value = "";
 | 
			
		||||
    });
 | 
			
		||||
    // 关闭页面时候关闭ws
 | 
			
		||||
    window.addEventListener("beforeunload", function(event) {
 | 
			
		||||
        ws.close();
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										12
									
								
								spring/spring-websocket-annotation/src/main/webapp/index.jsp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								spring/spring-websocket-annotation/src/main/webapp/index.jsp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <title>Title</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<form action="${pageContext.request.contextPath}/login" method="post">
 | 
			
		||||
    <input name="username" type="text">
 | 
			
		||||
    <button id="btn">输入临时用户名后登录!</button>
 | 
			
		||||
</form>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user