first commit

This commit is contained in:
jieyuu 2024-12-29 21:57:47 +08:00
commit 39f6b38e04
41 changed files with 2118 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

13
.idea/encodings.xml Normal file
View File

@ -0,0 +1,13 @@
<?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$/common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/pojo/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/pojo/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/server/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/server/src/main/resources" 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>

19
.idea/misc.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="ignoredFiles">
<set>
<option value="$PROJECT_DIR$/pojo/pom.xml" />
</set>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml Normal file
View File

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

6
.idea/vcs.xml Normal file
View File

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

73
common/pom.xml Normal file
View File

@ -0,0 +1,73 @@
<?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>net.carbon</groupId>
<artifactId>CarbonNeutrality</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--项目中添加 spring-boot-starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--swagger ui接口文档依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--用于加密-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- JWT相关 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,30 @@
package net.carbon.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 MybatisPlusPageConfig {
/* 旧版本配置
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}*/
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@ -0,0 +1,118 @@
package net.carbon.config;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.*;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
@Component
@EnableOpenApi
@Data
public class SwaggerConfiguration {
/**
* C端文档
* @return
*/
@Bean
public Docket webApiDoc() {
return new Docket(DocumentationType.OAS_30)
.groupName("用户端接口文档")
.pathMapping("/")
// 定义是否开启swaggerfalse为关闭可以通过变量控制线上关闭
.enable(true)
//配置api文档元信息
.apiInfo(apiInfo())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.basePackage("net.carbon"))
//正则匹配请求路径并分配至当前分组
.paths(PathSelectors.ant("/api/**"))
.build()
//新版swagger3.0配置
.globalRequestParameters(getGlobalRequestParameters())
.globalResponses(HttpMethod.GET, getGlobalResponseMessage())
.globalResponses(HttpMethod.POST, getGlobalResponseMessage());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("碳中和")
.description("接口文档")
.contact(new Contact("jieyuu", "https://106.52.88.120", "645634619@qq.com"))
.version("12")
.build();
}
/**
* 管理端文档
* @return
*/
@Bean
public Docket adminApiDoc() {
return new Docket(DocumentationType.OAS_30)
.groupName("管理端接口文档")
.pathMapping("/")
// 定义是否开启swaggerfalse为关闭可以通过变量控制线上关闭
.enable(true)
//配置api文档元信息
.apiInfo(apiInfo())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.basePackage("net.jieyuu"))
//正则匹配请求路径并分配至当前分组
.paths(PathSelectors.ant("/admin/**"))
.build();
}
/**
* 生成全局通用参数, 支持配置多个响应参数
* @return
*/
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("token")
.description("登录令牌")
.in(ParameterType.HEADER)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
// parameters.add(new RequestParameterBuilder()
// .name("version")
// .description("版本号")
// .required(true)
// .in(ParameterType.HEADER)
// .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
// .required(false)
// .build());
return parameters;
}
/**
* 生成通用响应信息
*
* @return
*/
private List<Response> getGlobalResponseMessage() {
List<Response> responseList = new ArrayList<>();
responseList.add(new ResponseBuilder().code("4xx").description("请求错误根据code和msg检查").build());
return responseList;
}
}

View File

@ -0,0 +1,62 @@
package net.carbon.enums;
import lombok.Getter;
/**
* @Description 状态码定义约束共6位数前三位代表服务后4位代表接口
* 比如 商品服务210,购物车是220用户服务230403代表权限
**/
public enum BizCodeEnum {
/**
* 通用操作码
*/
OPS_REPEAT(110001, "重复操作"),
/**
* 验证码
*/
CODE_TO_ERROR(240001, "接收号码不合规"),
CODE_LIMITED(240002, "验证码发送过快"),
CODE_ERROR(240003, "验证码错误"),
CODE_CAPTCHA(240101, "图形验证码错误"),
/**
* 账号
*/
ACCOUNT_REPEAT(250001, "账号已经存在"),
ACCOUNT_UNREGISTER(250002, "账号不存在"),
ACCOUNT_PWD_ERROR(250003, "账号或者密码错误"),
ACCOUNT_UNLOGIN(250004, "账号未登录"),
ILLEGAL_ARGUMENT(250005, "参数非法"),
/**
* 流控操作
*/
CONTROL_FLOW(500101, "限流控制"),
CONTROL_DEGRADE(500201, "降级控制"),
CONTROL_AUTH(500301, "认证控制");
@Getter
private int code;
@Getter
private String message;
private BizCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,25 @@
package net.carbon.exception;
import lombok.Data;
import net.carbon.enums.BizCodeEnum;
@Data
public class BizException extends RuntimeException {
private Integer code;
private String msg;
public BizException(Integer code, String message) {
super(message);
this.code = code;
this.msg = message;
}
public BizException(BizCodeEnum bizCodeEnum) {
super(bizCodeEnum.getMessage());
this.code = bizCodeEnum.getCode();
this.msg = bizCodeEnum.getMessage();
}
}

View File

@ -0,0 +1,30 @@
package net.carbon.handler;
import lombok.extern.slf4j.Slf4j;
import net.carbon.exception.BizException;
import net.carbon.utils.JsonData;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
@Slf4j
public class CustomExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonData Handle(Exception e) {
if (e instanceof BizException) {
BizException bizException = (BizException) e;
log.info("[业务异常]{}", e);
return JsonData.buildCodeAndMsg(bizException.getCode(), bizException.getMsg());
} else {
log.info("[系统异常]{}", e);
return JsonData.buildError("全局异常,未知错误");
}
}
}

View File

@ -0,0 +1,66 @@
package net.carbon.interceptor;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import net.carbon.enums.BizCodeEnum;
import net.carbon.model.LoginUser;
import net.carbon.utils.CommonUtil;
import net.carbon.utils.JWTUtil;
import net.carbon.utils.JsonData;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accessToken = request.getHeader("token");
if (accessToken == null) {
accessToken = request.getParameter("token");
}
//不为空
if (StringUtils.isNotBlank(accessToken)) {
Claims claims = JWTUtil.checkJWT(accessToken);
if (claims == null) {
//未登录
CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
return false;
}
long userId = Long.valueOf(claims.get("id").toString());
String name = (String) claims.get("username");
// LoginUser loginUser = new LoginUser();
LoginUser loginUser = LoginUser.builder()
.id(userId)
.username(name)
.build();
//通过threadlocal传递用户信息
threadLocal.set(loginUser);
return true;
}
//未登录
CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}

View File

@ -0,0 +1,23 @@
package net.carbon.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginUser {
/**
* 主键
*/
private Long id;
/**
* 名称
*/
private String username;
}

View File

@ -0,0 +1,39 @@
package net.carbon.result;
import lombok.Data;
import java.io.Serializable;
/**
* 后端统一返回结果
*
* @param <T>
*/
@Data
public class Result<T> implements Serializable {
private Integer code; // 编码1成功0和其它数字为失败
private String msg; // 错误信息
private T data; // 数据
public static <T> Result<T> success() {
Result<T> result = new Result<T>();
result.code = 1;
return result;
}
public static <T> Result<T> success(T object) {
Result<T> result = new Result<T>();
result.data = object;
result.code = 1;
return result;
}
public static <T> Result<T> error(String msg) {
Result<T> result = new Result<>();
result.msg = msg;
result.code = 0;
return result;
}
}

View File

@ -0,0 +1,83 @@
package net.carbon.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CheckUtil {
/**
* 邮箱正则
*/
private static final Pattern MAIL_PATTERN = Pattern.compile("^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$");
/**
* 手机号正则暂时未用
*/
private static final Pattern PHONE_PATTERN = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$");
/**
* 密码正则
* 只能包含字母大小写和数字
* 长度必须在6到16个字符之间
*/
private static final Pattern PASSWORD_PATTERN = Pattern.compile("^[a-zA-Z0-9]{6,16}$");
/**
* 用户名正则
* 用户名只能包含字母大小写和数字
* 用户名长度必须在6到16个字符之间
*/
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]{6,16}$");
/**
* @param email
* @return
*/
public static boolean isEmail(String email) {
if (null == email || "".equals(email)) {
return false;
}
Matcher m = MAIL_PATTERN.matcher(email);
return m.matches();
}
/**
* 手机号验证
* @param phone
* @return
*/
public static boolean isPhone(String phone) {
if (null == phone || "".equals(phone)) {
return false;
}
Matcher m = PHONE_PATTERN.matcher(phone);
return m.matches();
}
/**
* 密码验证
* @param password
* @return
*/
public static boolean isPassword(String password) {
if (null == password || "".equals(password)) {
return false;
}
Matcher m = PASSWORD_PATTERN.matcher(password);
return m.matches();
}
/**
* 用户名验证
* @param username
* @return
*/
public static boolean isUsername(String username) {
if (null == username || "".equals(username)) {
return false;
}
Matcher m = USERNAME_PATTERN.matcher(username);
return m.matches();
}
}

View File

@ -0,0 +1,165 @@
package net.carbon.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.Random;
import java.util.UUID;
@Slf4j
public class CommonUtil {
/**
* 获取ip
*
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
// "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
/**
* MD5加密
*
* @param data
* @return
*/
public static String MD5(String data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
} catch (Exception exception) {
}
return null;
}
/**
* 生成随机数
*
* @param length
* @return
*/
public static String getRandomCode(int length) {
String sources = "0123456789";
Random random = new Random();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(sources.charAt(random.nextInt(9)));
}
return stringBuilder.toString();
}
/**
* 生成UUID
*
* @return
*/
public static String generateUUID() {
return UUID.randomUUID().toString()
//删除-
.replaceAll("-", "")
//截取前32位
.substring(0, 32);
}
/**
* 获取当前时间戳
*
* @return
*/
public static long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* 生成指定长度随机串
*
* @param length
* @return
*/
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String getStringNumRandom(int length) {
//生成随机数字和字母,
Random random = new Random();
StringBuilder saltString = new StringBuilder(length);
for (int i = 1; i <= length; ++i) {
saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
}
return saltString.toString();
}
/**
* 响应json数据给前端
* @param response
* @param obj
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
response.setContentType("application/json; charset=utf-8");
try(PrintWriter writer=response.getWriter()){
writer.print(objectMapper.writeValueAsString(obj));
writer.close();
response.flushBuffer();
}catch(IOException e){
log.warn("响应json数据给前端异常:{}",e);
}
}
}

View File

@ -0,0 +1,76 @@
package net.carbon.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import net.carbon.model.LoginUser;
import java.util.Date;
@Slf4j
public class JWTUtil {
/**
* 过期时间
* 1000毫秒 * 60秒 * 60分钟 * 24小时 * 7天 * 10
*/
private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7 * 10;
/**
* 加密密钥
*/
private static final String SECRET = "net.carbon.xyz";
/**
* 令牌前缀
*/
private static final String TOKEN_PREFIX = "carbon";
/**
* 令牌前缀
*/
private static final String SUBJECT = "carbonemission";
/**
* 根据用户信息生成令牌
*
* @param user
* @return
*/
public static String geneJsonWebToken(LoginUser user) {
Long userId = user.getId();
String token = Jwts.builder().setSubject(SUBJECT)
.claim("id", userId)
.claim("username", user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(SignatureAlgorithm.HS256, SECRET).compact();
token = TOKEN_PREFIX + token;
return token;
}
/**
* 校验token的方法
*
* @param token
* @return
*/
public static Claims checkJWT(String token) {
try {
final Claims claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody();
return claims;
} catch (Exception e) {
log.info("jwt token解密失败");
return null;
}
}
}

View File

@ -0,0 +1,90 @@
package net.carbon.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.carbon.enums.BizCodeEnum;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonData {
/**
* 状态码 0 表示成功1表示处理中-1表示失败
*/
private Integer code;
/**
* 数据
*/
private Object data;
/**
* 描述
*/
private String msg;
/**
* 获取远程调用数据对象
* 注意 支持多单词下划线转驼峰(序列化和反序列化)
* 空对象不序列化
*/
public <T> T getData(TypeReference<T> typeReference) {
return JSON.parseObject(JSON.toJSONString(data), typeReference);
}
/**
* 成功传入数据
*
* @return
*/
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
/**
* 成功传入数据
*
* @param data
* @return
*/
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
/**
* 失败传入描述信息
*
* @param msg
* @return
*/
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
/**
* 自定义状态码和错误信息
*
* @param code
* @param msg
* @return
*/
public static JsonData buildCodeAndMsg(int code, String msg) {
return new JsonData(code, null, msg);
}
/**
* 传入枚举返回信息
*
* @param codeEnum
* @return
*/
public static JsonData buildResult(BizCodeEnum codeEnum) {
return JsonData.buildCodeAndMsg(codeEnum.getCode(), codeEnum.getMessage());
}
}

173
pom.xml Normal file
View File

@ -0,0 +1,173 @@
<?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>net.carbon</groupId>
<artifactId>CarbonNeutrality</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>server</module>
</modules>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.boot.version>2.3.3.RELEASE</spring.boot.version>
<mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
<lombok.version>1.18.16</lombok.version>
<commons.lang3.version>3.9</commons.lang3.version>
<commons.codec.version>1.15</commons.codec.version>
<springfox.boot.starter.version>3.0.0</springfox.boot.starter.version>
<jjwt.version>0.7.0</jjwt.version>
<velocity-engine-core.version>2.0</velocity-engine-core.version>
<fastjson.version>1.2.62</fastjson.version>
<!--跳过单元测试-->
<skipTests>true</skipTests>
</properties>
<!--锁定版本-->
<dependencyManagement>
<dependencies>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/2.3.3.RELEASE-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mybatis plus和springboot整合-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.boot.starter.version}</version>
</dependency>
<!--https://mvnrepository.com/artifact/org.projectlombok/lombok/1.18.16-->
<!--scope=provided说明它只在编译阶段生效不需要打入包中, Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<!-- <scope>provided</scope>-->
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<!--用于加密-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons.codec.version}</version>
</dependency>
<!--接口文档依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.boot.starter.version}</version>
</dependency>
<!-- JWT相关 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity-engine-core.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--swagger ui接口文档依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.boot.starter.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 代码库 -->
<repositories>
<repository>
<id>maven-ali</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<!--module不用添加打包版本信息-->
<build>
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- <version>${spring.boot.version}</version>-->
<!-- <configuration>-->
<!-- <fork>true</fork>-->
<!-- <addResources>true</addResources>-->
<!-- </configuration>-->
<!-- </plugin>-->
<!-- </plugins>-->
</build>
</project>

55
server/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<?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>net.carbon</groupId>
<artifactId>CarbonNeutrality</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>server</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.carbon</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 代码自动生成依赖 begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
package net.carbon;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("net.carbon.mapper")
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}

View File

@ -0,0 +1,24 @@
package net.carbon.config;
import lombok.extern.slf4j.Slf4j;
import net.carbon.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@Slf4j
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry
.addInterceptor(new LoginInterceptor())
//拦截的路径
// .addPathPatterns("/api/user/*/**", "/api/**/*/**")
//放行的路径
.excludePathPatterns("/api/user/*/register", "/api/user/*/login");
WebMvcConfigurer.super.addInterceptors(registry);
}
}

View File

@ -0,0 +1,48 @@
package net.carbon.controller;
import net.carbon.service.CarbonEmissionService;
import net.carbon.utils.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 前端控制器
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
@RestController
@RequestMapping("/api/carbon/v1")
public class CarbonEmissionController {
@Autowired
private CarbonEmissionService carbonEmissionService;
/**
* 及时预警接口
*
* @param city
* @return
*/
@GetMapping("timelyAlert")
public JsonData timelyAlert(@RequestBody String city) {
return JsonData.buildSuccess(carbonEmissionService.timelyAlert(city));
}
/**
* 获取数据
*
* @param city
* @return
*/
@GetMapping("getCarbonEmissionData")
public JsonData getCarbonEmissionData(@RequestBody String city) {
return JsonData.buildSuccess(carbonEmissionService.getCarbonEmissionData(city));
}
}

View File

@ -0,0 +1,57 @@
// 用户登录demo
package net.carbon.controller;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.carbon.request.UserRegisterRequest;
import net.carbon.request.UserLoginRequest;
import net.carbon.service.UserService;
import net.carbon.utils.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping("/api/user/v1")
public class UserController {
@Autowired
private UserService userService;
/**
* 用户注册
*
* @param registerRequest
* @return
*/
@ApiOperation("用户注册")
@PostMapping(value = "register")
public JsonData register(
@ApiParam(value = "用户注册对象", required = true)
@RequestBody UserRegisterRequest registerRequest) {
JsonData jsonData = userService.register(registerRequest);
return jsonData;
}
/**
* 用户登录
*
* @param loginRequest
* @return
*/
@ApiOperation("用户登录")
@PostMapping("login")
public JsonData userLogin(@ApiParam("用户登陆对象") @RequestBody UserLoginRequest loginRequest) {
JsonData jsonData = userService.login(loginRequest);
return jsonData;
}
}

View File

@ -0,0 +1,16 @@
package net.carbon.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.carbon.model.CarbonEmissionDO;
/**
* <p>
* Mapper 接口
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
public interface CarbonEmissionMapper extends BaseMapper<CarbonEmissionDO> {
}

View File

@ -0,0 +1,17 @@
package net.carbon.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.carbon.model.UserDO;
/**
* <p>
* Mapper 接口
* </p>
*
* @author jieyuu
* @since 2024-11-23
*/
public interface UserMapper extends BaseMapper<UserDO> {
}

View File

@ -0,0 +1,61 @@
package net.carbon.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* <p>
*
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("carbon_emission")
public class CarbonEmissionDO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String city;
private BigDecimal wastewaterDischargeTotal;
private BigDecimal airQualityAchievementRate;
private BigDecimal gdpElectricityConsumption;
private BigDecimal wasteResourceIndustryValue;
private BigDecimal forestCoverageRate;
private BigDecimal ecologicalIndex;
private BigDecimal importExportTotal;
private Integer foreignInvestmentEnterprises;
private BigDecimal tourismIncome;
private Integer overnightTourists;
private BigDecimal publicManagementDensity;
private BigDecimal perCapitaServiceFunds;
private BigDecimal averageAnnualSalary;
private BigDecimal urbanPerCapitaIncome;
}

View File

@ -0,0 +1,31 @@
package net.carbon.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author jieyuu
* @since 2024-11-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("user")
public class UserDO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String username;
private String password;
}

View File

@ -0,0 +1,20 @@
package net.carbon.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@ApiModel(value = "登录对象", description = "用户登录请求对象")
@AllArgsConstructor
@NoArgsConstructor
public class UserLoginRequest {
@ApiModelProperty(value = "用户名", example = "jieyuu")
private String username;
@ApiModelProperty(value = "密码", example = "123456")
private String password;
}

View File

@ -0,0 +1,17 @@
package net.carbon.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "用户注册实体类")
public class UserRegisterRequest {
@ApiModelProperty(value = "用户名", example = "123456")
private String username;
@ApiModelProperty(value = "密码", example = "123456")
private String password;
}

View File

@ -0,0 +1,22 @@
package net.carbon.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.carbon.model.CarbonEmissionDO;
import net.carbon.vo.CarbonVO;
/**
* <p>
* 服务类
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
public interface CarbonEmissionService extends IService<CarbonEmissionDO> {
public Object timelyAlert(String city);
CarbonVO getCarbonEmissionData(String city);
}

View File

@ -0,0 +1,36 @@
package net.carbon.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.carbon.model.UserDO;
import net.carbon.request.UserRegisterRequest;
import net.carbon.request.UserLoginRequest;
import net.carbon.utils.JsonData;
/**
* <p>
* 服务类
* </p>
*
* @author jieyuu
* @since 2024-11-23
*/
public interface UserService extends IService<UserDO> {
/**
* 用户注册
*
* @param userRegisterRequest
* @return
*/
JsonData register(UserRegisterRequest userRegisterRequest);
/**
* 用户登录
*
* @param loginRequest
* @return
*/
JsonData login(UserLoginRequest loginRequest);
}

View File

@ -0,0 +1,63 @@
package net.carbon.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.carbon.mapper.CarbonEmissionMapper;
import net.carbon.model.CarbonEmissionDO;
import net.carbon.service.CarbonEmissionService;
import net.carbon.vo.CarbonTimelyAlertVO;
import net.carbon.vo.CarbonVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
@Service
public class CarbonEmissionServiceImpl extends ServiceImpl<CarbonEmissionMapper, CarbonEmissionDO> implements CarbonEmissionService {
@Autowired
private CarbonEmissionMapper carbonEmissionMapper;
@Override
public CarbonTimelyAlertVO timelyAlert(String city) {
if (city == null || StringUtils.isBlank(city)) {
return null;
}
QueryWrapper<CarbonEmissionDO> queryWrapper = new QueryWrapper<>();
queryWrapper.like("city", city);
CarbonEmissionDO carbonEmissionDO = carbonEmissionMapper.selectOne(queryWrapper);
CarbonTimelyAlertVO result = new CarbonTimelyAlertVO();
BeanUtils.copyProperties(carbonEmissionDO, result);
return result;
}
@Override
public CarbonVO getCarbonEmissionData(String city) {
if (city == null || StringUtils.isBlank(city)) {
return null;
}
QueryWrapper<CarbonEmissionDO> queryWrapper = new QueryWrapper<>();
queryWrapper.like("city", city);
CarbonEmissionDO carbonEmissionDO = carbonEmissionMapper.selectOne(queryWrapper);
CarbonVO result = new CarbonVO();
BeanUtils.copyProperties(carbonEmissionDO, result);
return result;
}
}

View File

@ -0,0 +1,122 @@
package net.carbon.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.carbon.enums.BizCodeEnum;
import net.carbon.mapper.UserMapper;
import net.carbon.model.LoginUser;
import net.carbon.model.UserDO;
import net.carbon.request.UserRegisterRequest;
import net.carbon.request.UserLoginRequest;
import net.carbon.service.UserService;
import net.carbon.utils.CheckUtil;
import net.carbon.utils.CommonUtil;
import net.carbon.utils.JWTUtil;
import net.carbon.utils.JsonData;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author jieyuu
* @since 2024-11-23
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
@Transactional(rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRED)
public JsonData register(UserRegisterRequest registerRequest) {
UserDO userDO = new UserDO();
BeanUtils.copyProperties(registerRequest, userDO);
String cryptPwd = CommonUtil.MD5(userDO.getPassword());
userDO.setPassword(cryptPwd);
if (CheckUtil.isUsername(registerRequest.getUsername()) ||
CheckUtil.isPassword(registerRequest.getPassword())) {
//账号唯一性检查
if (checkUnique(userDO.getUsername())) {
//插入数据库
int rows = userMapper.insert(userDO);
log.info("rows:{},注册成功{}", rows, userDO.toString());
return JsonData.buildSuccess();
} else {
return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
}
} else {
return JsonData.buildResult(BizCodeEnum.ILLEGAL_ARGUMENT);
}
}
/**
* 校验用户账号唯一
*
* @param username
* @return
*/
private boolean checkUnique(String username) {
QueryWrapper queryWrapper = new QueryWrapper<UserDO>().eq("username", username);
List<UserDO> list = userMapper.selectList(queryWrapper);
return list.size() > 0 ? false : true;
}
/**
* 用户登陆注册
* <p>
* 判断用户注册情况
*
* @param loginRequest
* @return
*/
@Override
public JsonData login(UserLoginRequest loginRequest) {
List<UserDO> userDOList = userMapper.selectList(new QueryWrapper<UserDO>().eq("username", loginRequest.getUsername()));
if (userDOList != null && userDOList.size() == 1) {
//已经注册
UserDO userDO = userDOList.get(0);
String cryptPwd = CommonUtil.MD5(loginRequest.getPassword());
if (cryptPwd.equals(userDO.getPassword())) {
//登陆成功
//生成token令牌并且返回
LoginUser loginUser = LoginUser.builder().build();
BeanUtils.copyProperties(userDO, loginUser);
//accessToken
String accessToken = JWTUtil.geneJsonWebToken(loginUser);
// accessToken过期时间
//UUID生成一个token
return JsonData.buildSuccess(accessToken);
} else {
return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
}
} else {
//未注册
//这里选择 账号或密码错误防止被爆破
return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
}
}
}

View File

@ -0,0 +1,50 @@
package net.carbon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* <p>
*
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class CarbonTimelyAlertVO {
private String city;
private BigDecimal wastewaterDischargeTotal;
private BigDecimal airQualityAchievementRate;
private BigDecimal gdpElectricityConsumption;
private BigDecimal wasteResourceIndustryValue;
private BigDecimal forestCoverageRate;
private BigDecimal ecologicalIndex;
private BigDecimal importExportTotal;
private Integer foreignInvestmentEnterprises;
private BigDecimal tourismIncome;
private Integer overnightTourists;
private BigDecimal publicManagementDensity;
private BigDecimal perCapitaServiceFunds;
private BigDecimal averageAnnualSalary;
private BigDecimal urbanPerCapitaIncome;
}

View File

@ -0,0 +1,42 @@
package net.carbon.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* <p>
*
* </p>
*
* @author jieyuu
* @since 2024-12-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class CarbonVO {
private String city;
private BigDecimal wastewaterDischargeTotal;
private BigDecimal airQualityAchievementRate;
private BigDecimal gdpElectricityConsumption;
private BigDecimal wasteResourceIndustryValue;
private BigDecimal forestCoverageRate;
private BigDecimal ecologicalIndex;
private BigDecimal importExportTotal;
private Integer foreignInvestmentEnterprises;
}

View File

@ -0,0 +1,19 @@
server:
port: 8089
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://106.52.88.120:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 59ae8683c59fead903132a8d440bd7d9fd4936529d1d6f45f9d41111d7537bdd
#配置plus打印sql日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#设置日志级别,ERROR/WARN/INFO/DEBUG,默认是INFO以上才显示
logging:
level:
root: INFO

View File

@ -0,0 +1,30 @@
<?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="net.carbon.mapper.CarbonEmissionMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="net.carbon.model.CarbonEmissionDO">
<id column="id" property="id" />
<result column="city" property="city" />
<result column="wastewater_discharge_total" property="wastewaterDischargeTotal" />
<result column="air_quality_achievement_rate" property="airQualityAchievementRate" />
<result column="gdp_electricity_consumption" property="gdpElectricityConsumption" />
<result column="waste_resource_industry_value" property="wasteResourceIndustryValue" />
<result column="forest_coverage_rate" property="forestCoverageRate" />
<result column="ecological_index" property="ecologicalIndex" />
<result column="import_export_total" property="importExportTotal" />
<result column="foreign_investment_enterprises" property="foreignInvestmentEnterprises" />
<result column="tourism_income" property="tourismIncome" />
<result column="overnight_tourists" property="overnightTourists" />
<result column="public_management_density" property="publicManagementDensity" />
<result column="per_capita_service_funds" property="perCapitaServiceFunds" />
<result column="average_annual_salary" property="averageAnnualSalary" />
<result column="urban_per_capita_income" property="urbanPerCapitaIncome" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, city, wastewater_discharge_total, air_quality_achievement_rate, gdp_electricity_consumption, waste_resource_industry_value, forest_coverage_rate, ecological_index, import_export_total, foreign_investment_enterprises, tourism_income, overnight_tourists, public_management_density, per_capita_service_funds, average_annual_salary, urban_per_capita_income
</sql>
</mapper>

View File

@ -0,0 +1,18 @@
<?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="net.carbon.mapper.UserMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="net.carbon.model.UserDO">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id
, username, password
</sql>
</mapper>

View File

@ -0,0 +1,91 @@
package net.jieyuu.db;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class MyBatisPlusGenerator {
public static void main(String[] args) {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
// 是否支持AR模式
config.setActiveRecord(true)
// 作者
.setAuthor("jieyuu")
// 生成路径最好使用绝对路径window路径是不一样的
.setOutputDir("D:\\workspace\\project\\CarbonNeutrality\\server\\src\\main\\java")
// 文件覆盖
.setFileOverride(true)
// 主键策略
.setIdType(IdType.AUTO)
.setDateType(DateType.ONLY_DATE)
// 设置生成的service接口的名字的首字母是否为I默认Service是以I开头的
.setServiceName("%sService")
//实体类结尾名称
.setEntityName("%sDO")
//生成基本的resultMap
.setBaseResultMap(true)
//不使用AR模式
.setActiveRecord(false)
//生成基本的SQL片段
.setBaseColumnList(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
// 设置数据库类型
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
.setUrl("jdbc:mysql://106.52.88.120:3306/demo?useSSL=false")
.setUsername("root")
.setPassword("59ae8683c59fead903132a8d440bd7d9fd4936529d1d6f45f9d41111d7537bdd");
//3. 策略配置globalConfiguration中
StrategyConfig stConfig = new StrategyConfig();
//全局大写命名
stConfig.setCapitalMode(true)
// 数据库表映射到实体的命名策略
.setNaming(NamingStrategy.underline_to_camel)
//使用lombok
.setEntityLombokModel(true)
//使用restcontroller注解
.setRestControllerStyle(true)
// 生成的表, 支持多表一起生成以数组形式填写
.setInclude("carbon_emission");
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("net.jieyuu")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("model")
.setXml("mapper");
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 执行操作
ag.execute();
System.out.println("======= Done 相关代码生成完毕 ========");
}
}