优化代码格式
This commit is contained in:
parent
707a616bda
commit
fc69911580
4
pom.xml
4
pom.xml
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,48 @@ import java.util.Objects;
|
|||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AopLog {
|
public class AopLog {
|
||||||
|
/**
|
||||||
|
* 获取ip地址
|
||||||
|
*
|
||||||
|
* @param request 请求体
|
||||||
|
* @return 返回ip地址
|
||||||
|
*/
|
||||||
|
public static String getIp(HttpServletRequest request) {
|
||||||
|
String ip = request.getHeader("X-Forwarded-For");
|
||||||
|
if (isInvalidIp(ip)) {
|
||||||
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (isInvalidIp(ip)) {
|
||||||
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (isInvalidIp(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||||
|
}
|
||||||
|
if (isInvalidIp(ip)) {
|
||||||
|
ip = request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理多级代理
|
||||||
|
if (ip != null && ip.contains(",")) {
|
||||||
|
ip = ip.split(",")[0].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本地地址处理
|
||||||
|
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
|
||||||
|
try {
|
||||||
|
ip = InetAddress.getLocalHost().getHostAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
log.error("获取本地 IP 失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInvalidIp(String ip) {
|
||||||
|
return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切入点
|
* 切入点
|
||||||
*/
|
*/
|
||||||
@ -111,48 +153,6 @@ public class AopLog {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取ip地址
|
|
||||||
*
|
|
||||||
* @param request 请求体
|
|
||||||
* @return 返回ip地址
|
|
||||||
*/
|
|
||||||
public static String getIp(HttpServletRequest request) {
|
|
||||||
String ip = request.getHeader("X-Forwarded-For");
|
|
||||||
if (isInvalidIp(ip)) {
|
|
||||||
ip = request.getHeader("Proxy-Client-IP");
|
|
||||||
}
|
|
||||||
if (isInvalidIp(ip)) {
|
|
||||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
|
||||||
}
|
|
||||||
if (isInvalidIp(ip)) {
|
|
||||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
|
||||||
}
|
|
||||||
if (isInvalidIp(ip)) {
|
|
||||||
ip = request.getRemoteAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理多级代理
|
|
||||||
if (ip != null && ip.contains(",")) {
|
|
||||||
ip = ip.split(",")[0].trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 本地地址处理
|
|
||||||
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
|
|
||||||
try {
|
|
||||||
ip = InetAddress.getLocalHost().getHostAddress();
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
log.error("获取本地 IP 失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isInvalidIp(String ip) {
|
|
||||||
return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@ -12,70 +12,114 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum Status {
|
public enum Status {
|
||||||
/** 操作成功! */
|
/**
|
||||||
|
* 操作成功!
|
||||||
|
*/
|
||||||
SUCCESS(200, "操作成功!"),
|
SUCCESS(200, "操作成功!"),
|
||||||
|
|
||||||
/** 未知异常 */
|
/**
|
||||||
|
* 未知异常
|
||||||
|
*/
|
||||||
UNKNOWN_ERROR(500, "未知异常"),
|
UNKNOWN_ERROR(500, "未知异常"),
|
||||||
|
|
||||||
/** 退出成功! */
|
/**
|
||||||
|
* 退出成功!
|
||||||
|
*/
|
||||||
LOGOUT(200, "退出成功!"),
|
LOGOUT(200, "退出成功!"),
|
||||||
|
|
||||||
/** 登录成功! */
|
/**
|
||||||
|
* 登录成功!
|
||||||
|
*/
|
||||||
LOGIN_SUCCESS(200, "登录成功!"),
|
LOGIN_SUCCESS(200, "登录成功!"),
|
||||||
|
|
||||||
/** 请先登录! */
|
/**
|
||||||
|
* 请先登录!
|
||||||
|
*/
|
||||||
UNAUTHORIZED(401, "请先登录!"),
|
UNAUTHORIZED(401, "请先登录!"),
|
||||||
|
|
||||||
/** 暂无权限访问! */
|
/**
|
||||||
|
* 暂无权限访问!
|
||||||
|
*/
|
||||||
ACCESS_DENIED(403, "权限不足!"),
|
ACCESS_DENIED(403, "权限不足!"),
|
||||||
|
|
||||||
/** 请求不存在! */
|
/**
|
||||||
|
* 请求不存在!
|
||||||
|
*/
|
||||||
REQUEST_NOT_FOUND(404, "请求不存在!"),
|
REQUEST_NOT_FOUND(404, "请求不存在!"),
|
||||||
|
|
||||||
/** 请求方式不支持! */
|
/**
|
||||||
|
* 请求方式不支持!
|
||||||
|
*/
|
||||||
HTTP_BAD_METHOD(405, "请求方式不支持!"),
|
HTTP_BAD_METHOD(405, "请求方式不支持!"),
|
||||||
|
|
||||||
/** 请求异常! */
|
/**
|
||||||
|
* 请求异常!
|
||||||
|
*/
|
||||||
BAD_REQUEST(400, "请求异常!"),
|
BAD_REQUEST(400, "请求异常!"),
|
||||||
|
|
||||||
/** 参数不匹配! */
|
/**
|
||||||
|
* 参数不匹配!
|
||||||
|
*/
|
||||||
PARAM_NOT_MATCH(400, "参数不匹配!"),
|
PARAM_NOT_MATCH(400, "参数不匹配!"),
|
||||||
|
|
||||||
/** 参数不能为空! */
|
/**
|
||||||
|
* 参数不能为空!
|
||||||
|
*/
|
||||||
PARAM_NOT_NULL(400, "参数不能为空!"),
|
PARAM_NOT_NULL(400, "参数不能为空!"),
|
||||||
|
|
||||||
/** 当前用户已被锁定,请联系管理员解锁! */
|
/**
|
||||||
|
* 当前用户已被锁定,请联系管理员解锁!
|
||||||
|
*/
|
||||||
USER_DISABLED(403, "当前用户已被锁定,请联系管理员解锁!"),
|
USER_DISABLED(403, "当前用户已被锁定,请联系管理员解锁!"),
|
||||||
|
|
||||||
/** 用户名或密码错误! */
|
/**
|
||||||
|
* 用户名或密码错误!
|
||||||
|
*/
|
||||||
USERNAME_PASSWORD_ERROR(5001, "用户名或密码错误!"),
|
USERNAME_PASSWORD_ERROR(5001, "用户名或密码错误!"),
|
||||||
|
|
||||||
/** token 已过期,请重新登录! */
|
/**
|
||||||
|
* token 已过期,请重新登录!
|
||||||
|
*/
|
||||||
TOKEN_EXPIRED(5002, "token 已过期,请重新登录!"),
|
TOKEN_EXPIRED(5002, "token 已过期,请重新登录!"),
|
||||||
|
|
||||||
/** token 解析失败,请尝试重新登录! */
|
/**
|
||||||
|
* token 解析失败,请尝试重新登录!
|
||||||
|
*/
|
||||||
TOKEN_PARSE_ERROR(5002, "token 解析失败,请尝试重新登录!"),
|
TOKEN_PARSE_ERROR(5002, "token 解析失败,请尝试重新登录!"),
|
||||||
|
|
||||||
/** 当前用户已在别处登录,请尝试更改密码或重新登录! */
|
/**
|
||||||
|
* 当前用户已在别处登录,请尝试更改密码或重新登录!
|
||||||
|
*/
|
||||||
TOKEN_OUT_OF_CTRL(5003, "当前用户已在别处登录,请尝试更改密码或重新登录!"),
|
TOKEN_OUT_OF_CTRL(5003, "当前用户已在别处登录,请尝试更改密码或重新登录!"),
|
||||||
|
|
||||||
/** 无法手动踢出自己,请尝试退出登录操作! */
|
/**
|
||||||
|
* 无法手动踢出自己,请尝试退出登录操作!
|
||||||
|
*/
|
||||||
KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"),
|
KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"),
|
||||||
|
|
||||||
/** 账号密码错误 */
|
/**
|
||||||
|
* 账号密码错误
|
||||||
|
*/
|
||||||
USERNAME_OR_PASSWORD_ERROR(200, "账号密码错误"),
|
USERNAME_OR_PASSWORD_ERROR(200, "账号密码错误"),
|
||||||
|
|
||||||
/** 账户已被锁定 */
|
/**
|
||||||
|
* 账户已被锁定
|
||||||
|
*/
|
||||||
ACCOUNT_LOCKED(200, "账户已被锁定"),
|
ACCOUNT_LOCKED(200, "账户已被锁定"),
|
||||||
|
|
||||||
/** 注册成功! */
|
/**
|
||||||
|
* 注册成功!
|
||||||
|
*/
|
||||||
REGISTER_SUCCESS(200, "注册成功");
|
REGISTER_SUCCESS(200, "注册成功");
|
||||||
|
|
||||||
/** 状态码 */
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
private final Integer code;
|
private final Integer code;
|
||||||
|
|
||||||
/** 内容 */
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
Status(Integer code, String message) {
|
Status(Integer code, String message) {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package asia.yulinling.workflow.dto.request;
|
|||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 登录请求类
|
* 登录请求类
|
||||||
|
|||||||
@ -29,7 +29,8 @@ public class PageResult<T> implements Serializable {
|
|||||||
private int to; // 当前页最后一条数据在总数据中的位置
|
private int to; // 当前页最后一条数据在总数据中的位置
|
||||||
|
|
||||||
// 无参构造器
|
// 无参构造器
|
||||||
public PageResult() {}
|
public PageResult() {
|
||||||
|
}
|
||||||
|
|
||||||
// 构造方法(可选传参)
|
// 构造方法(可选传参)
|
||||||
public PageResult(long total, int currentPage, int pageSize, List<T> list) {
|
public PageResult(long total, int currentPage, int pageSize, List<T> list) {
|
||||||
|
|||||||
@ -4,23 +4,15 @@ import asia.yulinling.workflow.exception.PageException;
|
|||||||
import asia.yulinling.workflow.exception.ServiceException;
|
import asia.yulinling.workflow.exception.ServiceException;
|
||||||
import asia.yulinling.workflow.model.ApiResponse;
|
import asia.yulinling.workflow.model.ApiResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.FieldError;
|
|
||||||
import org.springframework.validation.ObjectError;
|
import org.springframework.validation.ObjectError;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 全局异常处理
|
* 全局异常处理
|
||||||
|
|||||||
@ -130,11 +130,6 @@ public class UserPrincipal implements UserDetails {
|
|||||||
this.authorities = authorities;
|
this.authorities = authorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserPrincipal(Long id,
|
public UserPrincipal(Long id,
|
||||||
String username,
|
String username,
|
||||||
String password,
|
String password,
|
||||||
@ -173,6 +168,10 @@ public class UserPrincipal implements UserDetails {
|
|||||||
return userPrincipal;
|
return userPrincipal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
package asia.yulinling.workflow.service;
|
package asia.yulinling.workflow.service;
|
||||||
|
|
||||||
import asia.yulinling.workflow.dto.request.LoginRequest;
|
|
||||||
import asia.yulinling.workflow.dto.request.RegisterRequest;
|
import asia.yulinling.workflow.dto.request.RegisterRequest;
|
||||||
import asia.yulinling.workflow.model.ApiResponse;
|
|
||||||
import asia.yulinling.workflow.model.vo.LoginVO;
|
import asia.yulinling.workflow.model.vo.LoginVO;
|
||||||
import asia.yulinling.workflow.model.vo.RegisterVO;
|
import asia.yulinling.workflow.model.vo.RegisterVO;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,17 +1,13 @@
|
|||||||
package asia.yulinling.workflow.service.impl;
|
package asia.yulinling.workflow.service.impl;
|
||||||
|
|
||||||
import asia.yulinling.workflow.constant.Status;
|
|
||||||
import asia.yulinling.workflow.dto.request.RegisterRequest;
|
import asia.yulinling.workflow.dto.request.RegisterRequest;
|
||||||
import asia.yulinling.workflow.mapper.UserMapper;
|
import asia.yulinling.workflow.mapper.UserMapper;
|
||||||
import asia.yulinling.workflow.model.ApiResponse;
|
|
||||||
import asia.yulinling.workflow.model.entity.User;
|
import asia.yulinling.workflow.model.entity.User;
|
||||||
import asia.yulinling.workflow.model.vo.LoginVO;
|
import asia.yulinling.workflow.model.vo.LoginVO;
|
||||||
import asia.yulinling.workflow.model.vo.RegisterVO;
|
import asia.yulinling.workflow.model.vo.RegisterVO;
|
||||||
import asia.yulinling.workflow.model.vo.user.UserPrincipal;
|
import asia.yulinling.workflow.model.vo.user.UserPrincipal;
|
||||||
import asia.yulinling.workflow.service.AuthService;
|
import asia.yulinling.workflow.service.AuthService;
|
||||||
import asia.yulinling.workflow.utils.JwtUtil;
|
import asia.yulinling.workflow.utils.JwtUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package asia.yulinling.workflow.service.impl;
|
|||||||
|
|
||||||
import asia.yulinling.workflow.service.MailService;
|
import asia.yulinling.workflow.service.MailService;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import jakarta.mail.MessagingException;
|
||||||
|
import jakarta.mail.internet.MimeMessage;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
@ -10,9 +12,6 @@ import org.springframework.mail.javamail.JavaMailSender;
|
|||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import jakarta.mail.internet.MimeMessage;
|
|
||||||
import jakarta.mail.MessagingException;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,7 +41,9 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class UserServiceImpl implements UserService {
|
public class UserServiceImpl implements UserService {
|
||||||
|
|
||||||
/** 注入用户Mapper */
|
/**
|
||||||
|
* 注入用户Mapper
|
||||||
|
*/
|
||||||
private final UserMapper userMapper;
|
private final UserMapper userMapper;
|
||||||
private final RequestScopeData scopeData;
|
private final RequestScopeData scopeData;
|
||||||
private final RoleUserMapper roleUserMapper;
|
private final RoleUserMapper roleUserMapper;
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
package asia.yulinling.workflow.task;
|
package asia.yulinling.workflow.task;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 定时任务
|
* 定时任务
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
SELECT * FROM wk_notes;
|
SELECT *
|
||||||
SELECT * FROM wk_attachments;
|
FROM wk_notes;
|
||||||
SELECT * FROM wk_note_tags;
|
SELECT *
|
||||||
SELECT * FROM wk_tags;
|
FROM wk_attachments;
|
||||||
SELECT * FROM wk_notebooks;
|
SELECT *
|
||||||
|
FROM wk_note_tags;
|
||||||
|
SELECT *
|
||||||
|
FROM wk_tags;
|
||||||
|
SELECT *
|
||||||
|
FROM wk_notebooks;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span style="text-align: center; padding: 10px">
|
<span style="text-align: center; padding: 10px">
|
||||||
<a style="text-decoration: none" href="#" th:href="@{${url}}" target="_blank">
|
<a href="#" style="text-decoration: none" target="_blank" th:href="@{${url}}">
|
||||||
<strong>Spring Boot入门首选</strong>
|
<strong>Spring Boot入门首选</strong>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
<head lang="en">
|
<head lang="en">
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<title>统一页面异常处理</title>
|
<title>统一页面异常处理</title>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span style="text-align: center; padding: 10px">
|
<span style="text-align: center; padding: 10px">
|
||||||
<a style="text-decoration: none" href="#" th:href="@{${url}}" target="_blank">
|
<a href="#" style="text-decoration: none" target="_blank" th:href="@{${url}}">
|
||||||
<strong>Spring Boot入门首选</strong>
|
<strong>Spring Boot入门首选</strong>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user