Based on Springboot and WebScoket to write an online chat small procedures
(I haven’t written anything for a few days, and HAVEN’t gone to practice, so I just read this…)
Project description
- This project is a small demo chat, using Springboot + Websocket + Vue development.
- One of the interfaces is the Add Friend interface, adding a friend will determine whether they are already friends.
- During chatting: USER A sends A message to user B. If user B’s chat window is not user A’s, user B will prompt user A to send A message.
- The input box of chat content adopts layui’s rich text editor, and currently does not support carriage return to send content.
- Chat can send pictures, which are stored in D:/chat/ by default.
- Clicking on an image in the chat brings up a preview that brings up all the images in the message.
- By default, voice messages are sent to users in the current chat window. Therefore, ensure that the selected users are available in the current chat window when recording voice messages.
- You can add friends if you know the user’s account. At present, you can add friends if the account exists
As usual, let’s look at the small project directory structure first:
First, introduce poM files
I only put a little bit of code here (it’s 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> < the 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 > < the dependency > < groupId > com. Alibaba < / groupId > < artifactId > fastjson < / artifactId > < version > 1.2.60 < / version > < / dependency > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>Copy the code
2. Create the corresponding YML configuration file
spring:
profiles:
active: prod
Copy the code
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
# specify data source
type: com.alibaba.druid.pool.DruidDataSource
Other configuration of data source
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# Configure the filters for monitoring statistics interception. After removing the filters, the MONITORING interface SQL cannot be counted. 'wall' is used for the firewall
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: The format of the returned date field
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
write-dates-as-timestamps: false # true Displays the time using a timestamp
http:
multipart:
max-file-size: 1000Mb
max-request-size: 1000Mb
Config file development
mybatis:
Location of the global configuration file
config-location: classpath:mybatis/mybatis-config.xml
The location of all SQL mapping configuration files
mapper-locations: classpath:mybatis/mapper/**/*.xml
server:
session:
timeout: 7200
Copy the code
Create an entity class
Here is no longer say more, with the Login, the Userinfo, ChatMsg, ChatFriends
Create the corresponding MAPper (dao layer) and the corresponding mapper mapping file
(Here is just one, no more details)
public interface ChatFriendsMapper {
// Query all friends
List<ChatFriends> LookUserAllFriends(String userid);
// Insert a friend
void InsertUserFriend(ChatFriends chatFriends);
// Determine whether to add friends
Integer JustTwoUserIsFriend(ChatFriends chatFriends);
// Query user information
Userinfo LkUserinfoByUserid(String userid);
}
Copy the code
<?xml version="1.0" encoding="UTF-8"? >
<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>
Copy the code
Create the corresponding business class (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){
returnchatFriendsMapper.LkUserinfoByUserid(userid); }}Copy the code
6. Create a controller
Let’s talk about the project interface
- /chat/upimg Interface for uploading chat pictures
- The /chat/lkuser interface is used to add friends. If the user exists, the user information is returned. If the user does not exist, the user information is returned
- The /chat/adduser/ interface is used to add friends. It checks whether the added friend is the user and returns the value if the added friend already exists
- /chat/ct The chat page is displayed
- /chat/ lkFriends Queries a user’s friends
- /chat/lkuschatmsg/ This interface is used to query the chat information between two users. The user’s userID is passed in to query the chat records of the current logged-in user and the user.
- The /chat/audio interface is used by Ajax to upload audio data recorded by JS on the Web interface
(Again, just write one)
@Controller
public class LoginCtrl {
@Autowired
LoginService loginService;
@GetMapping("/")
public String tologin(a){
return "user/login";
}
/** * log in ** /
@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("Wrong account or password");
}
session.setAttribute("userid",userid);
return R.ok().message("Login successful"); }}Copy the code
Create the corresponding tool class and custom exception class
- Expression filtering tool class
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(a){
String s = EmojiFilter.filterEmoji("Hello 😄, how are you?");
System.out.println(s);
}
Copy the code
- Md5 data encryption class
static String[] chars = {"0"."1"."2"."3"."4"."5"."6"."Seven"."8"."9"."a"."b"."c"."d"."e"."f"};
/** * encrypts an ordinary string with MD5 and converts it to a hexadecimal string *@param str
* @return* /
public static String StringInMd5(String str) {
// Message signature (digest)
MessageDigest md5 = null;
try {
// The parameter represents the algorithm name
md5 = MessageDigest.getInstance("md5");
byte[] result = md5.digest(str.getBytes());
StringBuilder sb = new StringBuilder(32);
// Convert the result to hexadecimal characters 0 to 9 A to F
for (int i = 0; i < result.length; i++) {
// One byte corresponds to two characters
byte x = result[i];
// get a high position
int h = 0x0f & (x >>> 4);
// get the low value
int l = 0x0f & x;
sb.append(chars[h]).append(chars[l]);
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw newRuntimeException(e); }}Copy the code
- Test data encryption classes
public class TestUtil {
@Test
public void testA(a){
String s = Md5Util.StringInMd5("123456"); System.out.println(s); }}Copy the code
8. Introduce the corresponding static resource file (this should be done at the beginning)
9. Customize some configurations and inject them into the container
- Druid data source
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(a){
return new DruidDataSource();
}
// Configure Druid monitoring
//1. Configure the Servlet to be assigned to the admin background
@Bean
public ServletRegistrationBean servletRegistrationBean(a){
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 access is allowed by default
initParams.put("deny"."");
bean.setInitParameters(initParams);
return bean;
}
//2. Configure a filter for monitoring
@Bean
public FilterRegistrationBean webStarFilter(a){
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("/ *"));
returnbean; }}Copy the code
- Static resources and interceptors
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter {
Otherwise, CSS and JS cannot be used. The default static resource is static, but the folder inside is not configured
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
@Bean
public WebMvcConfigurerAdapter WebMvcConfigurerAdapter(a) {
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) {
// Register TestInterceptor interceptor
InterceptorRegistration registration = registry.addInterceptor(new AdminInterceptor());
registration.addPathPatterns("/chat/*"); }}Copy the code
- WebSocketConfigScokt Communication configuration
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(a) {
return newServerEndpointExporter(); }}Copy the code
10. Test
These are two different users
Of course, you can also make voice calls and add friends
That’s all for today! Thank you very much!
I want to mention the personal blog of one of my upperclassmen and, of course, mine. Thank you
Richard wood guest
my