基于Springboot和WebScoket寫的一個(gè)在線聊天小程序

基于Springboot和WebScoket寫的一個(gè)在線聊天小程序

(好幾天沒有寫東西了盔夜,也沒有去練手了怎燥,就看了看這個(gè)瘫筐。。铐姚。)

6

項(xiàng)目說明

  • 此項(xiàng)目為一個(gè)聊天的小demo策肝,采用springboot+websocket+vue開發(fā)肛捍。
  • 其中有一個(gè)接口為添加好友接口,添加好友會(huì)判斷是否已經(jīng)是好友之众。
  • 聊天的時(shí)候:A給B發(fā)送消息如果B的聊天窗口不是A拙毫,則B處會(huì)提醒A發(fā)來一條消息。
  • 聊天內(nèi)容的輸入框采用layui的富文本編輯器棺禾,目前不支持回車發(fā)送內(nèi)容缀蹄。
  • 聊天可以發(fā)送圖片,圖片默認(rèn)存儲(chǔ)在D:/chat/目錄下膘婶。
  • 點(diǎn)擊聊天內(nèi)容中的圖片會(huì)彈出預(yù)覽缺前,這個(gè)預(yù)覽彈出此條消息中的所有圖片。
  • 在發(fā)送語(yǔ)音的時(shí)候悬襟,語(yǔ)音默認(rèn)發(fā)送給當(dāng)前聊天窗口的用戶衅码,所以錄制語(yǔ)音的時(shí)候務(wù)必保證當(dāng)前聊天窗口有選擇的用戶。
  • 知道用戶的賬號(hào)可以添加好友脊岳,目前是如果賬號(hào)存在逝段,可以直接添加成功

老規(guī)矩,還是先看看小項(xiàng)目的目錄結(jié)構(gòu):

1

一割捅、先引入pom文件

這里就只放了一點(diǎn)點(diǎn)代碼(代碼太長(zhǎng)了)

<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

二奶躯、創(chuàng)建對(duì)應(yīng)的yml配置文件

spring:
  profiles:
    active: prod
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/chat?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=UTC
    driver-class-name: com.mysql.jdbc.Driver
    #指定數(shù)據(jù)源
    type: com.alibaba.druid.pool.DruidDataSource

    # 數(shù)據(jù)源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #   配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計(jì)亿驾,'wall'用于防火墻
    filters: stat,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

  thymeleaf:
    suffix: .html
    prefix:
      classpath: /templates/
    cache: false

  jackson: #返回的日期字段的格式
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false # true 使用時(shí)間戳顯示時(shí)間
  http:
    multipart:
      max-file-size: 1000Mb
      max-request-size: 1000Mb
#配置文件式開發(fā)
mybatis:
  #全局配置文件的位置
  config-location: classpath:mybatis/mybatis-config.xml
  #所有sql映射配置文件的位置
  mapper-locations: classpath:mybatis/mapper/**/*.xml

server:
  session:
    timeout: 7200

三嘹黔、創(chuàng)建實(shí)體類

這里就不再多說了,有Login,Userinfo,ChatMsg,ChatFriends

2

四颊乘、創(chuàng)建對(duì)應(yīng)的mapper(即dao層)還有對(duì)應(yīng)的mapper映射文件

(這里就舉出了一個(gè)参淹,不再多說)

public interface ChatFriendsMapper {
    //查詢所有的好友
    List<ChatFriends> LookUserAllFriends(String userid);
    //插入好友
    void InsertUserFriend(ChatFriends chatFriends);
    //判斷是否加好友
    Integer JustTwoUserIsFriend(ChatFriends chatFriends);
    //查詢用戶的信息
    Userinfo LkUserinfoByUserid(String userid);
}
<?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.chat.mapper.ChatFriendsMapper">
    <select id="LookUserAllFriends" resultType="com.chat.bean.ChatFriends" parameterType="java.lang.String">
      select userid,nickname,uimg from userinfo where userid in (select a.fuserid from chat_friends a where a.userid=#{userid})
    </select>
    <insert id="InsertUserFriend" parameterType="com.chat.bean.ChatFriends">
        insert into chat_friends (userid, fuserid) value (#{userid},#{fuserid})
    </insert>
    <select id="JustTwoUserIsFriend" parameterType="com.chat.bean.ChatFriends" resultType="java.lang.Integer">
        select id from chat_friends where userid=#{userid} and fuserid=#{fuserid}
    </select>
    <select id="LkUserinfoByUserid" parameterType="java.lang.String" resultType="com.chat.bean.Userinfo">
        select * from userinfo where userid=#{userid}
    </select>
</mapper>

五、創(chuàng)建對(duì)應(yīng)的業(yè)務(wù)類(即service)

(同樣的業(yè)務(wù)層這里也就指出一個(gè))

@Service
public class ChatFriendsService {
    @Autowired
    ChatFriendsMapper chatFriendsMapper;
    public List<ChatFriends> LookUserAllFriends(String userid){
        return chatFriendsMapper.LookUserAllFriends(userid);
    }
    public void InsertUserFriend(ChatFriends chatFriends){
        chatFriendsMapper.InsertUserFriend(chatFriends);
    }
    public Integer JustTwoUserIsFriend(ChatFriends chatFriends){
        return chatFriendsMapper.JustTwoUserIsFriend(chatFriends);
    }
    public Userinfo LkUserinfoByUserid(String userid){
        return chatFriendsMapper.LkUserinfoByUserid(userid);
    }
}

六乏悄、創(chuàng)建對(duì)應(yīng)的控制器

這里再說說項(xiàng)目的接口

  1. /chat/upimg
    聊天圖片上傳接口
  2. /chat/lkuser
    這個(gè)接口用來添加好友的時(shí)候:查詢用戶浙值,如果用戶存在返回用戶信息,如果不存在返回不存在
  3. /chat/adduser/
    這個(gè)接口是添加好友接口檩小,會(huì)判斷添加的好友是否是自己开呐,如果添加的好友已經(jīng)存在則直接返回
  4. /chat/ct
    跳轉(zhuǎn)到聊天界面
  5. /chat/lkfriends
    查詢用戶的好友
  6. /chat/lkuschatmsg/
    這個(gè)接口是查詢兩個(gè)用戶之間的聊天信息的接口,傳入用戶的userid规求,查詢當(dāng)前登錄用戶和該用戶的聊天記錄筐付。
  7. /chat/audio
    這個(gè)接口是Ajax上傳web界面js錄制的音頻數(shù)據(jù)用的接口

(同樣就只寫一個(gè))

@Controller
public class LoginCtrl {
    @Autowired
    LoginService loginService;
    @GetMapping("/")
    public String tologin(){
        return "user/login";
    }
    /**
     * 登陸
     * */
    @PostMapping("/justlogin")
    @ResponseBody
    public R login(@RequestBody Login login, HttpSession session){
        login.setPassword(Md5Util.StringInMd5(login.getPassword()));
        String userid = loginService.justLogin(login);
        if(userid==null){
            return R.error().message("賬號(hào)或者密碼錯(cuò)誤");
        }
        session.setAttribute("userid",userid);
        return R.ok().message("登錄成功");
    }
}

七、創(chuàng)建對(duì)應(yīng)的工具類以及自定義異常類

  1. 表情過濾工具類
public class EmojiFilter {
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    @Test
    public void testA(){
        String s = EmojiFilter.filterEmoji("您好??阻肿,你好啊");
        System.out.println(s);
    }

  1. Md5數(shù)據(jù)加密類
   static String[] chars = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

    /**
     * 將普通字符串用md5加密瓦戚,并轉(zhuǎn)化為16進(jìn)制字符串
     * @param str
     * @return
     */
    public static String StringInMd5(String str) {

        // 消息簽名(摘要)
        MessageDigest md5 = null;
        try {
            // 參數(shù)代表的是算法名稱
            md5 = MessageDigest.getInstance("md5");
            byte[] result = md5.digest(str.getBytes());

            StringBuilder sb = new StringBuilder(32);
            // 將結(jié)果轉(zhuǎn)為16進(jìn)制字符  0~9 A~F
            for (int i = 0; i < result.length; i++) {
                // 一個(gè)字節(jié)對(duì)應(yīng)兩個(gè)字符
                byte x = result[i];
                // 取得高位
                int h = 0x0f & (x >>> 4);
                // 取得低位
                int l = 0x0f & x;
                sb.append(chars[h]).append(chars[l]);
            }
            return sb.toString();

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
  1. 測(cè)試數(shù)據(jù)加密類
public class TestUtil {
    @Test
    public void testA(){
        String s = Md5Util.StringInMd5("123456");
        System.out.println(s);
    }
}

八、引入對(duì)應(yīng)的靜態(tài)資源文件(這個(gè)應(yīng)該一開始就做的)

4

九丛塌、自定義一些配置并且注入到容器里面

  1. Druid數(shù)據(jù)源
@Configuration
public class DruidConfig {
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
        return new DruidDataSource();
    }
    //配置Druid的監(jiān)控
    //1.配置要給管理后臺(tái)的Servlet
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        ServletRegistrationBean bean=new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
        Map<String,String> initParams=new HashMap<>();
        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","admin233215");
        initParams.put("allow","");//默認(rèn)允許ip訪問
        initParams.put("deny","");
        bean.setInitParameters(initParams);
        return bean;
    }
    //2.配置一個(gè)監(jiān)控的filter
    @Bean
    public FilterRegistrationBean webStarFilter(){
        FilterRegistrationBean bean=new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());
        Map<String,String> initParams=new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }
}
  1. 靜態(tài)資源以及攔截器
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter {
    //配置一個(gè)靜態(tài)文件的路徑 否則css和js無法使用较解,雖然默認(rèn)的靜態(tài)資源是放在static下畜疾,但是沒有配置里面的文件夾
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
    @Bean
    public WebMvcConfigurerAdapter WebMvcConfigurerAdapter() {
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                //registry.addResourceHandler("/pic/**").addResourceLocations("file:D:/chat/");
                registry.addResourceHandler("/pic/**").addResourceLocations("file:D:/idea_project/SpringBoot/Project/Complete&&Finish/chat/chatmsg/");
                super.addResourceHandlers(registry);
            }
        };
        return adapter;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注冊(cè)TestInterceptor攔截器
        InterceptorRegistration registration = registry.addInterceptor(new AdminInterceptor());
        registration.addPathPatterns("/chat/*");
    }
}
  1. WebSocketConfigScokt通信配置
@Configuration
@EnableWebSocket
public class WebSocketConfig {
 
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

十、進(jìn)行測(cè)試

這是兩個(gè)不同的用戶

7

8

當(dāng)然了印衔,還可以進(jìn)行語(yǔ)音啡捶,添加好友
今天的就寫到這里吧!謝謝奸焙!
這里要提一下我的一個(gè)學(xué)長(zhǎng)的個(gè)人博客瞎暑,當(dāng)然了,還有我的与帆,謝謝

理木客

我的

天涯志

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末了赌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鲤桥,更是在濱河造成了極大的恐慌揍拆,老刑警劉巖渠概,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茶凳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡播揪,警方通過查閱死者的電腦和手機(jī)贮喧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猪狈,“玉大人箱沦,你說我怎么就攤上這事」兔恚” “怎么了谓形?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)疆前。 經(jīng)常有香客問我寒跳,道長(zhǎng),這世上最難降的妖魔是什么竹椒? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任童太,我火速辦了婚禮,結(jié)果婚禮上胸完,老公的妹妹穿的比我還像新娘书释。我一直安慰自己,他們只是感情好赊窥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布爆惧。 她就那樣靜靜地躺著,像睡著了一般锨能。 火紅的嫁衣襯著肌膚如雪扯再。 梳的紋絲不亂的頭發(fā)上肴捉,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音叔收,去河邊找鬼齿穗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饺律,可吹牛的內(nèi)容都是我干的窃页。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼复濒,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼脖卖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起巧颈,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤畦木,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后砸泛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體十籍,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年唇礁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了勾栗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盏筐,死狀恐怖围俘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琢融,我是刑警寧澤界牡,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站漾抬,受9級(jí)特大地震影響宿亡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奋蔚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一她混、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泊碑,春花似錦坤按、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腹忽,卻和暖如春来累,著一層夾襖步出監(jiān)牢的瞬間砚作,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工嘹锁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葫录,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓领猾,卻偏偏與公主長(zhǎng)得像米同,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摔竿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,768評(píng)論 0 15
  • 聊天控制器(ChatViewController)界面搭建 14.聊天界面-工具條排版 1)搭建界面 添加聊天控制...
    夜空已沉寂閱讀 3,030評(píng)論 0 4
  • 參考文章:http://blog.csdn.net/q199109106q/article/details/865...
    abs1004閱讀 231評(píng)論 0 0
  • 術(shù)語(yǔ):高可用性:通常來描述一個(gè)系統(tǒng)經(jīng)過專門的設(shè)計(jì)面粮,從而減少停工時(shí)間,而保持其服務(wù)的高度可用性继低。高可靠性:產(chǎn)品在規(guī)定...
    權(quán)艷霞閱讀 459評(píng)論 0 1
  • 好友給我講了一件事情熬苍,大致如下:朋友讓她放學(xué)幫忙接孩子,周五路上堵袁翁,來回估計(jì)要將近兩個(gè)小時(shí)柴底,況且這幾天下雪,...
    滾哥閱讀 162評(píng)論 0 2