1.创建项目
Sevlet多的情况推荐还是要web.xml管理Servlet,方便维护和管理。
如果Sevlet少,就使用@WebServle注解方式管理。
2.创建登陆的Servlet [可以直接访问]
HttpServlet依赖于Tomcat。
2.1 添加tomcat依赖
package controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Program: nettyDemo
* @Description: controller.LoginServlet
* @Author: BitterGourd
* @Date: 2020-03-07 00:08
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String userName = req.getParameter("username");
String passWord = req.getParameter("password");
System.out.println("username: "+userName+",password: "+passWord);
HttpSession session = req.getSession();
String id = session.getId();
System.out.println("wssessionid:"+id);
req.getRequestDispatcher("/WEB-INF/jsp/WebSocketChat.jsp").forward(req,resp);
// WebSocketChat.jsp不允许直接访问放在WEB-INF下 转发进去
}
}
3.创建WebSocket
@ServerEndpoint("/url")是创建WebSocket的Server类需要的注解 用法同 @WebServlet("/url"),url是前端建立连接时需要的地址
- 一般情况下加入tomcat依赖时不会引入websocket的jar包
package controller;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Program: nettyDemo
* @Description: WSServer
* @Author: BitterGourd
* @Date: 2020-03-08 01:59
*/
@ServerEndpoint("/chatRoom")
public class WSServer {
private static final Set<WSServer> connections =
new CopyOnWriteArraySet<>(); // 连接的数量
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private Session session; // 保存的客户端的session
private final String nickname;
public WSServer() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
public void sendMsgToAll(String message) throws IOException {
for (WSServer eve : connections){
eve.session.getBasicRemote().sendText(message);
}
}
@OnOpen
public void start(Session session) throws IOException { // webSocket包下的Session类
System.out.println(new String("连接建立成功".getBytes(),"utf-8"));
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "加入了聊天室.");
sendMsgToAll(message);
}
@OnClose
public void end() throws IOException {
System.out.println("连接关闭");
connections.remove(this);
String message = String.format("* %s %s", nickname, "离开了聊天室.");
sendMsgToAll(message);
connectionIds.getAndDecrement();
}
@OnMessage
public void incoming(String message) throws IOException { // 接收前台发送的消息
System.out.println(nickname+"说: "+message);
sendMsgToAll(message);
}
@OnError
public void onError(Throwable t) throws Throwable{
System.out.println("Chat Error: " + t.toString());
}
}
4.Demo整体流程
4.0项目结构
4.1 先写index.jsp [登陆页面]
<%--
Created by IntelliJ IDEA.
User: lenovo
Date: 2020/3/6
Time: 23:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆</title>
</head>
<body>
<div>
<form action="login">
<table>
<tr>
<td>用户名: </td>
<td><input type="text" id="username" name="username" placeholder="输入用户名..."></td>
</tr>
<tr>
<td>密码: </td>
<td><input type="password" id="password" name="password" placeholder="请输入密码..."></td>
</tr>
<tr>
<td><button type="submit">登陆</button></td>
</tr>
</table>
</form>
</div>
</body>
</html>
4.2 表单提交到LoginServlet
package controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Program: nettyDemo
* @Description: controller.LoginServlet
* @Author: BitterGourd
* @Date: 2020-03-07 00:08
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String userName = req.getParameter("username");
String passWord = req.getParameter("password");
System.out.println("username: "+userName+",password: "+passWord);
HttpSession session = req.getSession();
String id = session.getId();
System.out.println("wssessionid:"+id);
req.getRequestDispatcher("/WEB-INF/jsp/WebSocketChat.jsp").forward(req,resp);
}
}
4.3 WebSocket聊天室页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ChatRoom</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
var ws;
var ws_url = "ws://127.0.0.1:8080/WebSocket/chatRoom"
$(function () {
wsConnect();
$("#send").click(function () {
sendMessage();
})
})
function wsConnect() {
if ('WebSocket' in window) {
ws = new WebSocket(ws_url); // 连接成功 回调函数生成一个ws对象(websocket连接)
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(ws_url);
} else {
console.log('Error: WebSocket is not supported by this browser.');
return;
}
// 都是回调函数
ws.onopen = function () {
console.log('Info: WebSocket connection opened.');
};
ws.onclose = function () {
console.log('Info: WebSocket closed.');
};
ws.onmessage = function (message) { // message是从后台传过来的
console.log(message.data);
$("#chat_content").append("<p>"+message.data+"</p>");
};
}
function sendMessage() {
var sendMsg = $("#msg").val();
ws.send(sendMsg);
$("#msg").val("");
}
</script>
</head>
<body>
<div style="610px;border:1px solid #000">
<h1 align="center">Welcome to ChatRoom</h1>
<div id="chat_content" style="margin: 2px; 600px; height: 400px;border:1px solid #000;">
</div>
<input id="msg" placeholder="输入消息..." style="margin: 2px; 300px;"><button id="send">发送消息</button>
</div>
</body>
</html>
4.4 WSServer类
package controller;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Program: nettyDemo
* @Description: WSServer
* @Author: BitterGourd
* @Date: 2020-03-08 01:59
*/
@ServerEndpoint("/chatRoom")
public class WSServer {
private static final Set<WSServer> connections =
new CopyOnWriteArraySet<>(); // 连接的数量
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private Session session; // 保存的客户端的session
private final String nickname;
public WSServer() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
public void sendMsgToAll(String message) throws IOException {
for (WSServer eve : connections){
eve.session.getBasicRemote().sendText(message);
}
}
@OnOpen
public void start(Session session) throws IOException { // webSocket包下的Session类
System.out.println(new String("连接建立成功".getBytes(),"utf-8"));
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "加入了聊天室.");
sendMsgToAll(message);
}
@OnClose
public void end() throws IOException {
System.out.println("连接关闭");
connections.remove(this);
String message = String.format("* %s %s", nickname, "离开了聊天室.");
sendMsgToAll(message);
connectionIds.getAndDecrement();
}
@OnMessage
public void incoming(String message) throws IOException { // 接收前台发送的消息
System.out.println(nickname+"说: "+message);
sendMsgToAll(message);
}
@OnError
public void onError(Throwable t) throws Throwable{
System.out.println("Chat Error: " + t.toString());
}
}
5.效果