首先,websocket要求是spring4.0以上,网上你找spring redis的例子的话,它配的是spring3.0,要是你把spring-websocket和spring-redis-data结合的话要是版本不一致会出问题。
主要是spring-bean,spring-context,与spring-websocket,spring-redis-data匹配问题造成的。
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.0modelVersion>
<groupId>org.springframework.samples.service.servicegroupId>
<artifactId>online_qqartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<java.version>1.6java.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<jsp.version>2.2jsp.version>
<jstl.version>1.2jstl.version>
<servlet.version>2.5servlet.version>
<spring-framework.version>3.2.3.RELEASEspring-framework.version>
<hibernate.version>4.2.1.Finalhibernate.version>
<logback.version>1.0.13logback.version>
<slf4j.version>1.7.5slf4j.version>
<junit.version>4.11junit.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-expressionartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-messagingartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-websocketartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>4.0.6.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
<version>1.6.6.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<version>${jstl.version}version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>${servlet.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>${jsp.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring-framework.version}version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>${slf4j.version}version>
<scope>compilescope>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>${logback.version}version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
<version>2.4.2version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring-framework.version}version>
<scope>testscope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
<scope>testscope>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.8.0version>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-mapper-aslartifactId>
<version>1.9.13version>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-core-aslartifactId>
<version>1.9.13version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.5.0version>
dependency>
<dependency>
<groupId>org.jsongroupId>
<artifactId>jsonartifactId>
<version>20160212version>
dependency>
<dependency>
<groupId>net.sf.json-libgroupId>
<artifactId>json-libartifactId>
<version>2.4version>
<classifier>jdk15classifier>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>2.0.2version>
<configuration>
<source>1.7source>
<target>1.7target>
<encoding>utf8encoding>
configuration>
plugin>
plugins>
build>
project>
依赖的插件截图
spring的application-config.xml配置
<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:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
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">
<context:component-scan base-package="com.hainan.cs"/>
<context:property-placeholder location="classpath:redis.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:pool-config-ref="poolConfig" p:password="${redis.pass}"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
bean>
<bean id="userDao" class="com.hainan.cs.dao.UserDaoImp">bean>
beans>
redis连接设置redis.properties,当然不在这里面写,直接在application-config中写配置信息也是可以的。redis有桌面编辑软件,redis desktop manager
# Redis settings
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
springmvc配置 mvc-config.xml配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
<context:component-scan base-package="com.hainan.cs"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
bean>
beans>
web.xml配置
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>online_qqdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring/application-config.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/mvc-config.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
redis操作部分主要管用户的注册,登陆,好友搜索,好友添加等
RedisGeneratorDao.java
package com.hainan.cs.dao;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
public class RedisGeneratorDao<k extends Serializable, v extends Serializable> {
@Autowired
protected RedisTemplate redisTemplate;
public void setRedisTemplate(RedisTemplate redisTemplate){
this.redisTemplate=redisTemplate;
}
protected RedisSerializer getRedisSerializer(){
return redisTemplate.getStringSerializer();
}
}
@Autowired 和@Resource都是依赖注入的方式,当然也可以使用
ClassPathXmlApplicationContext context=new ClassPaxthXmlApplicationContext("application-config.xml");
UserDaoImp udi=context.getBean(UserDaoImp.class);
来获取spring容器中的对象。
UserDaoImp.java
package com.hainan.cs.dao;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Repository;
import com.hainan.cs.bean.User;
@Repository(value="userDao")
public class UserDaoImp extends RedisGeneratorDao implements UserDao{
//添加user Hash hsetNX
@Override
public boolean addUser(final User user){
boolean result=redisTemplate.execute(new RedisCallback(){
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer=getRedisSerializer();
byte[] key=serializer.serialize(user.getId());
byte[] name=serializer.serialize("name");
byte[] namea=serializer.serialize(user.getUsername());
byte[] passworda=serializer.serialize(user.getPassword());
byte[] password=serializer.serialize("password");
byte[] email=serializer.serialize("email");
byte[] emaila=serializer.serialize(user.getEmial());
byte[] phone=serializer.serialize("phone");
byte[] phonea=serializer.serialize(user.getPhone());
byte[] address=serializer.serialize("address");
byte[] addressa=serializer.serialize(user.getAdress());
connection.hSetNX(key, name,namea);//hash类型的提交
connection.hSetNX(key, password, passworda);
connection.hSetNX(key, email, emaila);
connection.hSetNX(key, phone, phonea);
connection.hSetNX(key, address, addressa);
return true;
}
});
return result;
}
//获取用户信息
public Map getUser(String userid){
BoundHashOperations bhops=redisTemplate.boundHashOps(userid);
return bhops.entries();
}
//添加用户好友
@Override
public void addFriends(final String userid, final String friendid, final String group){
Boolean result=redisTemplate.execute(new RedisCallback(){
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer=redisTemplate.getStringSerializer();
String key="friend"+userid;
byte[] fkey=serializer.serialize(key);
byte[] ffriendid=serializer.serialize(friendid);
byte[] fgroup=serializer.serialize(group);
Boolean r= connection.hSet(fkey, ffriendid, fgroup);
return r;
}
});
}
//删除用户好友
@Override
public void deleteFriend(User user, String friendsid){
BoundHashOperations bhops=redisTemplate.boundHashOps("friend"+user.getId());
bhops.delete(friendsid);
}
//添加用户好友组
@Override
public void addFriendsGroup(final User user, final String group){
redisTemplate.execute(new RedisCallback(){
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer=redisTemplate.getStringSerializer();
byte[] key=serializer.serialize("group"+user.getId());
byte[] value=serializer.serialize(group);
connection.lPush(key, value);
return true;
}
});
}
//添加用户的列表的hashmap
@Override
public void addUserToList(final String key,final String userid,final String username){
redisTemplate.execute(new RedisCallback(){
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer=getRedisSerializer();
byte[] a=serializer.serialize(key);
byte[] c=serializer.serialize(userid);
byte[] b=serializer.serialize(username);
connection.hSet(a, c, b);
return true;
}
});
}
//获取用户列表
public Map getUserList(){
BoundHashOperations hlops=redisTemplate.boundHashOps("userlist");
return hlops.entries();
}
//删除对象
@Override
public void deleteUser(String userid){
redisTemplate.delete(userid);
}
//删除hash中的一条记录
@Override
public void deleteUserFromList(String key,String id){
BoundHashOperations bhops=redisTemplate.boundHashOps(key);
bhops.delete(id);
}
//获取用户的好友分组
public List getFriendGroups(String userid){
BoundListOperations blops=redisTemplate.boundListOps("group"+userid);
System.out.println(userid);
return blops.range(0, blops.size());
}
//获取用户的好友列表
public Map getFriends(String userid){
BoundHashOperations bhops=redisTemplate.boundHashOps("friend"+userid);
return bhops.entries();
}
//测试
public static void main(String args[]){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring/application-config.xml");
UserDaoImp udi=context.getBean(UserDaoImp.class);
User u=new User();
String id=UUID.randomUUID().toString();//自动生成一个id
u.setId(id);
u.setUsername("zhangsan");
u.setPassword("123456");
u.setEmial("[email protected]");
u.setPhone("234556");
u.setAdress("china haikou");
udi.addUser(u);
udi.addUserToList("userlist", id, "zhangsan");
context.close();
}
}
主要管,用户向指定好用发送消息,消息之间的同步
ChatConfig.java
package com.hainan.cs.websocket;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
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;
@Component
@EnableWebSocket
public class ChatConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
@Resource
private ChatHandler handler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addHandler(handler, "/ws").addInterceptors(new ChatHandShake());
}
}
ChatHandler.java
package com.hainan.cs.websocket;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import net.sf.json.JSONObject;
@Component
public class ChatHandler implements WebSocketHandler{
private Map usermap=new HashMap();
//连接关闭后的操作
@Override
public void afterConnectionClosed(WebSocketSession wsession, CloseStatus status) throws Exception {
System.out.println("用户"+wsession.getAttributes().get("username")+"已经关闭");
for(Map.Entryentry:usermap.entrySet()){
String key=entry.getKey();
WebSocketSession value=entry.getValue();
if(key.equals(wsession.getAttributes().get("username"))){
usermap.remove(key);
System.out.println("用户"+key+"已经移除");
}
}
}
//再handshake建立连接后,username存到map中了,wsession怎么拿到的map的值
@Override
public void afterConnectionEstablished(WebSocketSession wsession) throws Exception {
String uname=(String) wsession.getAttributes().get("username");
System.out.println("用户"+uname+"已经加入");
if(usermap.get(uname)==null){
usermap.put(uname, wsession);
}
}
// message 是前台传过来的json数据,包括用户名,和发送的消息,要将消息转发给所有的其他用户,重新转发的话message格式和原来是一样的
@Override
public void handleMessage(WebSocketSession wsession, WebSocketMessage> message) throws Exception {
//TextMessage tm=new TextMessage(message.toString());
System.out.println("开始发送消息"+usermap.size());
//这是json字符串
String jm=message.getPayload().toString();
JSONObject json=JSONObject.fromObject(jm);
System.out.println(jm);
System.out.println(json.get("to"));
for(Map.Entryentry:usermap.entrySet()){
String key=entry.getKey();
WebSocketSession value=entry.getValue();
//给指定的好友发消息
if(key.equals(json.get("to"))){
if(value!=null&&value.isOpen()){
value.sendMessage(message);
}
}
}
}
@Override
public void handleTransportError(WebSocketSession wsession, Throwable th) throws Exception {
if(wsession.isOpen()){
wsession.close();
}
for(Map.Entryentry:usermap.entrySet()){
String key=entry.getKey();
WebSocketSession value=entry.getValue();
if(key.equals(wsession.getAttributes().get("username"))){
usermap.remove(key);
System.out.println("传输出错!用户"+key+"已经移除");
}
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
ChatHandShake.java
package com.hainan.cs.websocket;
import java.util.Map;
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;
//一开始页面打开时建立连接,建立完后就没他的事了,之后就交给handler了
public class ChatHandShake implements HandshakeInterceptor{
@Override
public void afterHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2, Exception arg3) {
// TODO Auto-generated method stub
}
//request可以获取页面请求对象的值
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handlar,
Map<String, Object> map) throws Exception {
//getParamater是从这ws://localhost:8080/online_qq/ws?username="+name获取的“username”,
//我就不懂了为啥用getAttribute获取不到${username}显示的值,照理说这应该在request对象中的
System.out.println("用户"+((ServletServerHttpRequest) request).
getServletRequest().getParameter("username")+"已经建立连接");//这里可以获取前台传递的值
if(request instanceof ServletServerHttpRequest){
ServletServerHttpRequest srequest=(ServletServerHttpRequest)request;
if(srequest.getServletRequest().getParameter("username")!=null){
//页面传递的值在session中,把它存储到map中传给handler处理
map.put("username", srequest.getServletRequest().getParameter("username"));
}else {
return false;
}
}
return true;
}
}
home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="${pageContext.request.contextPath}/resources/layoutit/src/css/bootstrap.min.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/resources/layoutit/src/css/style.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/resources/layoutit/src/js/jquery.min.js">script>
<script src="${pageContext.request.contextPath}/resources/layoutit/src/js/bootstrap.min.js">script>
<title>Online QQtitle>
head>
<body>
<script type="text/javascript">
var name="${username}";
var websocket;
if('WebSocket' in window){
websocket=new WebSocket("ws://localhost:8080/online_qq/ws?username="+name);
}
websocket.onopen = function(event) {
console.log("WebSocket:已连接");
console.log(event);
};
websocket.onmessage = function(event) {
var data=JSON.parse(event.data);
console.log("WebSocket:收到一条消息",data);
$("#chatcontent").append(""
+data.username+":"
+data.msg+"");
};
websocket.onerror = function(event) {
console.log("WebSocket:发生错误 ");
console.log(event);
};
websocket.onclose = function(event) {
console.log("WebSocket:已关闭");
console.log(event);
}
function send(){
var message=$("#message").val();
var data={};
data["username"]="${username}";
data["msg"]=message;
//to是发送消息的目标
data["to"]=to;
$("#chatcontent").append(""
+'${username}'+":"
+message+"");
websocket.send(JSON.stringify(data));
}
script>
<script>
$(document).ready(function(){
$("#chatwindow").hide();
$("#searchinformation").hide();
});
script>
<div class="container-fluid">
<div class="row" style="background-color:#22DDDD">
<div class="col-md-2">
div>
<div class="col-md-8" style="margin-top:50px">
<div class="row">
<div class="col-md-3">
<div class="row">
<div class="col-md-12" style="height:150px ; background-color:#F7F7B3">
<h3 style="text-align:center">${username }h3>
div>
div>
<div class="row" style="background-color:#EAF3EA">
<br>
<div class="col-md-6">
<button type="button" class="btn btn-block btn-success" onclick="friends()">
好友列表
button>
div>
<script>
function friends(){
$.ajax({
url:"${pageContext.request.contextPath}/home/friends",
type:"POST",
dataType:"json",
success:function(data){
//alert(data.reply);
var content="";
var group=data.group;//这是一个好友分组的列表
var friends=data.friends;//这是所有好友的map<好友的姓名,好友的分组>
for(var i=0;i""
+group[i]+"";
for(var key in friends){
if(friends[key]==group[i]){
content=content+"";
//content=content+"";
//这种是错误的
}
}
}
$("#fcontent").html(content);
},
error:function(data){
alert("error");
}
});
}
var to;
function chat(key){
to=key;
$("#chatwindow").show();
$("#searchinformation").hide();
$("#showfname").html(key);
}
script>
<div class="col-md-6">
<button type="button" class="btn btn-block btn-success">
消息列表
button>
div>
div>
<div class="row" style="height:596px;background-color:#EAF3EA" >
<div class="col-md-12" >
<div class="row" id="fcontent" style="margin-left:7px;margin-right:7px">
div>
div>
div>
<div class="row" style="background-color:#EAF3EA">
<div class="col-md-12">
<div class="col-sm-8">
<input class="form-control" type="text" id="friendname"/>
div>
<div class="col-sm-4">
<button type="button" class="btn btn-default" onclick="search()">搜索好友button>
div>
div>
<br><br><br><br>
div>
<script>
function search(){
$.ajax({
data:"friendname="+$("#friendname").val(),
dataType:"json",
url:"${pageContext.request.contextPath}/home/search",
type:"POST",
success:function(data){
if(data.result=="exist"){
var content="姓名:"+data.name+"邮箱:"+data.email+"电话:"+data.phone+"地址:"
+data.address+"+data.name+"\">添加好友";
$("#searchinformation").show();
$("#chatwindow").hide();
$("#searchinformation").html(content);
}
if(data.result=="notexist"){
$("#searchinformation").show();
$("#chatwindow").hide();
$("#searchinformation").html("no such user name.");
}
},
error:function(data){
alert("error");
}
});
}
script>
div>
<div class="col-md-9">
<div class="row" id="chatwindow" style="background-color:#D6F5DC">
<div class="row" >
<div class="col-md-12">
<h4 style="text-align:center" id="showfname">h4>
<hr color="balck"/>
div>
div>
<div class="row" >
<div class="col-md-12" style="height:750px;margin-left:30px" id="chatcontent">
div>
div>
<div class="row">
<div class="col-md-12">
<div class="col-sm-9">
<input class="form-control" type="text" id="message"/>
div>
<div class="col-sm-3">
<button type="button" class="btn btn-default" onclick="send()">提交button>
div>
div>
<br><br><br>
div>
div>
<div class="row" style="background-color:#D6F5DC">
<div class="row" id="searchinformation" style="margin-left:50px;margin-top:50px">
div>
div>
div>
div>
div>
<div class="col-md-2">
div>
<div class="col-md-12">
<br><br>
<p class="text-center">
copyright ©UML Analyzer 2015 ICP 15003200 <a href="http://www.hainu.edu.cn/">Hainan Universitya>
| Designed by Huang Liang
p>
div>
div>
div>
body>
html>
https://github.com/huangliang992/online_qq