一、为什么用webscocket
http只能客户端发向服务器,而我们需要双向通信
二、先导包
<!--WebSocket 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<!--处理时间格式的 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<!--如果客户端浏览器不支持websocket降级为aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
三、配置需要websocket拦截的路径
可以配置xml,可以用注解在类中配置(注意添加context:component-scan 扫到这个类)我这里是注解
@EnableWebMvc
@Configuration
@EnableWebSocket
public class MyWebSocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(webSocketHandler(),"/websocket/socketServer.action")
.addInterceptors(new MyHandShakeInterceptor());
webSocketHandlerRegistry.addHandler(webSocketHandler(), "/sockjs/socketServer.action").setAllowedOrigins("http://localhost:8080")
.addInterceptors(new MyHandShakeInterceptor()).withSockJS();
}
@Bean
public MyWebSocketHandler webSocketHandler(){
return new MyWebSocketHandler();
}
}
这里路径就是JavaScript里ws://…(后面有),如果你springmvc配的要带.action,这里就要带.action,JavaScript里和这长得一样,也带.action。如果你配的.do就加.do。
配的/就不加
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
四、配置握手前的拦截器
这里不用粘过去,手打前面,alt+enter会生成这俩函数,函数里完成握手前的操做。
应该把你当前登录的用户存到map里,我这里代码比较臭是因为我有两种用户,得分别判断。
import java.util.Map;
public class MyHandShakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
HttpSession session = servletRequest.getServletRequest().getSession(false);
//标记用户
//如果是user
if (session.getAttribute("wUsers")!=null) {
System.out.println("Websocket:求职者[username:" + ((ServletServerHttpRequest) serverHttpRequest).getServletRequest().getSession(false).getAttribute("wUsers") + "]已经建立连接");
WUsers user = (WUsers) session.getAttribute("wUsers");
if(user!=null){
map.put("uid", user.getUsername());//为服务器创建WebSocketSession做准备
System.out.println("用户username:"+user.getUsername()+" 被加入");
}else{
System.out.println("user为空");
return false;
}
}
//如果是hr
if (session.getAttribute("wHr")!=null) {
System.out.println("Websocket:招聘者[username:" + ((ServletServerHttpRequest) serverHttpRequest).getServletRequest().getSession(false).getAttribute("wUsers") + "]已经建立连接");
WHr user = (WHr) session.getAttribute("wHr");
if(user!=null){
map.put("uid", user.getUsername());//为服务器创建WebSocketSession做准备
System.out.println("用户username:"+user.getUsername()+" 被加入");
}else{
System.out.println("user为空");
return false;
}
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
五、配置发消息的处理器
还是建议手打,再生成,不要直接粘我下面的代码,可能会出问题
注意:我的主键是String型的usernmae,代码里写的uid
Message是自定义的类,属性最好有fromid,toid,text,time,其他的随意加
import java.util.Map;
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
@Autowired
private ContactService youandmeService;
//当MyWebSocketHandler类被加载时就会创建该Map,随类而生
public static final Map<String, WebSocketSession> userSocketSessionMap;
static {
userSocketSessionMap = new HashMap<String, WebSocketSession>();
}
public MyWebSocketHandler() {}
//握手实现连接后,也就是MyHandShakeInterceptor beforeHandshake 出来
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
//beforeHandshake中 map放进去的
String uid = (String) webSocketSession.getAttributes().get("uid");
// System.out.println("握手连接uid:"+uid);
if (userSocketSessionMap.get(uid) == null) {
userSocketSessionMap.put(uid, webSocketSession);
}
}
//发送信息
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
System.out.println("进handleMessage");
if(webSocketMessage.getPayloadLength()==0)return;
//得到Socket通道中的数据并转化为Message对象
Message msg=new Gson().fromJson(webSocketMessage.getPayload().toString(),Message.class);
Timestamp now = new Timestamp(System.currentTimeMillis());
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
msg.setMessagedate(sdf.format(now));
// System.out.println(msg);
//将信息保存至数据库
youandmeService.addMessage(msg);
//发送Socket信息
sendMessageToUser(msg.getToid(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
}
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
}
/**
* 在此刷新页面就相当于断开WebSocket连接,原本在静态变量userSocketSessionMap中的
* WebSocketSession会变成关闭状态(close),但是刷新后的第二次连接服务器创建的
* 新WebSocketSession(open状态)又不会加入到userSocketSessionMap中,所以这样就无法发送消息
* 因此应当在关闭连接这个切面增加去除userSocketSessionMap中当前处于close状态的WebSocketSession,
* 让新创建的WebSocketSession(open状态)可以加入到userSocketSessionMap中
* @param webSocketSession
* @param closeStatus
* @throws Exception
*/
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
// System.out.println("WebSocket:"+webSocketSession.getAttributes().get("uid")+"close connection");
Iterator<Map.Entry<String,WebSocketSession>> iterator = userSocketSessionMap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String,WebSocketSession> entry = iterator.next();
if(entry.getValue().getAttributes().get("uid")==webSocketSession.getAttributes().get("uid")){
userSocketSessionMap.remove(webSocketSession.getAttributes().get("uid"));
// System.out.println("WebSocket in staticMap:" + webSocketSession.getAttributes().get("uid") + "removed");
}
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
//发送信息的实现
public void sendMessageToUser(String username, TextMessage message)
throws IOException {
WebSocketSession session = userSocketSessionMap.get(username);
if (session != null && session.isOpen()) {
session.sendMessage(message);
}
}
}
六、配置前端jsp
必须有的
注意:这里的ws地址跟controller的地址差不多,你要配了.action(或.do)就得加
下面的send()函数,是我点击发送触发的函数,一旦有消息来,自动执行websocket.onmessage
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
//这是我本地的,需要自己下
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
<script>
var socketPath = "${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/";
var websocket = null;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://"+socketPath+"websocket/socketServer.action");
}
else if ('MozWebSocket' in window) {
alert(2);
websocket = new MozWebSocket("ws://"+socketPath+"websocket/socketServer.action");
}
else {
alert(3);
websocket = new SockJS("ws://"+socketPath+"sockjs/socketServer.action");
}
websocket.onopen = onOpen;
websocket.onmessage = onMessage;
websocket.onerror = onError;
websocket.onclose = onClose;
function onOpen(event) {
console.log("连接成功");
console.log(event);
}
function onMessage(even) {
var obj = JSON.parse(even.data);
if (obj.fromid=="${who.username}"){
$("#jia").append("<li>"+
"<div class=\"message-data\">"+
"<span class=\"message-data-name\"><i class=\"fa fa-circle online\"></i>${who.name}</span>"+
"<span class=\"message-data-time\">"+ obj.messagedate+"</span>"+
"</div>"+
"<div class=\"message my-message\">"+
obj.messagetext+
"</div>"+
"</li>");
}
}
function onError(event) {
console.log("连接失败");
console.log(event);
}
function onClose(event) {
console.log("Socket连接断开");
console.log(event);
}
function send(me,you){
var data = {};//新建data对象,并规定属性名与相应的值
data['fromid'] = me;
data['toid'] = you;
if ("${wHr}"== "") {
data['fromname'] = "${wUsers.name}";
}
if ("${wUsers}"== "") {
data['fromname'] = "${wHr.name}";
}
data['toname'] = "${who.name}";
data['messagetext'] = $("#message-to-send").val();
// alert("发送");
var now = new Date();
var yyyyhh = now.toLocaleDateString().replace(/\//g, "-") + " " + now.toTimeString().substr(0, 8);
if (websocket.readyState === websocket.OPEN) {
websocket.send(JSON.stringify(data));//调用后台handleTextMessage方法
//给别人发,自己这也得更新
$("#jia").append("<li class='clearfix'>"+
"<div class=\"message-data align-right\">"+
"<span class=\"message-data-name\"><i class=\"fa fa-circle me\"></i>"+data.toname+"</span>"+
"<span class=\"message-data-time\">"+ yyyyhh+"</span>"+
"</div>"+
"<div class=\"message other-message float-right\">"+
data.messagetext+
"</div>"+
"</li>");
document.getElementById("messagediv").scrollTop = document.getElementById("messagediv").scrollHeight;
} else {
alert("连接失败!");
}
}
</script>
七、完整的前端代码
这里我是东拼西凑的 , header-end 之后是对话框主体
${usernameset}是我进这个页面前在controller里session.setAttribute的发过消息的用户名表
${user}是当前登录的用户的用户名
${who}是点击用户名之后,对应的联系人的对象
${list}是点击用户名之后,进入controller,查询与这个人的聊天记录,再回来显示的聊天记录。
我这里用的window.location,其实应该用异步ajax,回来之后再重新刷新聊天框。但我后台里存上request,前端一取就是null,只有这个页面这样,有没有大佬能解释下。ajax版的在后面我注释掉了
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
if ("${msg}" != "") {
alert("${msg}");
}
</script>
<c:remove var="msg"></c:remove>
<title>基于智能推荐的求职招聘系统</title>
<!-- Favicon -->
<link rel="icon" href="${pageContext.request.contextPath}/assets/images/favicon.png" type="image/png" sizes="32x32">
<!-- All CSS -->
<link rel="stylesheet" href="https://www.jq22.com/jquery/bootstrap-4.2.1.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/aos.min.css">
<link rel="stylesheet" href="https://www.jq22.com/jquery/font-awesome.4.7.0.css">
<script src="https://kit.fontawesome.com/b723086348.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script>
<script>
var socketPath = "${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/";
// var webSocket = new WebSocket("ws://"+socketPath+"websocket/socketServer.action");
var websocket = null;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://"+socketPath+"websocket/socketServer.action");
}
else if ('MozWebSocket' in window) {
alert(2);
websocket = new MozWebSocket("ws://"+socketPath+"websocket/socketServer.action");
}
else {
alert(3);
websocket = new SockJS("ws://"+socketPath+"sockjs/socketServer.action");
}
websocket.onopen = onOpen;
websocket.onmessage = onMessage;
websocket.onerror = onError;
websocket.onclose = onClose;
function onOpen(event) {
console.log("连接成功");
console.log(event);
}
function onMessage(even) {
var obj = JSON.parse(even.data);
<%--alert(obj.fromid);--%>
<%--alert("${who.username}");--%>
if (obj.fromid=="${who.username}"){
// alert("要刷");
<%--window.location="${pageContext.request.contextPath}/showmessage/showmessage1.action?your=${who.username}";--%>
$("#jia").append("<li>"+
"<div class=\"message-data\">"+
"<span class=\"message-data-name\"><i class=\"fa fa-circle online\"></i>${who.name}</span>"+
"<span class=\"message-data-time\">"+ obj.messagedate+"</span>"+
"</div>"+
"<div class=\"message my-message\">"+
obj.messagetext+
"</div>"+
"</li>");
}
}
function onError(event) {
console.log("连接失败");
console.log(event);
}
function onClose(event) {
console.log("Socket连接断开");
console.log(event);
}
function send(me,you){
var data = {};//新建data对象,并规定属性名与相应的值
<%--if ("${wUsers}"!== "") {--%>
<%-- data['fromid'] =${wUsers.username};--%>
<%-- data['fromname'] = ${wUsers.name};--%>
<%--}--%>
<%--if ("${wHr}"!== "") {--%>
<%-- data['fromid'] =${wHr.username};--%>
<%-- data['fromname'] = ${wHr.name};--%>
<%--}--%>
data['fromid'] = me;
data['toid'] = you;
if ("${wHr}"== "") {
data['fromname'] = "${wUsers.name}";
}
if ("${wUsers}"== "") {
data['fromname'] = "${wHr.name}";
}
data['toname'] = "${who.name}";
data['messagetext'] = $("#message-to-send").val();
// alert("发送");
var now = new Date();
var yyyyhh = now.toLocaleDateString().replace(/\//g, "-") + " " + now.toTimeString().substr(0, 8);
if (websocket.readyState === websocket.OPEN) {
websocket.send(JSON.stringify(data));//调用后台handleTextMessage方法
$("#jia").append("<li class='clearfix'>"+
"<div class=\"message-data align-right\">"+
"<span class=\"message-data-name\"><i class=\"fa fa-circle me\"></i>"+data.toname+"</span>"+
"<span class=\"message-data-time\">"+ yyyyhh+"</span>"+
"</div>"+
"<div class=\"message other-message float-right\">"+
data.messagetext+
"</div>"+
"</li>");
document.getElementById("messagediv").scrollTop = document.getElementById("messagediv").scrollHeight;
} else {
alert("连接失败!");
}
}
</script>
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/magnific.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/owl.carousel.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/select2.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/slimmenu.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/dist/style.css">
<!-- Google font -->
<link href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700" rel="stylesheet">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
</head>
<body>
<!--header-start -->
<header class="header-area sticky">
<div class="container">
<div class="row">
<div class="col-lg-2">
<div class="logo">
<a href="${pageContext.request.contextPath}/usershowinfo/splitone.action"><img src="${pageContext.request.contextPath}/assets/images/logo.png" alt="image" /></a>
</div>
</div>
<div class="col-lg-10">
<div class="header-container d-flex justify-content-between highlight">
<nav class="highlight">
<ul id="responsive-menu" class="slimmenu">
<li class="nav-item"><a class="nav-link" href="${pageContext.request.contextPath}/usershowinfo/splitone.action">主页</a>
<li id="userlist" class="nav-item">
<a class="nav-link" href="#">我的</a>
<ul>
<li><a href="${pageContext.request.contextPath}/toView/user/addinfo.action">消息</a>
<li><a onclick="logoff()" href="">退出登录</a>
</ul>
<li id="hrlist" class="nav-item">
<a class="nav-link" href="#">我的</a>
<ul>
<li><a href="${pageContext.request.contextPath}/toView/user/addinfo.action">新增招聘信息</a>
<li><a href="${pageContext.request.contextPath}/toView/user/addinfo.action">管理招聘信息</a>
<li><a href="${pageContext.request.contextPath}/toView/user/addinfo.action">消息</a>
<li><a onclick="logoff()" href="">退出登录</a>
</ul>
<li id="login" class="nav-item call-to-action"><a href="${pageContext.request.contextPath}/userlogin.jsp">登录</a>
</ul>
</nav>
</div>
</div>
</div>
</div>
</header>
<!--header-end -->
<!-- partial:index.partial.html -->
<div class="container1 clearfix">
<div class="people-list" id="people-list">
<div class="search">
<input type="text" placeholder="search" />
<i class="fa fa-search"></i>
</div>
<ul class="list">
<c:choose>
<c:when test="${usernameset.size()!=0}">
<c:forEach items="${usernameset}" var="p">
<li class="clearfix" >
<a style="display: block;" href="javascript:show('${p}')" >
<img src="/img/t1.png" alt="avatar" />
<div class="about">
<div class="name">${p}</div>
<div class="status">
<i class="fa fa-circle online"></i>
</div>
</div>
</a>
</li>
</c:forEach>
</c:when>
<c:otherwise>
<li class="clearfix">
<img src="/img/t1.png" alt="avatar" />
<div class="about">
<div class="name">Vincent Porter</div>
<div class="status">
<i class="fa fa-circle online"></i> online
</div>
</div>
</li>
<li class="clearfix">
<img src="/img/t2.png" alt="avatar" />
<div class="about">
<div class="name">Aiden Chavez</div>
<div class="status">
<i class="fa fa-circle offline"></i> left 7 mins ago
</div>
</div>
</li>
</c:otherwise>
</c:choose>
</ul>
</div>
<div class="chat">
<div class="chat-header clearfix">
<img src="/img/t1.png" alt="avatar" />
<div class="chat-about">
<div class="chat-with" >${who.name}</div>
<div class="chat-num-messages"></div>
</div>
<i class="fa fa-star"></i>
</div> <!-- end chat-header -->
<div class="chat-history" id="messagediv">
<c:choose>
<c:when test="${list.size()!=0}">
<ul id="jia">
<c:forEach items="${list}" var="p">
<c:if test="${p.fromid == user}">
<li class="clearfix">
<div class="message-data align-right">
<span class="message-data-time" >${p.messagedate}</span>
<span class="message-data-name" >${p.fromname}</span> <i class="fa fa-circle me"></i>
</div>
<div class="message other-message float-right">
${p.messagetext}
</div>
</li>
</c:if>
<c:if test="${p.toid == user}">
<li>
<div class="message-data">
<span class="message-data-name"><i class="fa fa-circle online"></i>${p.fromname}</span>
<span class="message-data-time">${p.messagedate}</span>
</div>
<div class="message my-message">
${p.messagetext}
</div>
</li>
</c:if>
</c:forEach>
</ul>
</c:when>
<c:otherwise>没有信息</c:otherwise>
</c:choose>
</div> <!-- end chat-history -->
<div class="chat-message clearfix">
<textarea name="message-to-send" id="message-to-send" placeholder ="Type your message" rows="3"></textarea>
<i class="fa fa-file-o"></i>
<i class="fa fa-file-image-o"></i>
<button onclick="send('${user}','${who.username}')">发送</button>
</div> <!-- end chat-message -->
</div> <!-- end chat -->
</div> <!-- end container -->
<%-- <script id="message-template" type="text/x-handlebars-template">--%>
<%-- <li class="clearfix">--%>
<%-- <div class="message-data align-right">--%>
<%-- <span class="message-data-time" >{{time}}, Today</span> --%>
<%-- <span class="message-data-name" >Olia</span> <i class="fa fa-circle me"></i>--%>
<%-- </div>--%>
<%-- <div class="message other-message float-right">--%>
<%-- {{messageOutput}}--%>
<%-- </div>--%>
<%-- </li>--%>
<%-- </script>--%>
<%-- <script id="message-response-template" type="text/x-handlebars-template">--%>
<%-- <li>--%>
<%-- <div class="message-data">--%>
<%-- <span class="message-data-name"><i class="fa fa-circle online"></i> Vincent</span>--%>
<%-- <span class="message-data-time">{{time}}, Today</span>--%>
<%-- </div>--%>
<%-- <div class="message my-message">--%>
<%-- {{response}}--%>
<%-- </div>--%>
<%-- </li>--%>
<%-- </script>--%>
<!--footer-area-start -->
<footer>
<div class="footer-area pt-100 pb-100 clearfix minus-30">
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-6">
<div class="footer-widget">
<div class="widget-title">
<a href="${pageContext.request.contextPath}/toVeiw/user/index.action"><img src="${pageContext.request.contextPath}/assets/images/footer-logo.png" alt="image" /></a>
</div>
<p>Cras semper auctor neque vitae tempus quam pellentesque nec nam aliquam sem et tortor consequat id porta nibh venenatis cras sed felis eget </p>
<div class="social-link mt-4">
<ul>
<li class="facebook"><a href="#"><i class="fa fa-facebook-f"></i></a></li>
<li class="twitter"><a href="#"><i class="fa fa-twitter"></i></a></li>
<li class="linkedin"><a href="#"><i class="fa fa-linkedin" ></i></a></li>
</ul>
</div>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-6">
<div class="footer-widget">
<div class="widget-title">
<h3>Candidates</h3>
</div>
<div class="widget-link">
<ul>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Browse Jobs</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Submit Resume</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>My Bookmarks</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Job Alerts</a></li>
</ul>
</div>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-6">
<div class="footer-widget">
<div class="widget-title">
<h3>Employers</h3>
</div>
<div class="widget-link">
<ul>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Employers</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Add Job</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Jobs Listing</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Employers Grid</a></li>
<li><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>Employer Listing</a></li>
</ul>
</div>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-6">
<div class="footer-widget">
<div class="widget-title">
<h3>Subscribe Us</h3>
</div>
<div class="widget-text">
<form action="#">
<input type="email" placeholder="Your Email" />
<button type="submit" class="buttonfx curtainup">Subscribe</button>
</form>
<p>Nceptos, nulla dictumst neque nam aliquam</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer-bottom-area clearfix">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="footer-bottom text-center">
<p>© Copyright - 2022 hrh - Designed By <a href="http://www.baidu.com/">胡荣华</a></p>
</div>
</div>
</div>
</div>
</div>
</footer>
<!--footer-area-end -->
<!-- ====================ALL JS FILE HERE===================================== -->
<!-- jQuery -->
<script src="${pageContext.request.contextPath}/assets/js/modules/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/proper.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/jquery.waypoints.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/owl.carousel.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/magnific.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/typing.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/select2.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/aos.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/modules/slimmenu.min.js"></script>
<%-- <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>--%>
<script src='${pageContext.request.contextPath}/dist/handlebars.min.js'></script>
<script src='${pageContext.request.contextPath}/dist/list.min.js'></script>
<script src="${pageContext.request.contextPath}/dist/script.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/app.js"></script>
</body>
<script type="text/javascript">
<%--function showmessage(your){--%>
<%-- $.ajax({--%>
<%-- url:"${pageContext.request.contextPath}/showmessage/showmessage1.action",--%>
<%-- data:{'your':your},--%>
<%-- type :"post",--%>
<%-- success:function (){--%>
<%-- alert("哈");--%>
<%-- alert("${list.size()}")--%>
<%-- $("#messagediv").load("${pageContext.request.contextPath}/user/contact.action #messagediv");--%>
<%-- }--%>
<%-- })--%>
<%--}--%>
</script>
<script>
function show(username){
window.location="${pageContext.request.contextPath}/showmessage/showmessage1.action?your="+username;
}
if ("${wHr}"== ""){
document.getElementById("hrlist").style.display="none";
}
if ("${wUsers}"== ""){
document.getElementById("userlist").style.display="none";
}
if ("${wHr}"!= ""||"${wUsers}"!= ""){
document.getElementById("login").style.display="none";
}
function logoff(){
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/user/logoff.action",
async : false,
success:function (){
alert("退出登录成功");
location.href="${pageContext.request.contextPath}/userlogin.jsp";
}
})
}
</script>
</html>
八、对话框运行展示
因为是东拼西凑的,我一点也不懂前端,所以这个上面总是挡
九、其他问题
像编写controller,service,pojo(entity),mapper这些问题就不再赘述了。
再多说一个:message按时间升序取,数据库新手不建议用Timestamp,用varchar就行了
希望有大佬能帮我解答:ajax异步跳controller,controller里sission存东西,回ajax取不出(之前存的都在,就是新存的el表达式一取就是null)