really! Based on Springboot and WebScoket, I wrote an online chat applet

An online chat applet based on Springboot and WebScoket

(I haven't written anything for a few days, and I haven't practiced my hands, so I just looked at this...)

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

project instruction

  • This project is a small demo for chat, developed by springboot+websocket+vue.
  • One of the interfaces is the add friend interface. Adding a friend will determine whether it is already a friend.
  • When chatting: A sends a message to B. If B’s chat window is not A, B will remind A to send a message.
  • The input box of chat content uses layui's rich text editor, and currently does not support carriage return to send content.
  • Chat can send pictures, and pictures are stored in the D:/chat/ directory by default.
  • Clicking on a picture in the chat content will pop up a preview, which will pop up all pictures in this message.
  • When sending a voice, the voice is sent to the user in the current chat window by default, so when recording the voice, make sure that there are selected users in the current chat window.
  • Know that the user's account can add friends, currently if the account exists, you can directly add it successfully

The old rules, let's take a look at the directory structure of small projects first:

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

One, first introduce the pom file

Just put a little code here (the code is too long)

<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>

Second, create the corresponding yml configuration file

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    #指定数据源    type: com.alibaba.druid.pool.DruidDataSource
    # 数据源其他配置    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'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 使用时间戳显示时间
  http:    multipart:      max-file-size: 1000Mb
      max-request-size: 1000Mb
#配置文件式开发mybatis:  #全局配置文件的位置  config-location: classpath:mybatis/mybatis-config.xml
  #所有sql映射配置文件的位置  mapper-locations: classpath:mybatis/mapper/**/*.xmlserver:  session:    timeout: 7200

Three, create an entity class

I won’t say more here, there are Login, Userinfo, ChatMsg, ChatFriends

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

Fourth, create the corresponding mapper (ie dao layer) and the corresponding mapper mapping file

(Here is just one, I won’t say more)

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>

Five, create the corresponding business class (ie service)

(The same business layer is also pointed out here)

@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);
    }}

Six, create the corresponding controller

Let me talk about the interface of the project

  1. /chat/upimg chat picture upload interface
  2. /chat/lkuser This interface is used to add friends: query the user, if the user exists, return user information, if not, return not exist
  3. /chat/adduser/ This interface is the interface for adding friends, it will determine whether the added friend is yourself, if the added friend already exists, it will return directly
  4. /chat/ct Jump to the chat interface
  5. /chat/lkfriends Query user's friends
  6. /chat/lkuschatmsg/ This interface is an interface for querying chat information between two users, passing in the userid of the user, and querying the currently logged-in user and the chat history of the user.
  7. /chat/audio This interface is used by Ajax to upload audio data recorded by web interface js

(Also just write one)

@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("账号或者密码错误");
        }        session.setAttribute("userid",userid);
        return R.ok().message("登录成功");
    }}

Seven, create the corresponding tool class and custom exception class

  1. Expression filtering tools
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 data encryption class
   static String[] chars = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
    /**
     * 将普通字符串用md5加密,并转化为16进制字符串
     * @param str
     * @return
     */
    public static String StringInMd5(String str) {        // 消息签名(摘要)
        MessageDigest md5 = null;        try {            // 参数代表的是算法名称
            md5 = MessageDigest.getInstance("md5");
            byte[] result = md5.digest(str.getBytes());            StringBuilder sb = new StringBuilder(32);
            // 将结果转为16进制字符  0~9 A~F
            for (int i = 0; i < result.length; i++) {
                // 一个字节对应两个字符
                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. Test data encryption
public class TestUtil {
    @Test
    public void testA(){
        String s = Md5Util.StringInMd5("123456");
        System.out.println(s);
    }}

8. Import the corresponding static resource file (this should be done at the beginning)

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

Nine, customize some configurations and inject them into the container

  1. Druid data source
@Configuration
public class DruidConfig {    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean    public DataSource druid(){        return new DruidDataSource();
    }    //配置Druid的监控    //1.配置要给管理后台的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","");//默认允许ip访问
        initParams.put("deny","");
        bean.setInitParameters(initParams);        return bean;
    }    //2.配置一个监控的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. Static resources and interceptors
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter {
    //配置一个静态文件的路径 否则css和js无法使用,虽然默认的静态资源是放在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) {        //注册TestInterceptor拦截器
        InterceptorRegistration registration = registry.addInterceptor(new AdminInterceptor());        registration.addPathPatterns("/chat/*");
    }}
  1. WebSocketConfigScokt communication arrangement
@Configuration
@EnableWebSocket
public class WebSocketConfig {
     @Bean
    public ServerEndpointExporter serverEndpointExporter() {        return new ServerEndpointExporter();
    }}

10. Test

These are two different users

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

really!  Based on Springboot and WebScoket, I wrote an online chat applet

 

Of course, you can also make a voice, add friends  and write today's here! Thank you!  I want to mention a personal blog of one of my seniors, of course, and mine, thank you

Author: Thinking milk

Link: https://juejin.im/post/5ea7994c5188256da14e972d

Source: Nuggets

Guess you like

Origin blog.csdn.net/GYHYCX/article/details/108646074