spring websocket开发

散装、总体介绍

品种背景

欠类型是通信软件开发实训课程的同一宗功课,要求就一个拉系统,但要求发生起码一个长,无论是功能及之还是技术上的。
咱小组于善于Java Web开发,因此决定在技术上做一个长,使用WebSocket

文档说明

拖欠文档按照如下顺序进行介绍

  1. 技术背景
    介绍该档要用到之有背景知识
  2. 色目录结构
    该项目应用myeclipse的Java EE项目,大体上只是分为前台和后台
  3. 列框架搭建
    介绍前台用到的技艺,以及后台框架的搭建
  4. 种类成果显示
  5. 代码分享

一致、技术背景

1.WebSocket

WebSocket是HTML5从头提供的平栽于单个 TCP
连接上进行全双工通讯的协商。WebSocket通讯协议为2011年吃IETF一定为规范RFC
6455,WebSocketAPI被W3C定为标准。
每当WebSocket
API中,浏览器与服务器就待举行一个握手的动作,然后,浏览器与服务器之间就形成了同样漫漫快速通道。两者之间就一直可以数交互传送。

2.Spring

Spring是一个开源轻量级的框架,使用控制反转(IoC)和面向切面(AOP),它好吃开发变得简单、轻便、快速与更灵敏。

3.Spring WebSocket

Spring从4.0开端进入了spring-websocket这个模块,并能够全面支持WebSocket,它同Java
WebSocket API标准(JSR-356)保持一致,同时提供了额外的劳务。

4.Spring MVC

Spring
MVC是一个model-view-controller(MVC)框架,能好好地拿数据、业务及见进行分离。Spring
MVC的规划是环绕DispatcherServlet展开的,DispatcherServlet负责用请求派发到一定的handler。

5.MyBatis

MyBatis 是支持定制化
SQL、存储过程与高档映射的好好的持久层框架。MyBatis 避免了几有的
JDBC 代码和手动设置参数和取得结果集。MyBatis
可以本着配置以及原生Map使用简便的 XML 或注解,将接口和 Java 的 POJOs(Plain
Old Java Objects,普通的 Java对象)映射成数据库被的记录。

每当随档面临,我们下了以上几乎个框架进行搭建。

第二、目录结构

  • Com.tx.
    Config websocket配置文件
    Controller spring mvc 控制层
    DAO 数据库连接操作
    Handler websocket操作
    Model 数据实体
    Service 服务器处理
    Tool 工具类

  • Webroot
    前台代码目录
    Js javascript代码
    Style css代码
    Test 前台测试代码

  • WEN-INF 配置文件夹
    Jsp jsp文件夹
    Lib 项目所需要的表jar包
    As-servlet.xml spring mvc 配置文件
    Web.xml web项目安排文件

目录结构

其三、实验步骤

web服务前端

1、socket相关代码结构

var socket = new Socket(url);//url必须为ws://开头的相关协议
socket.onopen = function(event){
    //连接初始化代码
};
sokcet.onmessage = function(event){
    var text = event.data;
    //处理接受到的消息
};
socket.onclose = function(event){
    //连接关闭时触发
};
socket.onerror = function(event){
    //连接过程中出错时触发
}

2.此次实验所封装的局部函数的分析

  1. 信息封装函数,用于生成能直接抬高到html的dom节点的文档类型

function messagePackage(message) {
    /*
     message{
     userName : xx,
     timeSign : 22:12:44,
     content : abc
     }
     */
    var element_section = $("<section></section>");
    var element_section_p1 = $("<p></p>");
    var element_section_p1_user = $("");
    var element_section_p1_time = $("<time></time>");
    var element_section_p2_content = $("<p></p>");
    element_section.addClass("message");
    element_section_p1.addClass("header");
    element_section_p2_content.addClass("content");
    element_section_p1_user.text(message.username);
    element_section_p1_time.text(message.timeSign);
    element_section_p2_content.text(message.content);
    element_section_p1.append(element_section_p1_user);
    element_section_p1.append(element_section_p1_time);
    element_section.append(element_section_p1);
    element_section.append(element_section_p2_content);
    return element_section;
}
  1. 信息处理函数,用于拍卖onmessage中出于服务器发送到客户端的音,并规定了音信类型及有关的处理方式

/*
jsonData : {
    type:1(聊天信息)||2(用户列表更新信息),
    username(1,2):xx,
    timeSign(1):xx:xx:xx,
    content(1):xxxxxxxxxxxxx,
}
 */
function messageHandle(event) {
    var jsonStr = event.data;
    var data = JSON.parse(jsonStr);
    var $message = null;
    switch(data.type) {
        //更新聊天显示框
        case 1:
            if(data.username == currentUser) return;
            $message = messagePackage({
               username : data.username,
                timeSign : data.timeSign,
                content : data.content
            });
            $show.append($message);
            //让滚动条自动滚到底
            $show.get(0).scrollTop = $show.get(0).scrollHeight;
            break;
        //向已经在线的用户发送用户列表更新信息
        case 2:
            var $userName = $("<p></p>");
            $userName.text(data.username);
            $("#usersInfo").append($userName);

            break;
        //将所有已经在线的用户信息发送给刚加入的用户
        case 3:
            var usernames = data.usernames;
            var $usersInfo = $("#usersInfo");
            $usersInfo.empty();
            for(var i= 0,len=usernames.length;i<len;i++) {
                var $userName = $("<p></p>");
                $userName.text(usernames[i]);
                $usersInfo.append($userName);
            }
            break;
        //删除用户信息
        case 4:
            var $usersInfo = $("#usersInfo");
            $usersInfo.find(":contains("+data.username+")").remove();
    }
}

Spring & Spring MVC配置

1、Web.xml 配置

配置spring 过滤器 并设置UTF-8编码

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
</filter>
<filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

配备servlet spring mvc拦截器 设置匹配后缀名为.do

    <display-name>as</display-name>
    <servlet>
        <servlet-name>as</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>as</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

2.as-servlet.xml 配置Spring MVC

行使Spring注解的主意

<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.tx.*" />

<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />

返回json模板

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
        </list>
    </property>
</bean>

设置spring mvc视图

<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
</bean>

3.编写Spring MVC controller

controller用于收纳及发送前后台的呼吁与应
内外台定义用来传送的json字符串

聊天消息:
'{"type":1,"username":"xxxx","timeSign":"15:21:02","content":"消息内容"}'
用户列表更新消息(已加入):
'{"type":2,"username":"xxxx"}'

用户列表全部消息(刚加入):
'{"type":3,"usernames":["a","b","c"]}'

用户列表某用户信息删除 :
{"type":4,"username":"xx"}

本例以用户登录、注册也例,其余部分请参考页面最下方提供的源代码
此以了Spring MVC注解来开展呼吁的拍卖

例:

@RequestMapping里头填写的是央的地方
return 根据返回值的不等进行页面跳转等操作,这里归 login
表示过反至 login.jsp 这个页面

@RequestMapping(“login.do”)
public String gtLogin() {
return “login”;
}

```java
@Controller
public class MainController {

    @RequestMapping("register.do")
    public String gtRegister() {
        return "register";
    }

    @RequestMapping("login.do")
    public String gtLogin() {
        return "login";
    }

    @RequestMapping("loginServer.do")
    public ModelAndView login(@RequestParam("username") String username,
            @RequestParam("password") String password) {

        ModelAndView modelAndView = new ModelAndView();
        StudentService ss = new StudentService();
        boolean r = ss.login(username, password);
        if (r) {
             modelAndView.addObject("name", username);
             modelAndView.setViewName("chat");
        } else {
            modelAndView.setViewName("login");
        }
        return modelAndView;
    }

    @RequestMapping(value = "registerServer.do", method = RequestMethod.POST)
    public ModelAndView gtRegister(@RequestParam("username") String username,
            @RequestParam("password") String password) {
        StudentService ss = new StudentService();
        ModelAndView modelAndView = new ModelAndView();  
        boolean r = ss.register(username, password);
        if (r) {
             modelAndView.addObject("name", username);  
             modelAndView.setViewName("chat");  
        } else {
            modelAndView.setViewName("login");  
        }
        return modelAndView;
    }

}

Mybatis配置

关于mybatis的现实使用说明可以参考
mybatis文档

1.确立及数码库表对应之model,POJO类

此间才为Student.java类来说明:
好像名同数据库被的表名一致,变量名同同数据库被之字段名相同,并编写get()和set()方法

package com.tx.model;

public class Student {
    private int id;
    private String name;
    private String password;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

2.mybatis-config.xml设置

咱们使用xml来对mybatis数据库进行配备,里面包括:

  • driver: 数据库驱动程序
  • url: 数据库连接地址和数量库名
  • username:数据库连接用户称
  • password:数据库连接密码

  • xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/chat"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
      </dataSource>
    </environment>
  </environments>

  <mappers>
    <mapper resource="com/tx/model/mapping.xml"/>
  </mappers>

</configuration>

3.mapping.xml设置

mybatis的映射表,通过描写sql语句来拓展询问

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tx.model.Mapper">

    <!-- 通过username获得密码 -->
    <select id="getpwd" parameterType="String" resultType="String">
      select stuPassword from student where stuName=#{stuName}
    </select>

    <insert id="register" parameterType="String">
        insert into student (stuName, stuPassword) values (#{stuName}, #{stuPassword}) 
    </insert>

</mapper>

DAO层代码

mybatis的投射文件,方法名及xml中之id相同

package com.tx.model;

import org.apache.ibatis.annotations.Param;

public interface Mapper {

    public String getpwd(String stuName);
    public int register(@Param("stuName")String stuName, @Param("stuPassword")String stuPassword);
}

DAO层,调用Mybatis的Mapper接口

package com.tx.DAO;

import org.apache.ibatis.session.SqlSession;

import com.tx.model.Mapper;
import com.tx.tools.Helper;

public class StudentDAO {
    SqlSession session = Helper.getSessionFactory().openSession();
    Mapper mapper = session.getMapper(Mapper.class);

    public String getpwd(String username){
        return mapper.getpwd(username);
    }

    public int register(String name, String password) {
        int result = 0;
        SqlSession session = Helper.getSessionFactory().openSession();
        try {
            Mapper mapper = session.getMapper(Mapper.class);
            result = mapper.register(name, password);
            session.commit();
        } finally {
            session.close();
        }
        return result;
    }
}

service层代码

service层调用DAO层

package com.tx.service;

import com.tx.DAO.StudentDAO;

public class StudentService {

    StudentDAO sdao = new StudentDAO();

    public boolean login(String name, String password) {
        boolean result = false;
        if (password.equals(sdao.getpwd(name))) {
            result = true;
        }
        return result;
    }

    public boolean register(String name, String password) {
        if(sdao.register(name, password) == 1) {
            return true;
        } else {
            return false;
        }
    }
}

Spring websocket配置

1.WebSocketConfigurer设置

注册Spring WebSocket服务

其中registerWebSocketHandlers方法:
registry.addHandler(systemWebSocketHandler(),”xxx”);
xxx填写准备用的WebSocket服务器请求地址,本档面临坐
webSocketServer.do 为条例

package com.tx.config;

import org.springframework.context.annotation.Bean;
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.WebSocketHandler;
import org.springframework.web.socket.client.standard.WebSocketContainerFactoryBean;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import com.tx.handler.SystemWebSocketHandler;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
         registry.addHandler(systemWebSocketHandler(),"webSocketServer.do");
    }

    @Bean
    public WebSocketHandler systemWebSocketHandler(){
        return new SystemWebSocketHandler();
    }

    @Bean
    public WebSocketContainerFactoryBean createWebSocketContainer() {
        WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
        container.setMaxTextMessageBufferSize(8192);
        container.setMaxBinaryMessageBufferSize(8192);
        return container;
    }
}

2.WebSocketHandler设置

服务器如何处理WebSocket请求于当下其中填写

成功建立连接
接到至信息处理
拍卖非常
老是关闭后

public class SystemWebSocketHandler implements WebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        System.out.println("ConnectionEstablished");
        //TODO
    }

    @Override
    public void handleMessage(WebSocketSession session,
            WebSocketMessage<?> message) throws Exception {
        //TODO
    }

    @Override
    public void handleTransportError(WebSocketSession session,
            Throwable exception) throws Exception {
        //TODO
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session,
            CloseStatus closeStatus) throws Exception {
        System.out.println("ConnectionClosed");
        //TODO
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}

季、运行结果

用户注册

于浏览器中输入
http://localhost:8080/RealTimeChat/register.do

注册界面

填写用户名及密码后,点击注册按钮
挂号成功后,自动跳反至聊天页面

聊天界面

聊天界面1

顶部也当下登录用户
左上方为聊天室的闲话窗口
右上为目前聊天室所有的在线用户
尘世为用户之输入窗口

报到界面

初用户登录
http://localhost:8080/RealTimeChat/login.do

登录界面

差不多总人口聊天

新用户进入

chat2

用户退

kyle用户退

logout

五、项目代码

github项目地址

网站地图xml地图