初始化框架

- 加入 mybatis
- 加入 springSecurity
main
gitee 3 weeks ago
parent 24e36c8a90
commit cbd8032d93

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<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,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">

@ -0,0 +1,124 @@
<?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>

@ -3,6 +3,12 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.supervision</groupId>
<artifactId>ai-demo-platform</artifactId>
@ -12,6 +18,123 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.21</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83_noneautotype</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.3</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.21.0</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.21.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -1,7 +0,0 @@
package com.supervision;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

@ -0,0 +1,15 @@
package com.supervision;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
@MapperScan(basePackages = {"com.supervision.**.mapper"})
@SpringBootApplication
public class PlatformApplication {
public static void main(String[] args) {
SpringApplication.run(PlatformApplication.class, args);
}
}

@ -0,0 +1,63 @@
package com.supervision.config;
import com.supervision.constant.ResultStatusEnum;
import com.supervision.dto.R;
import com.supervision.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
/**
*
*
* @author wb
* @date 2022/3/10 13:24
*/
@Slf4j
@Configuration
@RestControllerAdvice(annotations = RestController.class, basePackages = {"com.supervision.**.controller"})
public class ExceptionHandlerConfig {
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(IllegalArgumentException.class)
public R<?> manualValidationExceptionResponse(IllegalArgumentException exception) {
log.error("=========手动校验参数异常=========>>>");
log.error(exception.getMessage(), exception);
log.error("<<<=========手动校验参数异常=========");
return R.fail(ResultStatusEnum.ILLEGAL_ARGUMENT.getCode(), exception.getMessage());
}
@ExceptionHandler(BusinessException.class)
public R<?> businessExceptionResponse(BusinessException exception) {
log.error("=========运行异常=========>>>");
log.error(exception.getMessage(), exception);
log.error("<<<=========运行异常=========");
return R.fail(511, exception.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public R<?> manualValidationExceptionResponse(RuntimeException exception) {
log.error("=========运行异常=========>>>");
log.error(exception.getMessage(), exception);
log.error("<<<=========运行异常=========");
return R.fail(ResultStatusEnum.RUNTIME_EXCEPTION.getCode(), exception.getMessage());
}
@ExceptionHandler(MaxUploadSizeExceededException.class)
public R<?> handleMaxSizeException(MaxUploadSizeExceededException exception) {
log.error("=========文件大小超出限制异常=========>>>");
log.error(exception.getMessage(), exception);
log.error("<<<=========文件大小超出限制异常=========");
return R.fail(ResultStatusEnum.EXCEED_FILE_SIZE.getCode(), exception.getMessage());
}
}

@ -0,0 +1,26 @@
package com.supervision.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import java.time.LocalDateTime;
/**
* @author Ray
*/
public class MyMetaObjectHandler implements MetaObjectHandler {
public MyMetaObjectHandler() {
}
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
}

@ -0,0 +1,45 @@
package com.supervision.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
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;
/**
* MybatisPlus
*
* @author qmy
* @version 1.0.0 2020/10/22 9:47
* @since JDK1.8
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MyMetaObjectHandler myMetaObjectHandler() {
return new MyMetaObjectHandler();
}
/**
*
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(this.paginationInterceptor());
return interceptor;
}
private PaginationInnerInterceptor paginationInterceptor() {
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
paginationInterceptor.setOverflow(false);
/**
* ! .
*/
paginationInterceptor.setDbType(DbType.POSTGRE_SQL);
return paginationInterceptor;
}
}

@ -0,0 +1,82 @@
package com.supervision.config;
import com.supervision.filter.JwtAuthenticationFilter;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.util.Base64;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // 禁用CSRF
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// 👇 正确禁用方式(推荐)
.formLogin(Customizer.withDefaults()) // 启用默认配置
.httpBasic(Customizer.withDefaults()); // 启用默认配置
return http.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
// 使用DaoAuthenticationProvider并注入自定义的UserDetailsService和PasswordEncoder
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService); // 从数据库读取用户进行认证
authProvider.setPasswordEncoder(passwordEncoder()); // 使用BCrypt密码器验证密码
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
// 从AuthenticationConfiguration中获取AuthenticationManager实例
return config.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
// 使用BCryptPasswordEncoder作为密码加密器
return new BCryptPasswordEncoder();
}
public static void main(String[] args) {
String s = Base64.getEncoder().encodeToString(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("123456");
System.out.println(encode);
}
}

@ -0,0 +1,55 @@
package com.supervision.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
*
* @author qimaoyu
* @create 2019-07-14 10:22
*/
@NoArgsConstructor
@AllArgsConstructor
public enum ResultStatusEnum {
AUTHENTICATION_FAILED(320, "token失效请重新登录"),
NO_ACCESS_TO_THIS_INTERFACE(320, "无权访问此接口!"),
FAILED_TO_GENERATE_TOKEN(321, "生成token失败"),
ACCOUNT_PASSWORD_INCORRECT(322, "账号或密码错误!"),
ACCOUNT_NOT_CREATE(323, "账号未创建!"),
HAS_BEEN_PULLED_BLACK(324, "已被删除或禁用,无法登录!"),
USERNAME_MAIL_IS_EXIST(341, "登录名称已经被注册!"),
USERNAME_IS_BLANK(342, "登录名称为空!"),
VERIFICATION_CODE_EXPIRED(350,"验证码已过期,请重新获取。"),
VERIFICATION_CODE_FAILURE(351,"验证码输入错误。"),
OPERATE_FAIL(360,"修改毕业生信息失败。"),
DATA_IS_EMPTY(370,"查询到的结果为空"),
SYSTEM_ABNORMAL(500, "系统繁忙,请稍后重试!"),
UPLOAD_EXCEPTION(501, "文件上传异常!"),
EXPORT_EXCEPTION(502, "文件导出异常!"),
INCORRECT_FILE_FORMAT(503, "文件格式不正确!"),
PARAMETER_CANNOT_BE_EMPTY(504, "参数不能为空,操作失败!"),
NO_TEMP_UPLOADFILEPATH(505,"未配置文件上传临时存储路径"),
USER_DOES_NOT_EXIST(507, "用户不存在,操作失败!"),
ILLEGAL_ARGUMENT(508, "参数校验失败!"),
RUNTIME_EXCEPTION(509, "程序运行异常!"),
EXCEED_FILE_SIZE(510, "文件大小超出限制!"),
IMPORT_COMPANY_FORMAT_ERROR(521,"Excel表格格式错误"),
IMPORT_COMPANY_FAIL(522,"部分数据导入失败"),
INSERT_FAIL(600,"新增失败"),
DuplicateKeyException(601,"该条信息已经存在,请勿重复添加"),
UPDATE_FAIL(700,"更新失败"),
DELETE_FAIL(800,"删除失败"),
YEAR_IS_CLOSE(1001,"该年度暂未开启");
@Getter
@Setter
private int code;
@Getter
@Setter
private String message;
}

@ -0,0 +1,131 @@
package com.supervision.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.*;
/**
*
*
* @author qimaoyu
*/
@Data
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final String TOTAL_COUNT = "total";
public static final String RESULT_LIST = "result";
/**
*
*/
public static final int SUCCESS = 200;
/**
*
*/
public static final int FAIL = 500;
private int code;
private String msg;
private T data;
public static <T> R<T> ok() {
return restResult(null, SUCCESS, null);
}
public static <T> R<T> judgeResult(Boolean bo, String successMessage, String failMessage) {
if (bo) {
return restResult(null, SUCCESS, successMessage);
} else {
return restResult(null, FAIL, failMessage);
}
}
public static <T> R<T> okMsg(String msg) {
return restResult(null, SUCCESS, msg);
}
public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, null);
}
public static <T> R<T> ok(T data, String msg) {
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail() {
return restResult(null, FAIL, null);
}
public static <T> R<T> fail(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data) {
return restResult(data, FAIL, null);
}
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
public static Map<String, Object> buildDataMap(List list) {
Map<String, Object> dataMap = new HashMap<>();
if (list == null) {
dataMap.put(TOTAL_COUNT, 0);
dataMap.put(RESULT_LIST, new ArrayList<>());
} else {
dataMap.put(TOTAL_COUNT, list.size());
dataMap.put(RESULT_LIST, list);
}
return dataMap;
}
public static Map<String, Object> buildDataMap(List list, Long total) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put(TOTAL_COUNT, total);
dataMap.put(RESULT_LIST, list);
return dataMap;
}
public static Map<String, Object> buildDataMap(Set list) {
Map<String, Object> dataMap = new HashMap<>();
if (list == null) {
dataMap.put(TOTAL_COUNT, 0);
dataMap.put(RESULT_LIST, new ArrayList<>());
} else {
dataMap.put(TOTAL_COUNT, list.size());
dataMap.put(RESULT_LIST, list);
}
return dataMap;
}
public static Map<String, Object> buildDataMap(Object object) {
if (object == null) {
return null;
}
List<Object> resultList = new ArrayList<>();
resultList.add(object);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put(TOTAL_COUNT, resultList.size());
dataMap.put(RESULT_LIST, resultList);
return dataMap;
}
}

@ -0,0 +1,76 @@
/*
* : CustomException
* :
* : <>
* : RedName
* : 2022/8/5
* : <>
* : <>
* : <>
*/
package com.supervision.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
/**
* <>
*
*
* @author ljt
* @version [, 2022/8/5]
* @see [/]
* @since [/]
*/
@Slf4j
public class BusinessException extends RuntimeException {
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
public BusinessException(Throwable cause) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = null;
}
public BusinessException(Throwable cause, String message) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message) {
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message, Integer code) {
this.message = message;
this.code = code;
}
public BusinessException(String message, Throwable e) {
super(message, e);
log.error(message, e);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
}

@ -0,0 +1,62 @@
package com.supervision.filter;
import com.supervision.util.JwtUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtUtils jwtUtils;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
// 提取JWT Token去掉前缀"Bearer "
String token = authHeader.substring(7);
String username;
try {
// 从JWT中解析用户名
username = jwtUtils.getUsernameFromToken(token);
} catch (Exception e) {
// 如果JWT格式不正确或过期直接放行后续的过滤器会处理认证失败
filterChain.doFilter(request, response);
return;
}
// 如果成功提取到用户名,并且当前没有已认证的用户
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 根据用户名从数据库加载用户信息
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 验证Token的有效性是否未过期
if (!jwtUtils.isTokenExpired(token)) {
// 将用户信息封装到Authentication对象中标记为已认证
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 将Authentication对象放入SecurityContext表示当前请求已通过认证
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
}
filterChain.doFilter(request, response);
}
}

@ -0,0 +1,18 @@
package com.supervision.mapper;
import com.supervision.domain.SysUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author Administrator
* @description sys_userMapper
* @createDate 2025-07-09 15:19:45
* @Entity com.supervision.domain.SysUser
*/
public interface SysUserMapper extends BaseMapper<SysUser> {
}

@ -0,0 +1,16 @@
package com.supervision.service;
import com.supervision.domain.SysUser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author Administrator
* @description sys_userService
* @createDate 2025-07-09 15:19:45
*/
public interface SysUserService extends IService<SysUser> {
SysUser getByUsername(String username);
}

@ -0,0 +1,30 @@
package com.supervision.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.domain.SysUser;
import com.supervision.service.SysUserService;
import com.supervision.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
/**
* @author Administrator
* @description sys_userService
* @createDate 2025-07-09 15:19:45
*/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
implements SysUserService{
@Override
public SysUser getByUsername(String username) {
if (StrUtil.isEmpty(username)) {
return null;
}
return this.lambdaQuery().eq(SysUser::getUserName, username).one();
}
}

@ -0,0 +1,38 @@
package com.supervision.service.impl;
import com.supervision.domain.SysUser;
import com.supervision.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
private final SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 将查询到的用户信息组装成UserDetails对象
// **扩展点**:如需加载用户角色权限,可在此处查询 sys_user_role 表关联的角色,并将角色加入 authorities 列表
List<GrantedAuthority> authorities = Collections.emptyList();
// 使用Spring Security提供的User对象作为UserDetails返回
SysUser sysUser = sysUserService.getByUsername(username);
if (sysUser == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
return new User(sysUser.getUserName(), sysUser.getPassword(), authorities);
}
}

@ -0,0 +1,60 @@
package com.supervision.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String Secret;
@Value("${jwt.expiration}")
private long Expiration; // 1天
private SecretKey secretKey;
@PostConstruct
public void initKey() {
this.secretKey = Keys.hmacShaKeyFor(Base64.getDecoder().decode(Secret));
}
// 生成Token
public String generateToken(UserDetails userDetails) {
return Jwts.builder()
.subject(userDetails.getUsername())
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + Expiration))
.signWith(secretKey, Jwts.SIG.HS256)
.compact();
}
// 从 Token 中解析用户名
public String getUsernameFromToken(String token) {
Jws<Claims> jws = Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(token);
return jws.getPayload().getSubject();
}
// 判断是否过期
public boolean isTokenExpired(String token) {
Jws<Claims> jws = Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(token);
return jws.getPayload().getExpiration().before(new Date());
}
}

@ -0,0 +1,24 @@
server:
port: 9908
servlet:
context-path: /ai-platform
spring:
application:
name: pdf-qa-server
datasource:
druid:
url: jdbc:postgresql://192.168.10.137:54321/ai-demo-platform
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
jwt:
secret: "DlHaPUePiN6MyvpMpsMq/t6swzMHqtrRFd2YnofKz4k=" # JWT密钥 使用官方推荐方式生成 Base64.getEncoder().encodeToString(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
expiration: 3600000 # 1小时3600000 1天86400000

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<!-- 定义日志文件保存的路径和文件名 -->
<property name="LOG_PATH" value="./logs"/>
<property name="LOG_FILE" value="${LOG_PATH}/application.log"/>
<property name="LOGBACK_LOG_LEVEL" value="INFO"/>
<!-- 控制台输出,带有颜色 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 日志文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/application/application.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 异常错误日志单独输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/error/error.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- AOP -->
<appender name="AOP_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/AOP_LOG/AOP_LOG.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/AOP_LOG/AOP_LOG.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 根日志记录器 -->
<root level="${LOGBACK_LOG_LEVEL}">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>

@ -0,0 +1,24 @@
<?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.supervision.mapper.SysUserMapper">
<resultMap id="BaseResultMap" type="com.supervision.domain.SysUser">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="appId" column="app_id" jdbcType="VARCHAR"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="VARCHAR"/>
<result property="createUserId" column="create_user_id" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="updateUserId" column="update_user_id" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id,app_id,user_name,
password,status,create_user_id,
create_time,update_time,update_user_id
</sql>
</mapper>
Loading…
Cancel
Save