Compare commits

..

No commits in common. 'master' and 'main' have entirely different histories.
master ... main

@ -0,0 +1,2 @@
# software_teamwork

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="luojia_channel@192.168.59.129" uuid="fef17b9b-50ef-45a3-bed5-7aa6704a7372">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://192.168.59.129:3306/luojia_channel?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true&amp;serverTimezone=Asia/Shanghai</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="0@192.168.59.129" uuid="ad808a5f-004d-4f31-9402-19010c1be1ab">
<driver-ref>redis</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<jdbc-driver>jdbc.RedisDriver</jdbc-driver>
<jdbc-url>jdbc:redis://192.168.59.129:6379/0</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

@ -1,17 +0,0 @@
{
"luatools_path": "~/go/bin",
"dto_dir": "./ngx_conf/dto",
"swagger.docs.path": "./docs",
"swagger.excludes": "./client",
"swagger.file.type": "json",
"swagger.main.lua.path": "./main.lua",
"swagger.name": "swagger",
"swagger.search_dirs": "./ngx_conf,./config/cn/online",
"validator_dir": "./ngx_conf/validator",
"yapi.config.file": "docs/swagger-yapi.json",
"yapi.config.mode": "mergin",
"yapi.config.server": "https://api.yapi.net",
"yapi.config.token": "xxxxxxxxx"
}

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/service/src/main/resources/db/luojia_channel.sql" dialect="GenericSQL" />
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -1,7 +0,0 @@
package com.luojia_channel.common.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
}

@ -1,3 +0,0 @@
artifactId=common
groupId=com.luojia
version=1.0.0

@ -1,11 +0,0 @@
com\luojia\luojia_channel\advice\GlobalExceptionHandler.class
com\luojia\luojia_channel\domain\UserDTO.class
com\luojia\luojia_channel\utils\UserContext.class
com\luojia\luojia_channel\utils\JWTUtil.class
com\luojia\luojia_channel\config\RedisConfig.class
com\luojia\luojia_channel\utils\RedisUtil$ZSetItem.class
com\luojia\luojia_channel\domain\UserDTO$UserDTOBuilder.class
com\luojia\luojia_channel\exception\BaseException.class
com\luojia\luojia_channel\utils\RedisUtil.class
com\luojia\luojia_channel\domain\Result.class
com\luojia\luojia_channel\exception\UserException.class

@ -1,9 +0,0 @@
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\advice\GlobalExceptionHandler.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\config\RedisConfig.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\domain\Result.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\domain\UserDTO.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\exception\BaseException.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\exception\UserException.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\utils\JWTUtil.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\utils\RedisUtil.java
D:\javaCode\luojia_channel\common\src\main\java\com\luojia\luojia_channel\utils\UserContext.java

@ -1,32 +0,0 @@
package com.luojia_channel.modules.user.controller;
import com.luojia_channel.common.domain.Result;
import com.luojia_channel.modules.user.dto.UserChangeInfoDTO;
import com.luojia_channel.modules.user.service.UserInfoService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/user/info")
@RequiredArgsConstructor
public class UserInfoController {
private final UserInfoService userInfoService;
@PostMapping("/update")
public Result<Void> updateInfo(@RequestBody UserChangeInfoDTO userChangeInfoDTO){
userInfoService.updateInfo(userChangeInfoDTO);
return Result.success();
}
@PostMapping("/password")
public Result<Void> updatePassword(@RequestParam String password){
userInfoService.updatePassword(password);
return Result.success();
}
@PostMapping("/avatar")
public Result<Void> updateAvatar(@RequestParam MultipartFile file){
// TODO 通过oss存储服务或者minio实现头像更新
return Result.success();
}
}

@ -1,38 +0,0 @@
package com.luojia_channel.modules.user.controller;
import com.luojia_channel.common.domain.Result;
import com.luojia_channel.common.domain.UserDTO;
import com.luojia_channel.modules.user.dto.UserLoginDTO;
import com.luojia_channel.modules.user.dto.UserRegisterDTO;
import com.luojia_channel.modules.user.service.UserLoginService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserLoginController {
private final UserLoginService userLoginService;
@PostMapping("/login")
public Result<UserDTO> login(@RequestBody UserLoginDTO userLoginDTO){
return Result.success(userLoginService.login(userLoginDTO));
}
@PostMapping("/register")
public Result<UserDTO> register(@RequestBody UserRegisterDTO userRegisterDTO){
return Result.success(userLoginService.register(userRegisterDTO));
}
@PostMapping("/logout")
public Result<Void> logout(HttpServletRequest request){
userLoginService.logout(request);
return Result.success();
}
@PostMapping("/hello")
public Result<String> hello(){
return Result.success("hello");
}
}

@ -1,20 +0,0 @@
package com.luojia_channel.modules.user.dto;
import lombok.Data;
@Data
public class UserChangeInfoDTO {
private String username;
private String phone;
private String email;
private String studentId;
private String avatar;
private Integer gender;
private String college;
}

@ -1,11 +0,0 @@
package com.luojia_channel.modules.user.dto;
import lombok.Data;
@Data
public class UserLoginDTO {
// 用户标志,支持学号,手机号,邮箱
private String userFlag;
private String password;
}

@ -1,16 +0,0 @@
package com.luojia_channel.modules.user.dto;
import lombok.Data;
@Data
public class UserRegisterDTO {
private String username;
private String password;
private String phone;
private String email;
private String studentId;
}

@ -1,14 +0,0 @@
# 本地开发环境
lj:
db:
host: 192.168.59.129
password: Forely123!
redis:
host: 192.168.59.129
port: 6379
password: Forely123!
rabbitmq:
host: 192.168.59.129
port: 5672
username: admin
password: Forely123!

@ -1,51 +0,0 @@
server:
port: 8081
spring:
application:
name: service
profiles:
active: local
# 数据库
datasource:
url: jdbc:mysql://${lj.db.host}:3306/luojia_channel?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ${lj.db.password}
# redis配置
data:
redis:
host: ${lj.redis.host}
port: ${lj.redis.port}
password: ${lj.redis.password}
lettuce:
pool:
max-active: 10
max-idle: 10
min-idle: 1
time-between-eviction-runs: 10s
# rabbitmq配置
rabbitmq:
host: ${lj.rabbitmq.host}
port: ${lj.rabbitmq.port}
username: ${lj.rabbitmq.username}
password: ${lj.rabbitmq.password}
virtual-host: /
listener:
simple:
acknowledge-mode: manual
concurrency: 5
max-concurrency: 10
prefetch: 1
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
global-config:
db-config:
update-strategy: not_null
id-type: auto
mapper-locations: classpath*:mapper/**/*.xml
type-aliases-package: com.luojia.luojia_channel.modules.*.entity

@ -1,23 +0,0 @@
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`real_name` VARCHAR(50) COMMENT '实名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`phone` VARCHAR(20) UNIQUE COMMENT '注册手机号',
`email` VARCHAR(100) UNIQUE COMMENT '邮箱',
`student_id` VARCHAR(20) UNIQUE COMMENT '学号',
`avatar` VARCHAR(255) COMMENT '头像URL',
`gender` TINYINT DEFAULT 0 COMMENT '性别0未知1男2女',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` INT DEFAULT 1 COMMENT '状态1正常 2冻结',
`role` INT DEFAULT 1 COMMENT '身份1普通用户 2管理员 3超级管理员',
`integral` INT DEFAULT 0 COMMENT '用户积分',
`college` VARCHAR(100) COMMENT '所属学院',
INDEX `idx_username` (`username`),
UNIQUE INDEX `uk_phone` (`phone`),
UNIQUE INDEX `uk_email` (`email`),
UNIQUE INDEX `uk_student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

@ -1,6 +0,0 @@
<?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.luojia_channel.modules.user.mapper.UserMapper">
</mapper>

@ -1,14 +0,0 @@
# 本地开发环境
lj:
db:
host: 192.168.59.129
password: Forely123!
redis:
host: 192.168.59.129
port: 6379
password: Forely123!
rabbitmq:
host: 192.168.59.129
port: 5672
username: admin
password: Forely123!

@ -1,23 +0,0 @@
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`real_name` VARCHAR(50) COMMENT '实名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`phone` VARCHAR(20) UNIQUE COMMENT '注册手机号',
`email` VARCHAR(100) UNIQUE COMMENT '邮箱',
`student_id` VARCHAR(20) UNIQUE COMMENT '学号',
`avatar` VARCHAR(255) COMMENT '头像URL',
`gender` TINYINT DEFAULT 0 COMMENT '性别0未知1男2女',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`status` INT DEFAULT 1 COMMENT '状态1正常 2冻结',
`role` INT DEFAULT 1 COMMENT '身份1普通用户 2管理员 3超级管理员',
`integral` INT DEFAULT 0 COMMENT '用户积分',
`college` VARCHAR(100) COMMENT '所属学院',
INDEX `idx_username` (`username`),
UNIQUE INDEX `uk_phone` (`phone`),
UNIQUE INDEX `uk_email` (`email`),
UNIQUE INDEX `uk_student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

@ -1,6 +0,0 @@
<?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.luojia_channel.modules.user.mapper.UserMapper">
</mapper>

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

@ -0,0 +1,47 @@
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### Maven template
.idea/
**/target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
### Local
service/**/application-local.yaml

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,17 @@
package com.luojia_channel.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -0,0 +1,22 @@
package com.luojia_channel.common.config;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.OpenAPI;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("珞珈岛API文档")
.description("珞珈岛社交平台API接口文档")
.version("1.0")
);
}
}

@ -15,7 +15,15 @@ public class WebMvcConfig implements WebMvcConfigurer {
// 拦截器
registry.addInterceptor(authInterceptor)
.excludePathPatterns("/user/login",
"/user/register"
"/user/register",
"/user/captcha",
"/user/verify-captcha",
"/post/list",
"/post/detail",
"/comment/list",
"/comment/list/reply",
"/openapi/luojia-channel",
"/swagger-ui.html"
);
}

@ -5,4 +5,6 @@ public class RedisConstant {
public static final String REFRESH_TOKEN_PREFIX = "refresh_token:";
// redis存储的黑名单前缀
public static final String BLACKLIST_PREFIX = "blacklist:";
// 重建缓存分布式锁前缀
public static final String SAFE_GET_LOCK_KEY_PREFIX = "safe_get_lock_key_prefix:";
}

@ -1,12 +1,19 @@
package com.luojia_channel.common.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
// 统一返回前端的结果
@Data
@Schema(description = "统一返回前端的结果")
public class Result<T> {
@Schema(description = "状态码")
private int code;
@Schema(description = "提示消息")
private String msg;
@Schema(description = "响应数据")
private T data;
public Result(int code, String msg, T data) {
this.code = code;

@ -12,6 +12,7 @@ import lombok.NoArgsConstructor;
public class UserDTO {
private Long userId;
private String username;
private String avatar;
private String accessToken;
private String refreshToken;
}

@ -0,0 +1,10 @@
package com.luojia_channel.common.domain.page;
import lombok.Data;
@Data
public class PageRequest {
// 普通分页参数
private Long current = 1L;
private Long size = 10L;
}

@ -0,0 +1,21 @@
package com.luojia_channel.common.domain.page;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PageResponse<T> {
// 普通分页参数
private Long current; // 当前页数,适用于普通分页
private Long total;
private Long size = 10L;
private List<T> records = Collections.emptyList();
}

@ -0,0 +1,14 @@
package com.luojia_channel.common.domain.page;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ScrollPageRequest {
private Long lastVal; // 上次查询的最小值(用于游标分页)
private Integer offset = 0; // 偏移量(用于分页位置标记)
private Long size = 10L; // 每页数量
}

@ -0,0 +1,20 @@
package com.luojia_channel.common.domain.page;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
// 滚动分页请求
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ScrollPageResponse<T> {
private Long lastVal; // 上次查询的最小值(用于游标分页)
private Integer offset = 0; // 偏移量(用于分页位置标记)
private Long size = 10L; // 每页数量
private List<T> records; // 数据列表
}

@ -0,0 +1,7 @@
package com.luojia_channel.common.exception;
public class FileException extends BaseException{
public FileException(String msg){
super(500, msg);
}
}

@ -0,0 +1,7 @@
package com.luojia_channel.common.exception;
public class PostException extends BaseException{
public PostException(String msg){
super(500, msg);
}
}

@ -30,6 +30,7 @@ public final class JWTUtil {
private static final long NEED_REFRESH_TTL = 60 * 60 * 24 * 7 * 1000; //7天
private static final String USER_ID_KEY = "userId";
private static final String USER_NAME_KEY = "username";
private static final String USER_AVATAR_KEY = "avatar";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String ISS = "luojiachannel";
public static final String SECRET = "SecretKey5464Created2435By54377Forely02345239354893543157956476525685754352976546564766315468763584576";
@ -45,6 +46,7 @@ public final class JWTUtil {
Map<String, Object> customerUserMap = new HashMap<>();
customerUserMap.put(USER_ID_KEY, userInfo.getUserId());
customerUserMap.put(USER_NAME_KEY, userInfo.getUsername());
customerUserMap.put(USER_AVATAR_KEY, userInfo.getAvatar());
String jwtToken = Jwts.builder()
.signWith(SignatureAlgorithm.HS512, SECRET)
.setIssuedAt(new Date())
@ -64,6 +66,7 @@ public final class JWTUtil {
Map<String, Object> customerUserMap = new HashMap<>();
customerUserMap.put(USER_ID_KEY, userInfo.getUserId());
customerUserMap.put(USER_NAME_KEY, userInfo.getUsername());
customerUserMap.put(USER_AVATAR_KEY, userInfo.getAvatar());
String jwtToken = Jwts.builder()
.signWith(SignatureAlgorithm.HS512, SECRET)
.setIssuedAt(new Date())

@ -0,0 +1,41 @@
package com.luojia_channel.common.utils;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luojia_channel.common.domain.page.PageRequest;
import com.luojia_channel.common.domain.page.PageResponse;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class PageUtil {
public static <R,T> PageResponse<R> convert(IPage<T> page, Function<? super T,? extends R> mapper) {
List<R> targetList = page.getRecords().stream()
.map(mapper)
.collect(Collectors.toList());
return PageResponse.<R>builder()
.current(page.getCurrent())
.size(page.getSize())
.records(targetList)
.total(page.getTotal())
.build();
}
public static <R,T> PageResponse<R> convert(IPage<T> page, Class<R> clazz) {
List<R> targetList = page.getRecords().stream()
.map(each -> BeanUtil.copyProperties(each, clazz))
.collect(Collectors.toList());
return PageResponse.<R>builder()
.current(page.getCurrent())
.size(page.getSize())
.records(targetList)
.total(page.getTotal())
.build();
}
public static Page convert(PageRequest request){
return new Page(request.getCurrent(), request.getSize());
}
}

@ -1,26 +1,44 @@
package com.luojia_channel.common.utils;
import com.luojia_channel.common.domain.page.PageRequest;
import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.common.domain.page.ScrollPageRequest;
import com.luojia_channel.common.domain.page.ScrollPageResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static com.luojia_channel.common.constants.RedisConstant.SAFE_GET_LOCK_KEY_PREFIX;
@Component
@RequiredArgsConstructor
public class RedisUtil {
private final RedisTemplate<String, Object> redisTemplate;
private final RedissonClient redissonClient;
private static final Long DEFAULT_TIMEOUT = 30000L;
private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
// 获取redisTemplate,因为复杂的redis操作不便于封装
public RedisTemplate<String, Object> getInstance(){
return redisTemplate;
}
/**
* redis
*/
@ -30,12 +48,73 @@ public class RedisUtil {
return value != null ? type.cast(value) : null;
}
// 安全地从缓存中取值
public <T> T safeGet(String key, Class<T> type, Supplier<T> cacheLoader,
long timeout, TimeUnit timeUnit) {
T result = get(key, type);
if(result != null){
return result;
}
// 重建缓存
RLock lock = redissonClient.getLock(SAFE_GET_LOCK_KEY_PREFIX + key);
lock.lock();
try{
if(get(key, type) == null){
T dbResult = cacheLoader.get();
if(dbResult == null){
return null;
}
set(key, dbResult, timeout, timeUnit);
return dbResult;
}
}finally {
lock.unlock();
}
return get(key, type);
}
// 封装基于redis zset的滚动分页查询
public <T> ScrollPageResponse<T> scrollPageQuery(String key, Class<T> type,
ScrollPageRequest pageRequest,
Function<List<Long>, List<T>> dbFallback) {
long max = pageRequest.getLastVal();
long offset = pageRequest.getOffset();
long size = pageRequest.getSize();
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet()
.reverseRangeByScoreWithScores(key, 0, max, offset, size);
if(typedTuples == null || typedTuples.isEmpty()){
return ScrollPageResponse.<T>builder().build();
}
// 获取返回的offset与minTime
List<Long> ids = new ArrayList<>();
int returnOffset = 1;
long min = 0;
for (ZSetOperations.TypedTuple<Object> tuple : typedTuples) {
Long id = (Long)tuple.getValue();
ids.add(id);
long lastVal = tuple.getScore().longValue();
if(lastVal == min){
returnOffset++;
}else{
returnOffset = 1;
min = lastVal;
}
}
List<T> dbList = dbFallback.apply(ids);
return ScrollPageResponse.<T>builder()
.records(dbList)
.size(pageRequest.getSize())
.offset(returnOffset)
.lastVal(min)
.build();
}
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value, DEFAULT_TIMEOUT, DEFAULT_TIME_UNIT);
}
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
public void expire(String key, long time, TimeUnit timeUnit) {
@ -165,4 +244,27 @@ public class RedisUtil {
}
public <T> List<ZSetItem<T>> zRevRangeWithScores(String key, long count) {
return zRevRangeWithScores(key, 0, count - 1);
}
public <T> List<ZSetItem<T>> zRevRangeWithScores(String key, long start, long end) {
Set<ZSetOperations.TypedTuple<Object>> tuples = redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
return convertTuples(tuples);
}
public <T> T zRevMaxValue(String key) {
List<ZSetItem<T>> items = zRevRangeWithScores(key, 1);
return items.isEmpty() ? null : items.get(0).getValue();
}
public <T> ZSetItem<T> zRevMaxItem(String key) {
List<ZSetItem<T>> items = zRevRangeWithScores(key, 1);
return items.isEmpty() ? null : items.get(0);
}
}

@ -2,6 +2,7 @@ package com.luojia_channel.common.utils;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.luojia_channel.common.domain.UserDTO;
import com.luojia_channel.common.exception.UserException;
import java.util.Optional;
@ -18,12 +19,15 @@ public final class UserContext {
return Optional.ofNullable(userInfoDTO).map(UserDTO::getUserId).orElse(null);
}
public static String getUsername() {
UserDTO userInfoDTO = USER_THREAD_LOCAL.get();
return Optional.ofNullable(userInfoDTO).map(UserDTO::getUsername).orElse(null);
}
public static String getAvatar() {
UserDTO userInfoDTO = USER_THREAD_LOCAL.get();
return Optional.ofNullable(userInfoDTO).map(UserDTO::getAvatar).orElse(null);
}
public static String getAccessToken() {
UserDTO userInfoDTO = USER_THREAD_LOCAL.get();

@ -0,0 +1,6 @@
{
"name": "luojia-island",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

@ -82,6 +82,12 @@
<version>1.2.83</version>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
@ -93,8 +99,33 @@
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.5</version> <!-- 使用最新版本 -->
<version>8.5.12</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- openAPI -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.8</version>
</dependency>
<!-- es -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
<build>

@ -0,0 +1,8 @@
protected-mode no
requirepass "Redis@9012"
bind 0.0.0.0
port 6379

@ -2,19 +2,17 @@
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="common" />
<module name="service" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="common" options="-parameters" />
<module name="luojia_channel" options="" />
<module name="service" options="-parameters" />
</option>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
@ -11,10 +16,5 @@
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

@ -8,7 +8,5 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK" />
</project>

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save