add Notebook
This commit is contained in:
parent
f46f6d97e1
commit
717c3509b4
@ -29,11 +29,11 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 使用 aop 切面记录请求日志信息
|
||||
* 使用 aop 切面记录请求日志信息
|
||||
* </p>
|
||||
*
|
||||
* @author yulinling
|
||||
* @since 2025/6/5
|
||||
* @since 2025/6/5
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@ -87,6 +87,7 @@ public class AopLog {
|
||||
|
||||
/**
|
||||
* 获取方法参数名和参数值
|
||||
*
|
||||
* @param joinPoint 切入点
|
||||
* @return 接口参数和参数值
|
||||
*/
|
||||
@ -112,6 +113,7 @@ public class AopLog {
|
||||
|
||||
/**
|
||||
* 获取ip地址
|
||||
*
|
||||
* @param request 请求体
|
||||
* @return 返回ip地址
|
||||
*/
|
||||
@ -150,6 +152,7 @@ public class AopLog {
|
||||
private static boolean isInvalidIp(String ip) {
|
||||
return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip);
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
||||
@ -60,6 +60,7 @@ public class SecurityConfig {
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/auth/**").permitAll()
|
||||
.requestMatchers("/auth/register").permitAll()
|
||||
.requestMatchers("/api/**").permitAll()
|
||||
// .requestMatchers("/user/**").permitAll()
|
||||
.anyRequest().access((authenticationSupplier, requestAuthorizationContext) -> {
|
||||
HttpServletRequest request = requestAuthorizationContext.getRequest();
|
||||
|
||||
@ -63,6 +63,12 @@ public enum Status {
|
||||
/** 无法手动踢出自己,请尝试退出登录操作! */
|
||||
KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"),
|
||||
|
||||
/** 账号密码错误 */
|
||||
USERNAME_OR_PASSWORD_ERROR(200, "账号密码错误"),
|
||||
|
||||
/** 账户已被锁定 */
|
||||
ACCOUNT_LOCKED(200, "账户已被锁定"),
|
||||
|
||||
/** 注册成功! */
|
||||
REGISTER_SUCCESS(200, "注册成功");
|
||||
|
||||
|
||||
@ -1,13 +1,25 @@
|
||||
package asia.yulinling.workflow.controller;
|
||||
|
||||
import asia.yulinling.workflow.constant.Status;
|
||||
import asia.yulinling.workflow.dto.request.LoginRequest;
|
||||
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.RegisterVO;
|
||||
import asia.yulinling.workflow.service.AuthService;
|
||||
import asia.yulinling.workflow.utils.JwtUtil;
|
||||
import com.alibaba.druid.support.spring.stat.annotation.Stat;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -27,15 +39,33 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
private final JwtUtil jwtUtil;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<LoginVO> login(@RequestBody LoginRequest loginRequest) {
|
||||
return authService.login(loginRequest);
|
||||
public ResponseEntity<ApiResponse<LoginVO>> login(@Valid @RequestBody LoginRequest loginRequest) {
|
||||
try {
|
||||
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
|
||||
loginRequest.getUsername(), loginRequest.getPassword()
|
||||
));
|
||||
|
||||
LoginVO loginVO = authService.login(authentication, loginRequest.getRememberMe());
|
||||
return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO));
|
||||
} catch (BadCredentialsException e) {
|
||||
return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.USERNAME_PASSWORD_ERROR));
|
||||
} catch (LockedException e) {
|
||||
return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.ACCOUNT_LOCKED));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException {
|
||||
return authService.logout(request);
|
||||
public ApiResponse<?> logout(HttpServletRequest request) {
|
||||
String token = jwtUtil.getTokenFromRequest(request);
|
||||
if (token == null || token.isBlank()) {
|
||||
return ApiResponse.ofStatus(Status.TOKEN_EXPIRED);
|
||||
}
|
||||
authService.logout(token);
|
||||
return ApiResponse.ofStatus(Status.SUCCESS);
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package asia.yulinling.workflow.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Slf4j
|
||||
@RequestMapping("/api22")
|
||||
public class NoteController {
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package asia.yulinling.workflow.controller;
|
||||
|
||||
import asia.yulinling.workflow.constant.Status;
|
||||
import asia.yulinling.workflow.dto.request.NotebookRequest;
|
||||
import asia.yulinling.workflow.model.ApiResponse;
|
||||
import asia.yulinling.workflow.model.entity.Notebook;
|
||||
import asia.yulinling.workflow.service.NotebookService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@RequestMapping("/api")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class NotebookController {
|
||||
private final NotebookService notebookService;
|
||||
|
||||
@PostMapping("/notebooks")
|
||||
public ApiResponse<?> notebooks(@Valid @RequestBody NotebookRequest notebookRequest) {
|
||||
Notebook notebook = new Notebook();
|
||||
BeanUtils.copyProperties(notebookRequest, notebook);
|
||||
notebookService.addNotebook(notebook);
|
||||
return ApiResponse.ofStatus(Status.SUCCESS);
|
||||
}
|
||||
|
||||
@GetMapping("/notebooks")
|
||||
public void notebooksGet() {
|
||||
}
|
||||
|
||||
@GetMapping("/notebooks/{id}")
|
||||
public void notebooksGet(@PathVariable String id) {
|
||||
}
|
||||
|
||||
@PutMapping("/notebooks/{id}")
|
||||
public void notebooksPut(@PathVariable String id) {
|
||||
}
|
||||
|
||||
@DeleteMapping("/notebooks/{id}")
|
||||
public void notebooksDelete(@PathVariable String id) {
|
||||
}
|
||||
}
|
||||
@ -37,6 +37,7 @@ public class TestController {
|
||||
|
||||
/**
|
||||
* 测试方法 GET
|
||||
*
|
||||
* @param who 测试参数
|
||||
* @return {@link Dict}
|
||||
*/
|
||||
@ -47,6 +48,7 @@ public class TestController {
|
||||
|
||||
/**
|
||||
* 测试方法 POST
|
||||
*
|
||||
* @param map 请求的json参数
|
||||
* @return {@link Dict}
|
||||
*/
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package asia.yulinling.workflow.dto.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class NotebookRequest {
|
||||
/**
|
||||
* 用户id,外键
|
||||
*/
|
||||
@NotBlank(message = "创建用户为空")
|
||||
Long userId;
|
||||
|
||||
/**
|
||||
* 笔记本名称
|
||||
*/
|
||||
@NotBlank(message = "笔记本名称为空")
|
||||
String name;
|
||||
|
||||
/**
|
||||
* 笔记本颜色标识
|
||||
*/
|
||||
String color;
|
||||
|
||||
/**
|
||||
* 笔记本图标标识
|
||||
*/
|
||||
String icon;
|
||||
}
|
||||
16
src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java
Normal file
16
src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java
Normal file
@ -0,0 +1,16 @@
|
||||
package asia.yulinling.workflow.mapper;
|
||||
|
||||
import asia.yulinling.workflow.model.entity.Note;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 笔记本Mapper
|
||||
* </p>
|
||||
*
|
||||
* @author YLL
|
||||
* @since 2025/7/23
|
||||
*/
|
||||
public interface NoteMapper extends BaseMapper<Note> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package asia.yulinling.workflow.mapper;
|
||||
|
||||
import asia.yulinling.workflow.model.entity.Notebook;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 笔记本集合Mapper
|
||||
* </p>
|
||||
*
|
||||
* @author YLL
|
||||
* @since 2025/6/13
|
||||
*/
|
||||
@Mapper
|
||||
@Component
|
||||
public interface NotebookMapper extends BaseMapper<Notebook> {
|
||||
}
|
||||
99
src/main/java/asia/yulinling/workflow/model/entity/Note.java
Normal file
99
src/main/java/asia/yulinling/workflow/model/entity/Note.java
Normal file
@ -0,0 +1,99 @@
|
||||
package asia.yulinling.workflow.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class Note {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
Long id;
|
||||
|
||||
/**
|
||||
* 用户id,外键
|
||||
*/
|
||||
@TableField("user_id")
|
||||
Long userId;
|
||||
|
||||
/**
|
||||
* 笔记本id,外键
|
||||
*/
|
||||
@TableField("notebook_id")
|
||||
Long notebookId;
|
||||
|
||||
/**
|
||||
* 笔记标题
|
||||
*/
|
||||
String title;
|
||||
|
||||
/**
|
||||
* 笔记本内容
|
||||
*/
|
||||
String content;
|
||||
|
||||
/**
|
||||
* 笔记本内容预览,截取前200字符
|
||||
*/
|
||||
@TableField("preview_text")
|
||||
String previewText;
|
||||
|
||||
/**
|
||||
* 笔记内容字数统计
|
||||
*/
|
||||
@TableField("word_count")
|
||||
Integer wordCount;
|
||||
|
||||
/**
|
||||
* 是否置顶显示
|
||||
*/
|
||||
@TableField("is_pinned")
|
||||
Boolean isPinned;
|
||||
|
||||
/**
|
||||
* 是否归档(不显示在默认列表中)
|
||||
*/
|
||||
@TableField("is_archived")
|
||||
Boolean isArchived;
|
||||
|
||||
/**
|
||||
* 是否标记为收藏
|
||||
*/
|
||||
@TableField("is_favorite")
|
||||
Boolean isFavorite;
|
||||
|
||||
/**
|
||||
* 是否需要密码查看
|
||||
*/
|
||||
@TableField("password_protected")
|
||||
Boolean passwordProtected;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
Date updateTime;
|
||||
|
||||
/**
|
||||
* 提醒时间
|
||||
*/
|
||||
@TableField("reminder")
|
||||
Date reminderTime;
|
||||
|
||||
/**
|
||||
* 笔记封面图片url
|
||||
*/
|
||||
@TableField("cover_image")
|
||||
String coverImage;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package asia.yulinling.workflow.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("wk_notebooks")
|
||||
public class Notebook {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
Long id;
|
||||
|
||||
/**
|
||||
* 用户id,外键
|
||||
*/
|
||||
@TableField("user_id")
|
||||
Long userId;
|
||||
|
||||
/**
|
||||
* 笔记本名称
|
||||
*/
|
||||
String name;
|
||||
|
||||
/**
|
||||
* 笔记本颜色标识
|
||||
*/
|
||||
String color;
|
||||
|
||||
/**
|
||||
* 笔记本图标标识
|
||||
*/
|
||||
String icon;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("created_at")
|
||||
Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField("update_at")
|
||||
Date updateTime;
|
||||
|
||||
/**
|
||||
* 笔记本内的笔记数量
|
||||
*/
|
||||
Integer notesCount;
|
||||
}
|
||||
@ -6,6 +6,7 @@ import asia.yulinling.workflow.model.ApiResponse;
|
||||
import asia.yulinling.workflow.model.vo.LoginVO;
|
||||
import asia.yulinling.workflow.model.vo.RegisterVO;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -19,18 +20,16 @@ public interface AuthService {
|
||||
/**
|
||||
* 登录系统
|
||||
*
|
||||
* @param loginRequest 登录请求
|
||||
* @return token
|
||||
* @param authentication 登录信息
|
||||
*/
|
||||
ApiResponse<LoginVO> login(LoginRequest loginRequest);
|
||||
LoginVO login(Authentication authentication, boolean rememberMe);
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param request 退出登录请求
|
||||
* @return 请求结果
|
||||
* @param token 登录信息
|
||||
*/
|
||||
ApiResponse<?> logout(HttpServletRequest request) throws SecurityException;
|
||||
void logout(String token) throws SecurityException;
|
||||
|
||||
/**
|
||||
* 注册
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
package asia.yulinling.workflow.service;
|
||||
|
||||
public interface NoteService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package asia.yulinling.workflow.service;
|
||||
|
||||
import asia.yulinling.workflow.model.entity.Notebook;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Transactional
|
||||
public interface NotebookService {
|
||||
/**
|
||||
* 添加笔记本
|
||||
*
|
||||
* @param notebook 笔记本
|
||||
*/
|
||||
void addNotebook(Notebook notebook);
|
||||
|
||||
/**
|
||||
* 删除笔记本
|
||||
*
|
||||
* @param id 笔记本id
|
||||
*/
|
||||
void deleteNotebook(Long id);
|
||||
|
||||
/**
|
||||
* 更新笔记本
|
||||
*
|
||||
* @param notebook 笔记本
|
||||
*/
|
||||
void updateNotebook(Notebook notebook);
|
||||
|
||||
/**
|
||||
* 获取笔记本内容
|
||||
*
|
||||
* @param id 笔记本id
|
||||
* @return 笔记本
|
||||
*/
|
||||
Notebook getNotebook(Long id);
|
||||
|
||||
/**
|
||||
* 获取笔记本列表
|
||||
*
|
||||
* @return 笔记本列表
|
||||
*/
|
||||
List<Notebook> getNotebookList();
|
||||
}
|
||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -47,46 +48,36 @@ public class AuthServiceImpl implements AuthService {
|
||||
/**
|
||||
* 登录系统
|
||||
*
|
||||
* @param loginRequest 登录请求
|
||||
* @return token
|
||||
* @param authentication 登录信息
|
||||
*/
|
||||
@Override
|
||||
public ApiResponse<LoginVO> login(LoginRequest loginRequest) {
|
||||
public LoginVO login(Authentication authentication, boolean rememberMe) {
|
||||
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
|
||||
|
||||
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
|
||||
loginRequest.getUsername(), loginRequest.getPassword()
|
||||
));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
String accessToken = jwtUtil.generateToken(authentication, rememberMe);
|
||||
Long expiresIn = jwtUtil.getExpiresIn(rememberMe);
|
||||
|
||||
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
|
||||
|
||||
String accessToken = jwtUtil.generateToken(authentication, false);
|
||||
Long expiresIn = jwtUtil.getExpiresIn(loginRequest.getRememberMe());
|
||||
|
||||
LoginVO loginVO = LoginVO.builder()
|
||||
.userId(userPrincipal.getId())
|
||||
.username(userPrincipal.getUsername())
|
||||
.accessToken(accessToken)
|
||||
.expiresIn(expiresIn)
|
||||
.build();
|
||||
|
||||
return ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO);
|
||||
log.info("用户登录成功: {}", userPrincipal.getUsername());
|
||||
return LoginVO.builder()
|
||||
.userId(userPrincipal.getId())
|
||||
.username(userPrincipal.getUsername())
|
||||
.accessToken(accessToken)
|
||||
.expiresIn(expiresIn)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param request 退出登录请求
|
||||
* @return 请求结果
|
||||
* @param token 登录信息
|
||||
*/
|
||||
@Override
|
||||
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException {
|
||||
public void logout(String token) throws SecurityException {
|
||||
try {
|
||||
jwtUtil.invalidateToken(request);
|
||||
jwtUtil.invalidateToken(token);
|
||||
} catch (SecurityException e) {
|
||||
log.info("invalidateToken: {}", e.getMessage());
|
||||
}
|
||||
return ApiResponse.ofStatus(Status.LOGOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package asia.yulinling.workflow.service.impl;
|
||||
|
||||
import asia.yulinling.workflow.service.NoteService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class NoteServiceImpl implements NoteService {
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package asia.yulinling.workflow.service.impl;
|
||||
|
||||
import asia.yulinling.workflow.mapper.NotebookMapper;
|
||||
import asia.yulinling.workflow.model.entity.Notebook;
|
||||
import asia.yulinling.workflow.service.NotebookService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class NotebookServiceImpl implements NotebookService {
|
||||
private final NotebookMapper notebookMapper;
|
||||
|
||||
@Override
|
||||
public void addNotebook(Notebook notebook) {
|
||||
if (notebook == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
notebookMapper.insert(notebook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteNotebook(Long id) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNotebook(Notebook notebook) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Notebook getNotebook(Long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Notebook> getNotebookList() {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@ -91,11 +91,11 @@ public class JwtUtil {
|
||||
|
||||
// 3. 构建JwtBuilder
|
||||
JwtBuilder builder = Jwts.builder()
|
||||
.setSubject(username)
|
||||
.claim("userId", userId)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(expiration)
|
||||
.signWith(this.key());
|
||||
.setSubject(username)
|
||||
.claim("userId", userId)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(expiration)
|
||||
.signWith(this.key());
|
||||
|
||||
// 4. 生成token
|
||||
String token = builder.compact();
|
||||
@ -122,10 +122,10 @@ public class JwtUtil {
|
||||
try {
|
||||
// 1. 解析Token
|
||||
Claims claims = Jwts.parserBuilder()
|
||||
.setSigningKey(this.key())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
.setSigningKey(this.key())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
String username = claims.getSubject();
|
||||
Object userIdObj = claims.get("userId");
|
||||
long userId;
|
||||
@ -199,9 +199,9 @@ public class JwtUtil {
|
||||
// 2. 根据密钥解析token
|
||||
try {
|
||||
Jwts.parserBuilder()
|
||||
.setSigningKey(key)
|
||||
.build()
|
||||
.parse(token);
|
||||
.setSigningKey(key)
|
||||
.build()
|
||||
.parse(token);
|
||||
// 3. 解析正确
|
||||
return true;
|
||||
} catch (JwtException e) {
|
||||
@ -214,10 +214,9 @@ public class JwtUtil {
|
||||
/**
|
||||
* 设置Token过期
|
||||
*
|
||||
* @param request 请求
|
||||
* @param token 登录信息
|
||||
*/
|
||||
public void invalidateToken(HttpServletRequest request) {
|
||||
String token = getTokenFromRequest(request);
|
||||
public void invalidateToken(String token) {
|
||||
String username = parseToken(token).getSubject();
|
||||
stringRedisTemplate.delete(Const.REDIS_JWT_KEY_PREFIX + username);
|
||||
}
|
||||
|
||||
@ -86,26 +86,26 @@ CREATE TABLE `wk_role_user`
|
||||
DROP TABLE IF EXISTS `wk_notebooks`;
|
||||
CREATE TABLE `wk_notebooks`
|
||||
(
|
||||
id VARCHAR(36) PRIMARY KEY, -- 笔记本唯一标识
|
||||
user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者
|
||||
name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称
|
||||
color VARCHAR(20) COMMENT '笔记本颜色标记,用于UI显示', -- 如#FF0000
|
||||
icon VARCHAR(50) COMMENT '笔记本图标标识', -- 如media-book
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '笔记本主键', -- 笔记本唯一标识
|
||||
user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者
|
||||
name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称
|
||||
color VARCHAR(20) COMMENT '笔记本颜色标记,用于UI显示', -- 如#FF0000
|
||||
icon VARCHAR(50) COMMENT '笔记本图标标识', -- 如media-book
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',
|
||||
notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计
|
||||
notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计
|
||||
FOREIGN KEY (user_id) REFERENCES wk_user (id) ON DELETE CASCADE,
|
||||
CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空
|
||||
) COMMENT '用户笔记本分类表,用于组织管理笔记';
|
||||
CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空
|
||||
) COMMENT '用户笔记本';
|
||||
|
||||
DROP TABLE IF EXISTS `wk_notes`;
|
||||
CREATE TABLE `wk_notes`
|
||||
(
|
||||
id VARCHAR(36) PRIMARY KEY COMMENT '笔记唯一标识',
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '笔记唯一标识',
|
||||
user_id bigint(64) NOT NULL COMMENT '作者用户ID',
|
||||
notebook_id VARCHAR(36) COMMENT '所属笔记本ID,可为空',
|
||||
notebook_id BIGINT COMMENT '所属笔记本ID,可为空',
|
||||
title VARCHAR(255) COMMENT '笔记标题,可为空(自动提取内容首行)',
|
||||
content TEXT NOT NULL COMMENT '笔记正文内容,支持Markdown格式',
|
||||
content TEXT NOT NULL COMMENT '笔记正文内容,支持Markdown格式',
|
||||
preview_text VARCHAR(200) COMMENT '内容预览,自动提取前200字符',
|
||||
word_count INTEGER DEFAULT 0 COMMENT '自动计算的字数统计',
|
||||
is_pinned BOOLEAN DEFAULT FALSE COMMENT '是否置顶显示',
|
||||
@ -124,8 +124,8 @@ CREATE TABLE `wk_notes`
|
||||
DROP TABLE IF EXISTS `wk_tags`;
|
||||
CREATE TABLE `wk_tags`
|
||||
(
|
||||
id VARCHAR(36) PRIMARY KEY COMMENT '标签唯一标识',
|
||||
user_id bigint(64) NOT NULL COMMENT '所属用户ID',
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '标签唯一标识',
|
||||
user_id bigint(64) NOT NULL COMMENT '所属用户ID',
|
||||
name VARCHAR(50) NOT NULL COMMENT '标签名称',
|
||||
color VARCHAR(20) COMMENT '标签颜色,用于UI显示',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
@ -138,8 +138,8 @@ CREATE TABLE `wk_tags`
|
||||
DROP TABLE IF EXISTS `wk_note_tags`;
|
||||
CREATE TABLE `wk_note_tags`
|
||||
(
|
||||
note_id VARCHAR(36) NOT NULL COMMENT '关联的笔记ID',
|
||||
tag_id VARCHAR(36) NOT NULL COMMENT '关联的标签ID',
|
||||
note_id BIGINT NOT NULL COMMENT '关联的笔记ID',
|
||||
tag_id BIGINT NOT NULL COMMENT '关联的标签ID',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '关联创建时间',
|
||||
PRIMARY KEY (note_id, tag_id) COMMENT '联合主键,防止重复关联',
|
||||
FOREIGN KEY (note_id) REFERENCES wk_notes (id) ON DELETE CASCADE,
|
||||
@ -149,8 +149,8 @@ CREATE TABLE `wk_note_tags`
|
||||
DROP TABLE IF EXISTS `wk_attachments`;
|
||||
CREATE TABLE wk_attachments
|
||||
(
|
||||
id VARCHAR(36) PRIMARY KEY COMMENT '附件唯一标识',
|
||||
note_id VARCHAR(36) NOT NULL COMMENT '所属笔记ID',
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '附件唯一标识',
|
||||
note_id BIGINT NOT NULL COMMENT '所属笔记ID',
|
||||
file_path VARCHAR(255) NOT NULL COMMENT '文件存储路径',
|
||||
file_type VARCHAR(50) NOT NULL COMMENT '文件MIME类型,如image/png',
|
||||
file_name VARCHAR(255) NOT NULL COMMENT '原始文件名',
|
||||
|
||||
@ -1 +1,6 @@
|
||||
SELECT * FROM wk_notes;
|
||||
SELECT * FROM wk_attachments;
|
||||
SELECT * FROM wk_note_tags;
|
||||
SELECT * FROM wk_tags;
|
||||
SELECT * FROM wk_notebooks;
|
||||
|
||||
|
||||
5
src/main/resources/mapper/NoteMapper.xml
Normal file
5
src/main/resources/mapper/NoteMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?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="asia.yulinling.workflow.mapper.NoteMapper">
|
||||
|
||||
</mapper>
|
||||
5
src/main/resources/mapper/NotebookMapper.xml
Normal file
5
src/main/resources/mapper/NotebookMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?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="asia.yulinling.workflow.mapper.NotebookMapper">
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue
Block a user