提交信息

This commit is contained in:
顾挽 2024-10-22 22:43:04 +08:00
commit 70ef2cf196
49 changed files with 1883 additions and 0 deletions

58
.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
# ignore these folders
target/
.idea/
.settings/
.vscode/
bin/
out/
# ignore these files
.classpath
.project
.settings
.idea
# filter databfile、sln file
*.mdb
*.ldb
*.sln
# class file
*.com
*.class
*.dll
*.exe
*.o
*.so
# compression file
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.via
*.tmp
*.err
*.log
*.iml
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
.factorypath
.mvn/
mvnw.cmd
mvnw
# Files or folders need to be retained
# ...

15
Dockerfile Normal file
View File

@ -0,0 +1,15 @@
# 使用官方的OpenJDK基础镜像
#FROM openjdk:8-jre-slim
FROM openjdk:17
# 在镜像中创建一个目录用于存放我们的应用
VOLUME /tmp
# 将jar包添加到镜像中并更名为app.jar
ADD login/target/login.jar app.jar
# ADD shapelight-admin/src/main/resources/application.yml /config/application.yml
# ADD shapelight-admin/src/main/resources/application-dev.yml /config/application-de
# 在容器启动时运行jar包
# ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=/config/application.yml,/config/application-dev.yml"]
ENTRYPOINT ["java", "-jar", "app.jar"]

77
login/pom.xml Normal file
View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>login</artifactId>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-captcha-plus</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!-- Sa-Token 权限认证在线文档https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>1.39.0</version>
</dependency>
<dependency>
<groupId>com.pig4cloud.plugin</groupId>
<artifactId>oss-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,46 @@
package com.guwan.Interceptor;
import com.guwan.service.TokenService;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class TokenInterceptor implements HandlerInterceptor {
private final TokenService tokenService;
// 注入自定义的 Token 处理服务
public TokenInterceptor(TokenService tokenService) {
this.tokenService = tokenService;
}
// 在控制器方法执行之前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取 Token
String token = request.getHeader("Authorization");
if (token != null) {
// 验证 Token 的有效性
boolean isValid = tokenService.checkToken(token);
if (isValid) {
// 如果 Token 有效可能需要更新 Token 并将新的 Token 添加到响应头中
/* String newToken = tokenService.refreshToken(token);
if (newToken != null) {
response.setHeader("Authorization", newToken);
}*/
return true; // Token 有效继续处理请求
} else {
// 如果 Token 无效返回未授权状态码
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false; // 拦截请求
}
}
// 如果没有 Token返回未授权状态码
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false; // 拦截请求
}
}

View File

@ -0,0 +1,16 @@
package com.guwan;
import cn.dev33.satoken.SaManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LoginApplication {
public static void main(String[] args) {
SpringApplication.run(LoginApplication.class, args);
System.out.println("启动成功Sa-Token 配置如下:" + SaManager.getConfig());
}
}

View File

@ -0,0 +1,60 @@
package com.guwan.common;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
*
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
put("data", new HashMap<>());
}
public static R error() {
// return error(500, "未知异常,请联系管理员");
return error(500, "系统开小差了");
}
public static R error(String msg) {
return error(500, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
r.put("data",new HashMap<>());
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
@Override
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@ -0,0 +1,61 @@
package com.guwan.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/*
global:
http_flag: http
file_path:
static-locations: /home/shapelight/sl_site
static-user_path: userdata
#log_file: snail_develop.log
#http_flag: http
user_path: /home/shapelight/Snail_develop/UserData
common_path: /home/shapelight/Snail_develop/Common
wx_code_path: /home/shapelight/Snail_develop/WxCode
doc_path: /home/shapelight/Snail_develop/Doc
apk_path: /home/shapelight/Snail_develop/Apk
ten_pic: pic
ten_wx: wx
ten_xlsx: xlsx
ten_song: song
ten_logo: logo
ten_member_org: member_org
ten_member_face: member_face
ten_visitor_org: visitor_org
ten_visitor_face: visitor_face
ten_member_rec_org: member_rec_org
ten_member_rec_face: member_rec_face
ten_visitor_rec_org: visitor_rec_org
ten_visitor_rec_face: visitor_rec_face
url:
#addr: 192.168.1.50:9902
url_img: 192.168.1.50:9903
url_out: 192.168.1.50:9903
url_license: 39.96.9.232:3389
upload_zip:
protocal: http://
ip: 127.0.0.1
port: 8001
zippath: /home/shapelight/DataBase/studentOrg
small-face-path: /home/shapelight/DataBase/studentFace
*/
@Component
@Data
public class GlobalValue {
@Value("${global.minio.endpoint}")
private String minioEndpoint;
@Value("${global.minio.port}")
private String minioPort;
@Value("${global.minio.accessKey}")
private String minioAccessKey;
@Value("${global.minio.secretKey}")
private String minioSecretKey;
@Value("${global.minio.bucketName}")
private String minioBucketName;
}

View File

@ -0,0 +1,35 @@
package com.guwan.config;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@Component
public class JsonRedisTemplate extends RedisTemplate<String, Object>{
public JsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 构造函数注入 RedisConnectionFactory设置到父类
super.setConnectionFactory(redisConnectionFactory);
// 使用 Jackson 提供的通用 Serializer
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
serializer.configure(mapper -> {
// 如果涉及到对 java.time 类型的序列化反序列化那么需要注册 JavaTimeModule
mapper.registerModule(new JavaTimeModule());
});
// String 类型的 key/value 序列化
super.setKeySerializer(StringRedisSerializer.UTF_8);
super.setValueSerializer(serializer);
// Hash 类型的 key/value 序列化
super.setHashKeySerializer(StringRedisSerializer.UTF_8);
super.setHashValueSerializer(serializer);
}
}

View File

@ -0,0 +1,40 @@
package com.guwan.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 对象存储工具类
*/
@Component
public class MinioConfig {
@Autowired
private GlobalValue globalValue;
public String getMinioEndpoint() {
return globalValue.getMinioEndpoint();
}
public String getBucketName(){
return globalValue.getMinioBucketName();
}
@Bean("minioClient")
public MinioClient minioClient(){
MinioClient minioClient=null;
try {
minioClient = new MinioClient(globalValue.getMinioEndpoint(),
// globalValue.getMinioPort(),
globalValue.getMinioAccessKey(),
globalValue.getMinioSecretKey());
if (!minioClient.bucketExists(globalValue.getMinioBucketName())) {
minioClient.makeBucket(globalValue.getMinioBucketName());
}
} catch (Exception e) {
e.printStackTrace();
}
return minioClient;
}
}

View File

@ -0,0 +1,42 @@
package com.guwan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@Configuration
public class RedisConfig {
/**
* 实例化 RedisTemplate 对象
*
* @return
*/
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
return redisTemplate;
}
/**
* 设置数据存入 redis 的序列化方式,并开启事务
*
* @param redisTemplate
* @param factory
*/
private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
// 如果不配置Serializer那么存储的时候缺省使用String如果用User类型存储那么会提示错误User can't cast to String
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 开启事务
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(factory);
}
}

View File

@ -0,0 +1,21 @@
package com.guwan.config;
import com.guwan.Interceptor.TokenInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加自定义的 Token 拦截器
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/user/**") // 拦截 /User/** 路径
.excludePathPatterns("/user/login"); // 不拦截 /User/login 路径
}
}

View File

@ -0,0 +1,58 @@
package com.guwan.controller.login;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import com.xingyuv.captcha.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
@Resource
private CaptchaService captchaService;
@PostMapping("/get")
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
assert request.getRemoteHost() != null;
data.setBrowserInfo(getRemoteId(request));
return captchaService.get(data);
}
@PostMapping("/check")
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
data.setBrowserInfo(getRemoteId(request));
return captchaService.check(data);
}
//@PostMapping("/verify")
public ResponseModel verify(@RequestBody CaptchaVO data, HttpServletRequest request) {
return captchaService.verification(data);
}
public static String getRemoteId(HttpServletRequest request) {
String xfwd = request.getHeader("X-Forwarded-For");
String ip = getRemoteIpFromXfwd(xfwd);
String ua = request.getHeader("user-agent");
if (StringUtils.isNotBlank(ip)) {
return ip + ua;
}
return request.getRemoteAddr() + ua;
}
private static String getRemoteIpFromXfwd(String xfwd) {
if (StringUtils.isNotBlank(xfwd)) {
String[] ipList = xfwd.split(",");
return StringUtils.trim(ipList[0]);
}
return null;
}
}

View File

@ -0,0 +1,31 @@
package com.guwan.controller.login;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user/")
public class SatokenController {
// 测试登录浏览器访问 http://localhost:8081/user/doLogin?username=zhang&password=123456
// 存到cookie里面
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此处仅作模拟示例真实项目需要从数据库中查询数据进行比对
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "登录成功";
}
return "登录失败";
}
// 查询登录状态浏览器访问 http://localhost:8081/user/isLogin
@RequestMapping("isLogin")
public String isLogin() {
return "当前会话是否登录:" + StpUtil.isLogin();
}
}

View File

@ -0,0 +1,93 @@
package com.guwan.controller.login;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.guwan.controller.login.info.UserRequest;
import com.guwan.controller.login.info.WxMaUserInfo;
import com.guwan.controller.login.request.ScanResult;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.*;
@RestController
public class ScanCodeController {
@Operation(summary = "获取微信登录二维码信息")
@RequestMapping("/wxQr")
@ResponseBody
public void wxQr(String secret) {
// 请求易登获取二维码接口
String s = HttpUtil.get("https://yd.jylt.cc/api/wxLogin/tempUserId?secret=" + secret);
JSONObject jsonObject = JSONUtil.parseObj(s);
if (jsonObject.getInt("code") != 0) {
System.out.println(jsonObject.getInt("code") + "二维码获取失败");
}else {
System.out.println(jsonObject.getJSONObject("data"));
System.out.println(jsonObject.getJSONObject("data").
getStr("qrUrl"));
}
}
@PostMapping("/callback")
public ScanResult handleUserRequest(@RequestBody UserRequest userRequest) {
// 从userRequest中提取信息
String tempUserId = userRequest.getTempUserId();
WxMaUserInfo wxMaUserInfo = userRequest.getWxMaUserInfo();
// 你可以在这里添加你的业务逻辑比如保存用户信息到数据库等
System.out.println(tempUserId);
System.out.println(userRequest.getWxMaUserInfo().getNickName());
/**
* {
* "code": "0:登录成功;其他:登录失败",
* "msg": "响应给用户的提示信息,该信息用于在小程序端进行提示"
* }
*/
// 以下是一个简单的响应示例
return new ScanResult(0, "恭喜" +
userRequest.getWxMaUserInfo().getNickName() + "成功登录!!!");
}
//用户必须要修改 易登 的信息
//生产二维码之后 会有一个随机id
//用户 如果想使用扫码登录 必须要注册 易登
//而且必须要把 易登 的名字改成和系统一样
public ScanResult demo(@RequestBody UserRequest userRequest) {
// 从userRequest中提取信息
String tempUserId = userRequest.getTempUserId();
WxMaUserInfo wxMaUserInfo = userRequest.getWxMaUserInfo();
// 你可以在这里添加你的业务逻辑比如保存用户信息到数据库等
System.out.println(tempUserId);
System.out.println(wxMaUserInfo.getNickName());
/*
{
"code": "0:登录成功;其他:登录失败",
"msg": "响应给用户的提示信息,该信息用于在小程序端进行提示"
}
*/
//TODO: 查询该用户是否注册
// 注册之后 token 逻辑
// 以下是一个简单的响应示例
return new ScanResult(0, "恭喜" +
userRequest.getWxMaUserInfo().getNickName() + "成功登录!!!");
}
}

View File

@ -0,0 +1,119 @@
package com.guwan.controller.login;
import com.guwan.common.R;
import com.guwan.config.MinioConfig;
import com.pig4cloud.plugin.oss.service.OssTemplate;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.entity.FileEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Date;
import java.util.UUID;
@RestController
@RequestMapping("")
@RequiredArgsConstructor
public class UploadController {
private final MinioConfig minioConfig;
private final MinioClient minioClient;
private final OssTemplate template;
/**
* 上传文件
* 文件名采用uuid,避免原始文件名中带"-"符号导致下载的时候解析出现异常
* @param file 资源
* @return R(bucketName, filename)
*/
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String fileName = uuid + originalFilename;
template.putObject("demo", uuid + originalFilename, file.getInputStream());
return fileName;
}
/**
* 获取外链
* @param bucketName bucket名称
* @param objectName 文件名称
* @param minutes 过期时间单位分钟,请注意该值必须小于7天
* @return url
*/
@GetMapping("/getDownloadExternalChain")
public String get(String bucketName, String objectName, int minutes) {
return template.getObjectURL(bucketName, objectName, Duration.ofMinutes(minutes));
}
@PostMapping("/GBUpload")
public R gbUpload(MultipartFile file) {
if (file.isEmpty() || file.getSize() == 0) {
System.out.println("文件不能为空");
}
String fileName = null;
String catalogue;
try {
String extension = FilenameUtils.getExtension(file.getOriginalFilename()); //后缀名
if (extension.equals("png") || extension.equals("jpg")){
catalogue = "photo/";
}else if (extension.equals("mp4")){
catalogue = "video/";
}else {
return R.error().put("info", "不允许上传此类型!");
}
fileName = catalogue + "t_" +
UUID.randomUUID().toString().replace("-","") +
"." + extension;
InputStream inputStream = file.getInputStream();
PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
putObjectOptions.setContentType(file.getContentType());
minioClient.putObject(
minioConfig.getBucketName(), fileName, inputStream, putObjectOptions);
inputStream.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("方法结束");
UUID uuid = UUID.randomUUID();
String replace = uuid.toString().replace("-", "");
int lastDotIndex = file.getOriginalFilename().lastIndexOf('.');
String substring = file.getOriginalFilename().substring(0, lastDotIndex);
/* FileEntity fileEntity = new FileEntity(replace,
substring, fileName, new Date());
cqFileMapper.insert(fileEntity);
return R.ok().put("data", fileEntity);*/
return R.ok().put("data", minioConfig.getMinioEndpoint() + "/" +
minioConfig.getBucketName() + "/" + fileName);
}
}

View File

@ -0,0 +1,11 @@
package com.guwan.controller.login;
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}

View File

@ -0,0 +1,48 @@
package com.guwan.controller.login;
import com.guwan.service.TokenService;
import com.guwan.util.IPUtils;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Operation;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private TokenService tokenService;
@GetMapping("/login")
@PermitAll
@Operation(summary = "使用账号密码登录")
public String login(String userId, HttpServletRequest request) {
String ip = IPUtils.getIpAddr(request);
System.out.println("ip = " + ip);
return tokenService.createToken(userId, ip);
}
@GetMapping("/getInfo")
@PermitAll
@Operation(summary = "查询用户信息")
public String getInfo(String token) {
if (!tokenService.checkToken(token)) {
return "token无效";
}
try {
tokenService.getInfo(token);
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
tokenService.validateAndExtendToken(token);
}
return "getInfo";
}
}

View File

@ -0,0 +1,9 @@
package com.guwan.controller.login;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

View File

@ -0,0 +1,11 @@
package com.guwan.controller.login.info;
import lombok.Data;
@Data
public class UserRequest {
private String tempUserId;
private WxMaUserInfo wxMaUserInfo;
// 省略getter和setter方法
}

View File

@ -0,0 +1,11 @@
package com.guwan.controller.login.info;
import lombok.Data;
@Data
public class WxMaUserInfo {
private String openId;
private String nickName;
private String gender;
private String avatarUrl;
}

View File

@ -0,0 +1,17 @@
package com.guwan.controller.login.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ScanResult {
private int code;
private String msg;
}

View File

@ -0,0 +1,63 @@
/**
* Copyright (c) 2020 wuchenxi
* walter-blog is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* <p>
* <p>
* Mulan Permissive Software LicenseVersion 2
* <p>
* Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2)
* January 2020 http://license.coscl.org.cn/MulanPSL2
*/
package com.guwan.controller.login.response;
import lombok.Data;
import java.io.Serializable;
/**
* 统一系统响应结果格式
*
* @author wuchenxi
* @date 2020-08-08 10:07:03
*/
@Data
public class ResponseKit<T> implements Serializable {
private int code;
private String msg;
private T data;
private ResponseKit(int code, String msg) {
this.code = code;
this.msg = msg;
}
private ResponseKit(int code, T data) {
this.code = code;
this.data = data;
}
public static <T> ResponseKit<T> success() {
return new ResponseKit<T>(200, "操作成功!");
}
public static <T> ResponseKit<T> error(int code, String msg) {
return new ResponseKit<T>(code, msg);
}
public static <T> ResponseKit<T> success(T data) {
return new ResponseKit<T>(200, data);
}
private ResponseKit(){}
}

View File

@ -0,0 +1,69 @@
package com.guwan.service;
import com.guwan.config.JsonRedisTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Service
public class TokenService {
@Autowired
private JsonRedisTemplate redisTemplate;
public String createToken(String userId, String ip) {
if (userId == null) {
throw new RuntimeException("userId 不能为空");
}
String token;
if (redisTemplate.opsForValue().get("User-token:" + userId) != null) {
redisTemplate.delete("User-info:" + redisTemplate.opsForValue().get("User-token:" + userId));
redisTemplate.delete("User-token:" + userId);
}
token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set("User-token:" + userId, token, 30, TimeUnit.MINUTES);
HashMap<String, Object> userInfo = new HashMap<>();
userInfo.put("userId", userId);
userInfo.put("ip", ip);
userInfo.put("token", token);
redisTemplate.opsForHash().putAll("User-info:" + token, userInfo);
redisTemplate.expire("User-info:" + token, 30, TimeUnit.MINUTES);
// 将所有用户信息存储在一个键中
//redisTemplate.opsForValue().set("User-info-string:" + token, userInfo, 30, TimeUnit.MINUTES);
return token;
}
public boolean checkToken(String token) {
if (token != null) {
String key = "User-info:" + token;
Object value = redisTemplate.opsForHash().entries(key);
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>) value;
return map.get("userId") != null;
}
return false;
}
public void validateAndExtendToken(String token) {
// 重置过期时间
//redisTemplate.expire("User-info-string:" + token, 30, TimeUnit.MINUTES);
String userId = (String) redisTemplate.opsForHash().get("User-info:" + token, "userId");
redisTemplate.opsForValue().
set("User-token:" + userId, token,
30, TimeUnit.MINUTES);
redisTemplate.expire("User-info:" + token, 30, TimeUnit.MINUTES);
}
public void getInfo(String token) {
Map<Object, Object> map = redisTemplate.opsForHash().entries("User-info:" + token);
if (!map.isEmpty()) {
System.out.println(map);
}
}
}

View File

@ -0,0 +1,99 @@
package com.guwan.util;
import cn.hutool.core.io.resource.ResourceUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import java.io.IOException;
/**
* IP 工具类
*
* IP 数据源来自 ip2region.xdb 精简版基于 <a href="https://gitee.com/zhijiantianya/ip2region"/> 项目
*
* @author wanglhup
*/
@Slf4j
public class IPUtils {
/**
* 初始化 SEARCHER
*/
@SuppressWarnings("InstantiationOfUtilityClass")
private final static IPUtils INSTANCE = new IPUtils();
/**
* IP 查询器启动加载到内存中
*/
private static Searcher SEARCHER;
private static final String UNKNOWN = "unknown";
private static final String LOCAL_IP = "127.0.0.1";
/**
* 私有化构造
*/
private IPUtils() {
try {
long now = System.currentTimeMillis();
byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
SEARCHER = Searcher.newWithBuffer(bytes);
log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
} catch (IOException e) {
log.error("启动加载 IPUtils 失败", e);
}
}
/**
* 查询 IP 对应的地区编号
*
* @param ip IP 地址格式为 127.0.0.1
* @return 地区id
*/
@SneakyThrows
public static Integer getAreaId(String ip) {
return Integer.parseInt(SEARCHER.search(ip.trim()));
}
/**
* 查询 IP 对应的地区编号
*
* @param ip IP 地址的时间戳格式参考{@link Searcher#checkIP(String)} 的返回
* @return 地区编号
*/
@SneakyThrows
public static Integer getAreaId(long ip) {
return Integer.parseInt(SEARCHER.search(ip));
}
public static String getIpAddr(HttpServletRequest request) {
if (request == null) {
return UNKNOWN;
}
String ip = request.getHeader("x-forwarded-for");
if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip;
}
}

View File

@ -0,0 +1,56 @@
server:
port: 8084
spring:
data:
redis:
host: 1.92.149.170
port: 6379
password: 123456
database: 0
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/studb
username: root
password: 123456
servlet:
multipart:
max-file-size: 1000MB
max-request-size: 1000MB
enabled: true
file-size-threshold: 1000MB
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: satoken
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true
oss:
endpoint: http://localhost:9000
access-key: admin
secret-key: admin123456
global:
minio:
endpoint: http://127.0.0.1:9000
port: 9000
accessKey: admin
secretKey: admin123456
bucketName: yunnni

Binary file not shown.

View File

@ -0,0 +1,29 @@
package com.guwan;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSaveUser() {
String key = "user:1";
String value = "John Doe";
redisTemplate.opsForValue().set(key, value); // 保存数据
// 验证数据是否保存成功
String retrievedValue = (String) redisTemplate.opsForValue().get(key);
assertEquals(value, retrievedValue, "Retrieved value should match the saved value");
}
}

View File

@ -0,0 +1,24 @@
package com.guwan;
import com.guwan.controller.login.User;
import com.guwan.controller.login.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class SampleTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}

28
old-app/pom.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>old-app</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.guwan</groupId>
<artifactId>old-nacos</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,15 @@
package cn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BsApplication {
public static void main(String[] args) {
SpringApplication.run(BsApplication.class, args);
}
}

View File

@ -0,0 +1,22 @@
package cn.config;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@NacosPropertySource(dataId = "mysql", autoRefreshed = true)
public class MysqlNacosConf {
@NacosValue("${spring.datasource.driver-class-name}")
private String driverClassName;
@NacosValue("${spring.datasource.url}")
private String url;
@NacosValue("${spring.datasource.username}")
private String username;
@NacosValue("${spring.datasource.password}")
private String password;
}

View File

@ -0,0 +1,22 @@
package cn.config;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@NacosPropertySource(dataId = "mysql", autoRefreshed = true)
public class NacosConfig {
@NacosValue("${spring.datasource.driver-class-name}")
private String driverClassName;
@NacosValue("${spring.datasource.url}")
private String url;
@NacosValue("${spring.datasource.username}")
private String username;
@NacosValue("${spring.datasource.password}")
private String password;
}

View File

@ -0,0 +1,21 @@
package cn.test;
import cn.config.MysqlNacosConf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Component
public class Demo {
@Autowired
private MysqlNacosConf mysqlNacosConf;
@GetMapping("/get")
public String get() {
System.out.println("nacosConfig.getDriverClassName() = " + mysqlNacosConf.getUrl());
return mysqlNacosConf.getUrl();
}
}

View File

@ -0,0 +1,6 @@
server:
port: 8080
nacos:
config:
server-addr: localhost:8848

20
old-cache-redis/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>old-cache-redis</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

28
old-face/pom.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>old-face</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.830</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,156 @@
/*
package com.guwan.controller;
import com.mapper.UserMapper;
import com.pojo.Result;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonRequest;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonResponse;
import com.tencentcloudapi.iai.v20200303.models.PersonExDescriptionInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
*/
/**
* @author: 顾挽
* @description:
* @create: 2024-09-06 15:31
**//*
@RequestMapping("/face")
@RestController
public class FaceController {
@Autowired
private UserMapper userMapper;
@PostMapping("/upload")
public Result uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam("username") String username,
@RequestParam("realName") String realName,
@RequestParam("idCard") String idCard) {
System.out.println("username: " + username);
System.out.println("realName: " + realName);
System.out.println("idCard: " + idCard);
if (file.isEmpty()) {
return Result.error("File is empty");
}
try{
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDrhdr2JYdZMzQf2KWiqx47Vps3KsOtQFC",
"8PByngyJZkgZGsRrGiLviSIKSnGlI427");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("iai.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
IaiClient client = new IaiClient(cred, "ap-beijing", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
CreatePersonRequest req = new CreatePersonRequest();
req.setGroupId("userRe");
req.setPersonName(username);
req.setPersonId(idCard);
PersonExDescriptionInfo[] personExDescriptionInfos1 = new PersonExDescriptionInfo[1];
PersonExDescriptionInfo personExDescriptionInfo1 = new PersonExDescriptionInfo();
personExDescriptionInfo1.setPersonExDescriptionIndex(0L);
personExDescriptionInfo1.setPersonExDescription(realName);
personExDescriptionInfos1[0] = personExDescriptionInfo1;
req.setPersonExDescriptionInfos(personExDescriptionInfos1);
byte[] fileBytes = file.getBytes();
// 将字节数组转换为 Base64 字符串
String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);
req.setImage(base64Encoded);
// 返回的resp是一个CreatePersonResponse的实例与请求对象对应
CreatePersonResponse resp = client.CreatePerson(req);
// 输出json格式的字符串回包
System.out.println(AbstractModel.toJsonString(resp));
if (resp.getFaceId() != null){
userMapper.changeFaceState(username);
try {
// 获取项目根目录
String rootDir = System.getProperty("user.dir");
// 确保上传目录存在
File uploadDir = new File(rootDir + File.separator + "uploads");
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 保存文件到上传目录
String filePath = uploadDir.getPath() + File.separator + file.getOriginalFilename();
file.transferTo(new File(filePath));
System.out.println("File uploaded successfully: " + filePath);
*/
/* return Result.success("File uploaded successfully: " + filePath);*//*
} catch (IOException e) {
e.printStackTrace();
*/
/* return Result.error("File upload failed");*//*
}
*/
/* return Result.success();*//*
}
return Result.success();
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
return Result.error(e.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
*/

View File

@ -0,0 +1,27 @@
package com.guwan.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}

30
old-nacos/pom.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>old-nacos</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.3.0-RC</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,20 @@
package config;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import lombok.Data;
@Data
@NacosPropertySource(dataId = "mysql", autoRefreshed = true)
public class MysqlNacosConf {
@NacosValue("${spring.datasource.driver-class-name}")
private String driverClassName;
@NacosValue("${spring.datasource.url}")
private String url;
@NacosValue("${spring.datasource.username}")
private String username;
@NacosValue("${spring.datasource.password}")
private String password;
}

108
pom.xml Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>
<groupId>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>old-cache-redis</module>
<module>old-nacos</module>
<module>old-app</module>
<module>old-face</module>
<module>login</module>
<module>ss-Demo</module>
</modules>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Spring Boot Starter Test (可选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId> <!-- 接口文档:使用最新版本的 Swagger 模型 -->
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<scope>provided</scope>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.32</version>
</dependency>
<!--mysql-db-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--mp-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.4.1</version>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
</dependencies>
</project>

20
ss-Demo/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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>com.guwan</groupId>
<artifactId>old</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>ss-Demo</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,19 @@
package com.guwan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableAsync
@EnableTransactionManagement
public class SsDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SsDemoApplication.class, args);
}
}

View File

@ -0,0 +1,26 @@
package com.guwan.controller;
import com.guwan.dal.dataobject.Order;
import com.guwan.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public void createOrder(@RequestBody Order order) {
orderService.createOrder(order);
}
@GetMapping("/{userId}")
public List<Order> getOrders(@PathVariable Long userId) {
return orderService.getOrdersByUserId(userId);
}
}

View File

@ -0,0 +1,10 @@
package com.guwan.dal.dataobject;
import lombok.Data;
@Data
public class Order {
private Long orderId;
private Long userId;
private String orderContent;
}

View File

@ -0,0 +1,15 @@
package com.guwan.dal.mysql;
import com.guwan.dal.dataobject.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface OrderMapper {
void insertOrder(Order order);
List<Order> selectOrdersByUserId(@Param("userId") Long userId);
}

View File

@ -0,0 +1,23 @@
package com.guwan.service;
import com.guwan.dal.dataobject.Order;
import com.guwan.dal.mysql.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
public void createOrder(Order order) {
orderMapper.insertOrder(order);
}
public List<Order> getOrdersByUserId(Long userId) {
return orderMapper.selectOrdersByUserId(userId);
}
}

View File

@ -0,0 +1,36 @@
spring:
profiles:
active: dev
application:
name: sharging-jdbc-demo
shardingsphere:
datasource:
names: master,slave1
master:
type: com.zaxxer.hikari.HikariDataSource # 数据源类型
url: jdbc:mysql://localhost:3306/course_master_db # 数据库连接地址
username: root # 用户名
password: 123456 # 密码
driver-class-name: com.mysql.jdbc.Driver # 数据库驱动
slave1:
type: com.zaxxer.hikari.HikariDataSource # 数据源类型
url: jdbc:mysql://localhost:3306/course_db # 数据库连接地址
username: root # 用户名
password: 123456 # 密码
driver-class-name: com.mysql.jdbc.Driver # 数据库驱动
rules:
readwrite-splitting:
data-sources:
mds: #名字自定义
type: static #类型 静态获取
props:
auto-aware-data-source-name: master
write-data-source-name: master
read-data-source-names: slave1
load-balancer-name: read-random #读写分离规则自定义命名
load-balancers:
read-random:
type: ROUND_ROBIN # 轮询负载均衡
props:
sql-show: true # 是否打印sql
sql-simple: true # 打印简单的sql

View File

@ -0,0 +1,12 @@
<?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.guwan.dal.mysql.OrderMapper">
<insert id="insertOrder" parameterType="com.guwan.dal.dataobject.Order">
INSERT INTO t_order (order_id, user_id, order_content) VALUES (#{orderId}, #{userId}, #{orderContent})
</insert>
<select id="selectOrdersByUserId" parameterType="Long" resultType="com.guwan.dal.dataobject.Order">
SELECT * FROM t_order WHERE user_id = #{userId}
</select>
</mapper>