├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── README.md ├── src ├── main │ ├── java │ │ └── com │ │ │ └── wbm │ │ │ └── forum │ │ │ ├── exception │ │ │ ├── MyServiceException.java │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── service │ │ │ ├── LikeService.java │ │ │ ├── RoleMenuService.java │ │ │ ├── UserRoleService.java │ │ │ ├── RoleService.java │ │ │ ├── MenuService.java │ │ │ ├── impl │ │ │ │ ├── LikeServiceImpl.java │ │ │ │ ├── RoleMenuServiceImpl.java │ │ │ │ ├── UserRoleServiceImpl.java │ │ │ │ ├── MenuServiceImpl.java │ │ │ │ ├── RoleServiceImpl.java │ │ │ │ ├── UserDetailsServiceImpl.java │ │ │ │ ├── CommentServiceImpl.java │ │ │ │ ├── SubCommentServiceImpl.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ └── PostServiceImpl.java │ │ │ ├── SubCommentService.java │ │ │ ├── CommentService.java │ │ │ ├── UserService.java │ │ │ └── PostService.java │ │ │ ├── mapper │ │ │ ├── LikeMapper.java │ │ │ ├── PostMapper.java │ │ │ ├── UserMapper.java │ │ │ ├── CommentMapper.java │ │ │ ├── RoleMenuMapper.java │ │ │ ├── SubCommentMapper.java │ │ │ ├── UserRoleMapper.java │ │ │ ├── RoleMapper.java │ │ │ └── MenuMapper.java │ │ │ ├── entity │ │ │ ├── vo │ │ │ │ ├── UserRoleVO.java │ │ │ │ ├── RoleMenuVO.java │ │ │ │ ├── PostVO.java │ │ │ │ ├── CommentVO.java │ │ │ │ ├── UserVO.java │ │ │ │ └── SubCommentVO.java │ │ │ ├── dto │ │ │ │ └── UserDTO.java │ │ │ ├── UserRole.java │ │ │ ├── RoleMenu.java │ │ │ ├── Role.java │ │ │ ├── Like.java │ │ │ ├── Menu.java │ │ │ ├── Comment.java │ │ │ ├── SubComment.java │ │ │ ├── SecurityUser.java │ │ │ ├── Post.java │ │ │ └── User.java │ │ │ ├── ForumApplication.java │ │ │ ├── utils │ │ │ ├── WebUtils.java │ │ │ ├── BeanCopyUtils.java │ │ │ ├── JwtUtils.java │ │ │ └── RedisUtils.java │ │ │ ├── config │ │ │ ├── UploadConfig.java │ │ │ ├── MPConfig.java │ │ │ ├── KaptchaConfig.java │ │ │ ├── FastJson.java │ │ │ ├── RedisConfig.java │ │ │ └── SecurityConfig.java │ │ │ ├── common │ │ │ ├── Code.java │ │ │ └── Result.java │ │ │ ├── runner │ │ │ ├── UserRunner.java │ │ │ ├── PostRunner.java │ │ │ └── CommentRunner.java │ │ │ ├── handler │ │ │ ├── AccessDeniedHandlerImpl.java │ │ │ └── AuthenticationEntryPointImpl.java │ │ │ ├── job │ │ │ ├── UpdatePostViews.java │ │ │ ├── UpdatePostLikes.java │ │ │ ├── UpdateCommentLikes.java │ │ │ └── UpdateSubCommentLikes.java │ │ │ ├── controller │ │ │ ├── LoginController.java │ │ │ ├── ImageController.java │ │ │ ├── EmailController.java │ │ │ ├── SubCommentController.java │ │ │ ├── VerifyCodeController.java │ │ │ ├── MenuController.java │ │ │ ├── CommentController.java │ │ │ ├── RoleController.java │ │ │ ├── PostController.java │ │ │ ├── EchartsController.java │ │ │ └── UserController.java │ │ │ └── filter │ │ │ └── JwtFilter.java │ └── resources │ │ ├── mapper │ │ ├── UserRoleMapper.xml │ │ ├── RoleMenuMapper.xml │ │ ├── LikeMapper.xml │ │ ├── RoleMapper.xml │ │ ├── CommentMapper.xml │ │ ├── SubCommentMapper.xml │ │ ├── PostMapper.xml │ │ ├── UserMapper.xml │ │ └── MenuMapper.xml │ │ └── application.yml └── test │ └── java │ └── com │ └── wbm │ └── forum │ └── ForumApplicationTests.java ├── .gitignore ├── pom.xml ├── mvnw.cmd └── mvnw /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paakming/forum/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 工程简介 2 | spring boot+vue校园论坛后端项目 3 | 技术栈: 4 | springboot 5 | spring security 6 | mybatis-plus 7 | MySQL 8 | redis 9 | 前端项目:https://github.com/paakming/luntan 10 | # 延伸阅读 11 | 12 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/exception/MyServiceException.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.exception; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class MyServiceException extends RuntimeException{ 7 | private Integer code; 8 | 9 | public MyServiceException(Integer code,String msg){ 10 | super(msg); 11 | this.code = code; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/LikeService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.wbm.forum.entity.Like; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author Ming 8 | * @description 针对表【like】的数据库操作Service 9 | * @createDate 2023-03-14 22:01:31 10 | */ 11 | public interface LikeService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/RoleMenuService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.wbm.forum.entity.RoleMenu; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author Ming 8 | * @description 针对表【role_menu】的数据库操作Service 9 | * @createDate 2023-03-13 19:27:42 10 | */ 11 | public interface RoleMenuService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/UserRoleService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.wbm.forum.entity.UserRole; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author Ming 8 | * @description 针对表【user_role】的数据库操作Service 9 | * @createDate 2023-03-12 22:39:14 10 | */ 11 | public interface UserRoleService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/RoleService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.wbm.forum.entity.Role; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.wbm.forum.entity.User; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【role】的数据库操作Service 10 | * @createDate 2023-03-13 17:31:13 11 | */ 12 | public interface RoleService extends IService { 13 | Boolean makeRoleForUser(User user); 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/LikeMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.Like; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【like】的数据库操作Mapper 10 | * @createDate 2023-03-15 19:52:19 11 | * @Entity com.wbm.forum.entity.Like 12 | */ 13 | @Repository 14 | public interface LikeMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/PostMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.Post; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【post】的数据库操作Mapper 10 | * @createDate 2023-03-14 19:45:35 11 | * @Entity com.wbm.forum.entity.Post 12 | */ 13 | @Repository 14 | public interface PostMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.User; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【user】的数据库操作Mapper 10 | * @createDate 2023-03-06 14:01:02 11 | * @Entity com.wbm.forum.entity.User 12 | */ 13 | @Repository 14 | public interface UserMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/CommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.Comment; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【comment】的数据库操作Mapper 10 | * @createDate 2023-03-15 19:47:37 11 | * @Entity com.wbm.forum.entity.Comment 12 | */ 13 | @Repository 14 | public interface CommentMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/RoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.RoleMenu; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【role_menu】的数据库操作Mapper 10 | * @createDate 2023-03-13 19:27:42 11 | * @Entity com.wbm.forum.entity.RoleMenu 12 | */ 13 | @Repository 14 | public interface RoleMenuMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/SubCommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.SubComment; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @author Ming 9 | * @description 针对表【sub_comment】的数据库操作Mapper 10 | * @createDate 2023-03-15 19:47:48 11 | * @Entity com.wbm.forum.entity.SubComment 12 | */ 13 | @Repository 14 | public interface SubCommentMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/UserRoleVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | /** 9 | * @Author:Ming 10 | * @Date: 2023/3/13 17:29 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Accessors(chain = true) 16 | public class UserRoleVO { 17 | 18 | private int uid; 19 | 20 | private String username; 21 | 22 | private String roleName; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/MenuService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.wbm.forum.entity.Menu; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.wbm.forum.entity.vo.RoleMenuVO; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author Ming 12 | * @description 针对表【menu】的数据库操作Service 13 | * @createDate 2023-02-28 21:17:38 14 | */ 15 | public interface MenuService extends IService { 16 | IPage selectMenuByRoleId(IPage page, Integer roleId); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.wbm.forum.entity.UserRole; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.springframework.stereotype.Repository; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | 8 | /** 9 | * @author Ming 10 | * @description 针对表【user_role】的数据库操作Mapper 11 | * @createDate 2023-03-12 22:39:14 12 | * @Entity com.wbm.forum.entity.UserRole 13 | */ 14 | @Repository 15 | public interface UserRoleMapper extends BaseMapper { 16 | 17 | } 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/LikeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.wbm.forum.entity.Like; 5 | import com.wbm.forum.service.LikeService; 6 | import com.wbm.forum.mapper.LikeMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Ming 11 | * @description 针对表【like】的数据库操作Service实现 12 | * @createDate 2023-03-14 22:01:31 13 | */ 14 | @Service 15 | public class LikeServiceImpl extends ServiceImpl 16 | implements LikeService{ 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/RoleMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.wbm.forum.entity.RoleMenu; 5 | import com.wbm.forum.service.RoleMenuService; 6 | import com.wbm.forum.mapper.RoleMenuMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Ming 11 | * @description 针对表【role_menu】的数据库操作Service实现 12 | * @createDate 2023-03-13 19:27:42 13 | */ 14 | @Service 15 | public class RoleMenuServiceImpl extends ServiceImpl 16 | implements RoleMenuService{ 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/UserRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.wbm.forum.entity.UserRole; 5 | import com.wbm.forum.service.UserRoleService; 6 | import com.wbm.forum.mapper.UserRoleMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Ming 11 | * @description 针对表【user_role】的数据库操作Service实现 12 | * @createDate 2023-03-12 22:39:14 13 | */ 14 | @Service 15 | public class UserRoleServiceImpl extends ServiceImpl 16 | implements UserRoleService{ 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/ForumApplication.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 7 | 8 | @SpringBootApplication 9 | @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) 10 | @EnableScheduling 11 | public class ForumApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(ForumApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/SubCommentService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.wbm.forum.entity.SubComment; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.wbm.forum.entity.vo.SubCommentVO; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Ming 13 | * @description 针对表【sub_comment】的数据库操作Service 14 | * @createDate 2023-03-06 23:14:34 15 | */ 16 | public interface SubCommentService extends IService { 17 | Map getSubComment(Integer cid, Integer pageNum, Integer pageSize); 18 | Boolean postSubComment(JSONObject jsonObject); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | id,uid,role_id 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/utils/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.utils; 2 | 3 | import javax.servlet.http.HttpServletResponse; 4 | import java.io.IOException; 5 | 6 | /** 7 | * @Author:Ming 8 | * @Date: 2022/11/8 22:04 9 | */ 10 | public class WebUtils { 11 | public static String renderString(HttpServletResponse response,String json) { 12 | try { 13 | response.setStatus(200); 14 | response.setContentType("application/json"); 15 | response.setCharacterEncoding("utf-8"); 16 | response.getWriter().print(json); 17 | }catch (IOException e){ 18 | e.printStackTrace(); 19 | } 20 | return null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/mapper/RoleMenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | id,role_id,menu_id 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.wbm.forum.entity.Comment; 6 | import com.wbm.forum.entity.vo.CommentVO; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author Ming 14 | * @description 针对表【comment】的数据库操作Service 15 | * @createDate 2022-11-12 13:10:05 16 | */ 17 | 18 | public interface CommentService extends IService { 19 | 20 | Map getComment(Integer pid, Integer pageNum, Integer pageSize); 21 | 22 | Boolean doComment(Comment comment); 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/UploadConfig.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * @Author:Ming 9 | * @Date: 2022/12/11 14:52 10 | */ 11 | @Configuration 12 | public class UploadConfig implements WebMvcConfigurer { 13 | private String uploadPath = "F://fileData/" ; 14 | @Override 15 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 16 | registry.addResourceHandler("/image/**").addResourceLocations("file:"+uploadPath); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.wbm.forum.entity.Role; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.wbm.forum.entity.vo.UserRoleVO; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Ming 13 | * @description 针对表【role】的数据库操作Mapper 14 | * @createDate 2023-03-13 17:31:13 15 | * @Entity com.wbm.forum.entity.Role 16 | */ 17 | @Repository 18 | public interface RoleMapper extends BaseMapper { 19 | 20 | IPage selectUserRole(IPage page); 21 | //List selectUserRole(); 22 | } 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.wbm.forum.common.Result; 5 | import com.wbm.forum.entity.User; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author Ming 10 | * @description 针对表【user】的数据库操作Service 11 | * @createDate 2022-11-12 14:52:05 12 | */ 13 | public interface UserService extends IService { 14 | Result login(User user); 15 | 16 | Map getAllUser(Integer pageNum, Integer pageSize); 17 | 18 | Boolean changePwd(String oldPassword, String newPassword, String repeatPassword); 19 | 20 | Boolean forgetPassword(String username, String password, String email, String code); 21 | 22 | Boolean register(User user); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.exception; 2 | 3 | 4 | import com.wbm.forum.common.Code; 5 | import com.wbm.forum.common.Result; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.bind.annotation.RestControllerAdvice; 8 | 9 | @RestControllerAdvice 10 | public class GlobalExceptionHandler { 11 | 12 | @ExceptionHandler(MyServiceException.class) 13 | public Result serviceExceptionHandle(MyServiceException serviceException){ 14 | 15 | return Result.error(serviceException.getCode(),serviceException.getMessage()); 16 | } 17 | @ExceptionHandler(Exception.class) 18 | public Result exceptionHandle(Exception e){ 19 | 20 | return Result.error(Code.ERROR.getCode(),e.getMessage()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/mapper/LikeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | id,pid,cid, 17 | sub_id,uid 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/RoleMenuVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.util.Date; 12 | 13 | /** 14 | * @Author:Ming 15 | * @Date: 2023/3/13 19:24 16 | */ 17 | @Data 18 | @Accessors(chain = true) 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class RoleMenuVO { 22 | private Integer menuId; 23 | 24 | private String roleName; 25 | 26 | private Integer roleId; 27 | 28 | private String menuName; 29 | 30 | private String path; 31 | 32 | private String component; 33 | 34 | private String perm; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/mapper/MenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.wbm.forum.entity.Menu; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.wbm.forum.entity.vo.RoleMenuVO; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Ming 13 | * @description 针对表【menu】的数据库操作Mapper 14 | * @createDate 2023-02-28 21:17:38 15 | * @Entity com.wbm.forum.entity.Menu 16 | */ 17 | @Repository 18 | public interface MenuMapper extends BaseMapper { 19 | List selectPermissionByUid(Integer uid); 20 | 21 | List selectPathByUid(Integer uid); 22 | 23 | List selectComponentByUid(Integer uid); 24 | 25 | IPage selectMenuByRoleId(IPage page,Integer roleId); 26 | 27 | 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/MPConfig.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * @Author:Ming 12 | * @Date: 2022/12/9 17:28 13 | */ 14 | @Configuration 15 | @MapperScan("com.wbm.forum.mapper") 16 | public class MPConfig { 17 | @Bean 18 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 19 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 20 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); 21 | return interceptor; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/utils/BeanCopyUtils.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.utils; 2 | 3 | import org.springframework.beans.BeanUtils; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * @Author:Ming 10 | * @Date: 2022/12/9 19:51 11 | */ 12 | public class BeanCopyUtils { 13 | 14 | public static V copyBean(Object source,Class clazz) { 15 | V result = null; 16 | try { 17 | result = clazz.newInstance(); 18 | BeanUtils.copyProperties(source,result); 19 | } catch (InstantiationException e) { 20 | e.printStackTrace(); 21 | } catch (IllegalAccessException e) { 22 | e.printStackTrace(); 23 | } 24 | return result; 25 | } 26 | 27 | public static List copyBeanList(List list,Class clazz) { 28 | return list.stream().map(o -> copyBean(o,clazz)).collect(Collectors.toList()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/PostVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | * @Author:Ming 13 | * @Date: 2022/11/10 22:39 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Accessors(chain = true) 19 | public class PostVO { 20 | private Integer pid; 21 | 22 | private Integer uid; 23 | 24 | private String nickname; 25 | 26 | private String avatar; 27 | 28 | private String title; 29 | 30 | private String content; 31 | 32 | private String isTop; 33 | 34 | private String type; 35 | 36 | private Integer likes; 37 | 38 | private String isLike; 39 | 40 | private Integer commentNum; 41 | 42 | private LocalDateTime createTime; 43 | 44 | private LocalDateTime updateTime; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.dto; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import com.wbm.forum.entity.Menu; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.time.LocalDateTime; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * @Author:Ming 16 | * @Date: 2023/3/27 16:39 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Accessors(chain = true) 22 | public class UserDTO { 23 | private Integer uid; 24 | 25 | private String username; 26 | 27 | private String nickname; 28 | 29 | private String sex; 30 | 31 | private String phone; 32 | 33 | private String avatar; 34 | 35 | private String email; 36 | 37 | private String identity; 38 | 39 | @JSONField(format="yyyy-MM-dd ") 40 | private Date birthday; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/CommentVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | import com.wbm.forum.entity.SubComment; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.List; 11 | 12 | /** 13 | * @Author:Ming 14 | * @Date: 2022/11/10 22:40 15 | */ 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Accessors(chain = true) 20 | public class CommentVO { 21 | 22 | private Integer cid; 23 | 24 | private Integer pid; 25 | 26 | private Integer floor; 27 | 28 | private String avatar; 29 | 30 | private Integer replyId; 31 | 32 | private String replyName; 33 | 34 | private Integer subCommentNum; 35 | 36 | private String content; 37 | 38 | private Integer likes; 39 | 40 | private String isLike; 41 | 42 | private LocalDateTime createTime; 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/MenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.wbm.forum.entity.Menu; 6 | import com.wbm.forum.entity.vo.RoleMenuVO; 7 | import com.wbm.forum.service.MenuService; 8 | import com.wbm.forum.mapper.MenuMapper; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.Map; 13 | 14 | /** 15 | * @author Ming 16 | * @description 针对表【menu】的数据库操作Service实现 17 | * @createDate 2023-02-28 21:17:38 18 | */ 19 | @Service 20 | public class MenuServiceImpl extends ServiceImpl 21 | implements MenuService{ 22 | @Autowired 23 | private MenuMapper menuMapper; 24 | @Override 25 | public IPage selectMenuByRoleId(IPage page, Integer roleId) { 26 | return menuMapper.selectMenuByRoleId(page,roleId); 27 | } 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/common/Code.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author:Ming 9 | * @Date: 2023/3/4 23:24 10 | */ 11 | @Getter 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public enum Code { 15 | LOGIN_FAIL(401,"账号或密码错误"), 16 | SUCCESS(2000,"操作成功"), 17 | USER_NON_EXISTENT(4000,"用户不存在"), 18 | ERROR(5000,"操作失败"), 19 | ERROR_ADD(5000,"添加失败"), 20 | ERROR_UPDATE(5000,"修改失败"), 21 | ERROR_DELETE(5000,"删除失败"), 22 | ERROR_QUERY(5000,"查询失败"), 23 | VERIFY_CODE_SUCCESS(2000,"获取验证码成功"), 24 | VERIFY_CODE_FAIL(5000,"获取验证码失败"), 25 | VERIFY_CODE_EXPIRED(5000,"验证码已失效,请重新获取验证码"), 26 | VERIFICATION_FAIL(5000,"验证失败"), 27 | VERIFICATION_SUCCESS(2000,"验证成功"), 28 | PASSWORD_OLD_WRONG(5000,"旧密码错误"), 29 | PASSWORD_UPDATE_FAIL(5000,"修改密码失败"), 30 | PASSWORD_TWICE_FAIL(5000,"两次密码输入不一致"), 31 | REGISTER_ERROR(5000,"注册失败"), 32 | ; 33 | 34 | private int code; 35 | private String msg; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import com.wbm.forum.entity.Menu; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.time.LocalDateTime; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * @Author:Ming 16 | * @Date: 2023/2/25 14:50 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Accessors(chain = true) 22 | public class UserVO { 23 | 24 | private Integer uid; 25 | 26 | private String username; 27 | 28 | private String nickname; 29 | 30 | private String sex; 31 | 32 | private String phone; 33 | 34 | private LocalDateTime createTime; 35 | 36 | private String avatar; 37 | 38 | private String email; 39 | 40 | private String identity; 41 | 42 | @JSONField(format="yyyy-MM-dd ") 43 | private Date birthday; 44 | 45 | private List menuList; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/PostService.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service; 2 | 3 | 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.wbm.forum.entity.Post; 6 | import com.wbm.forum.entity.vo.PostVO; 7 | 8 | import java.util.Date; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author Ming 14 | * @description 针对表【post】的数据库操作Service 15 | * @createDate 2022-11-10 21:47:48 16 | */ 17 | public interface PostService extends IService { 18 | PostVO getPost(Integer pid); 19 | 20 | Map getPostByUid(Integer uid,Integer pageNum,Integer pageSize); 21 | 22 | Map getAllPost(Integer pageNum, Integer pageSize); 23 | 24 | Integer addPost(Post post); 25 | 26 | Integer deletePost(Integer pid); 27 | 28 | List getPostByTitle(String key); 29 | 30 | List getPostByPid(Post post); 31 | 32 | Map searchByTime(Date from, Date to, Integer pageNum, Integer pageSize); 33 | 34 | Map selectByType(Post post, Integer pageNum, Integer pageSize); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/vo/SubCommentVO.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity.vo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | import lombok.experimental.Accessors; 11 | 12 | import java.io.Serializable; 13 | import java.time.LocalDateTime; 14 | 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Accessors(chain = true) 19 | public class SubCommentVO implements Serializable { 20 | 21 | private Integer subId; 22 | 23 | private Integer rootId; 24 | 25 | private String avatar; 26 | 27 | private Integer replyId; 28 | 29 | private String replyName; 30 | 31 | private Integer targetId; 32 | 33 | private String targetName; 34 | 35 | private String content; 36 | 37 | private Integer likes; 38 | 39 | private String isLike; 40 | 41 | private LocalDateTime createTime; 42 | 43 | } -------------------------------------------------------------------------------- /src/main/resources/mapper/RoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | role_id,role_name,is_delete, 16 | create_time 17 | 18 | 19 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/common/Result.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.common; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @Author:Ming 7 | * @Date: 2022/11/9 20:15 8 | */ 9 | @Data 10 | 11 | public class Result { 12 | private Integer code; 13 | private String msg; 14 | private Object data; 15 | 16 | public Result() { 17 | } 18 | 19 | public Result(Integer code, String msg) { 20 | this.code = code; 21 | this.msg = msg; 22 | } 23 | 24 | public Result(Integer code, String msg, Object data) { 25 | this.code = code; 26 | this.msg = msg; 27 | this.data = data; 28 | } 29 | 30 | 31 | public static Result success(Integer code, String msg){ 32 | return new Result(code,msg); 33 | } 34 | public static Result success(Integer code, String msg, Object data){ 35 | return new Result(code,msg,data); 36 | } 37 | public static Result error(Integer code, String msg){ 38 | return new Result(code,msg); 39 | } 40 | public static Result error(Integer code, String msg, Object data){ 41 | return new Result(code,msg,data); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import lombok.experimental.Accessors; 13 | 14 | /** 15 | * 16 | * @TableName user_role 17 | */ 18 | @TableName(value ="user_role") 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Accessors(chain = true) 23 | public class UserRole implements Serializable { 24 | /** 25 | * 26 | */ 27 | @TableId(value = "id", type = IdType.AUTO) 28 | private Integer id; 29 | 30 | /** 31 | * 32 | */ 33 | @TableField(value = "uid") 34 | private Integer uid; 35 | 36 | /** 37 | * 38 | */ 39 | @TableField(value = "role_id") 40 | private Integer roleId; 41 | 42 | @TableField(exist = false) 43 | private static final long serialVersionUID = 1L; 44 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/runner/UserRunner.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.runner; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.wbm.forum.entity.User; 5 | import com.wbm.forum.mapper.UserMapper; 6 | import com.wbm.forum.utils.RedisUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/3 20:24 19 | */ 20 | @Component 21 | public class UserRunner implements CommandLineRunner { 22 | 23 | @Autowired 24 | private UserMapper userMapper; 25 | @Autowired 26 | private RedisUtils redisUtils; 27 | 28 | @Override 29 | public void run(String... args) throws Exception { 30 | List users = userMapper.selectList(null); 31 | Map userMap = users.stream().collect(Collectors.toMap(user -> user.getUid().toString(), user -> user)); 32 | redisUtils.hmset("userMap",userMap); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/KaptchaConfig.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import com.google.code.kaptcha.impl.DefaultKaptcha; 4 | import com.google.code.kaptcha.util.Config; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import java.util.Properties; 8 | 9 | /** 10 | * @Author:Ming 11 | * @Date: 2022/11/10 13:04 12 | */ 13 | @Configuration 14 | public class KaptchaConfig { 15 | 16 | @Bean 17 | public DefaultKaptcha getKaptcha(){ 18 | Properties properties = new Properties(); 19 | properties.setProperty("kaptcha.image.width","150"); 20 | properties.setProperty("kaptcha.image.height","50"); 21 | properties.setProperty("kaptcha.textproducer.char.string", "0123456789"); 22 | properties.setProperty("kaptcha.textproducer.char.length", "4"); 23 | properties.setProperty("kaptcha.textproducer.font.names", "楷体"); 24 | Config config = new Config(properties); 25 | DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); 26 | defaultKaptcha.setConfig(config); 27 | return defaultKaptcha; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/RoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import lombok.experimental.Accessors; 13 | 14 | /** 15 | * 16 | * @TableName role_menu 17 | */ 18 | @TableName(value ="role_menu") 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Accessors(chain = true) 23 | public class RoleMenu implements Serializable { 24 | /** 25 | * 26 | */ 27 | @TableId(value = "id", type = IdType.AUTO) 28 | private Integer id; 29 | 30 | /** 31 | * 32 | */ 33 | @TableField(value = "role_id") 34 | private Integer roleId; 35 | 36 | /** 37 | * 38 | */ 39 | @TableField(value = "menu_id") 40 | private Integer menuId; 41 | 42 | @TableField(exist = false) 43 | private static final long serialVersionUID = 1L; 44 | } -------------------------------------------------------------------------------- /src/main/resources/mapper/CommentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | cid,pid,floor, 20 | reply_id,content,create_time, 21 | is_delete,likes 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/handler/AccessDeniedHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.handler; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.wbm.forum.common.Result; 5 | import com.wbm.forum.utils.WebUtils; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * @Author:Ming 17 | * @Date: 2022/11/8 22:00 18 | */ 19 | @Component 20 | public class AccessDeniedHandlerImpl implements AccessDeniedHandler { 21 | @Override 22 | public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { 23 | Result result = new Result(HttpStatus.FORBIDDEN.value(),"权限不足"); 24 | //处理异常 25 | String json = JSONUtil.toJsonStr(result); 26 | WebUtils.renderString(httpServletResponse,json); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/mapper/SubCommentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | sub_id,root_id,reply_id, 20 | target_id,content,create_time, 21 | id_deleted,likes 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/job/UpdatePostViews.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.job; 2 | 3 | import com.wbm.forum.entity.Post; 4 | import com.wbm.forum.service.PostService; 5 | import com.wbm.forum.utils.RedisUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.stream.Collectors; 13 | 14 | /** 15 | * @Author:Ming 16 | * @Date: 2023/3/14 20:22 17 | */ 18 | @Component 19 | public class UpdatePostViews { 20 | @Autowired 21 | private RedisUtils redisUtils; 22 | @Autowired 23 | private PostService postService; 24 | 25 | @Scheduled(cron = "0/5 * * * * ?") 26 | public void updateViews(){ 27 | Map postViews = redisUtils.hGetAll("postViews"); 28 | List collect = postViews.entrySet().stream().map(entry -> { 29 | Post post = new Post(); 30 | post.setPid(Integer.valueOf(entry.getKey().toString())) 31 | .setViews(Long.valueOf(entry.getValue().toString())); 32 | return post; 33 | }).collect(Collectors.toList()); 34 | postService.updateBatchById(collect); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | import lombok.experimental.Accessors; 14 | 15 | /** 16 | * 17 | * @TableName role 18 | */ 19 | @TableName(value ="role") 20 | @Data 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @Accessors(chain = true) 24 | public class Role implements Serializable { 25 | /** 26 | * 27 | */ 28 | @TableId(value = "role_id", type = IdType.AUTO) 29 | private Integer roleId; 30 | 31 | /** 32 | * 33 | */ 34 | @TableField(value = "role_name") 35 | private String roleName; 36 | 37 | /** 38 | * 39 | */ 40 | @TableField(value = "is_delete") 41 | private Integer isDelete; 42 | 43 | /** 44 | * 45 | */ 46 | @TableField(value = "create_time") 47 | private Date createTime; 48 | 49 | @TableField(exist = false) 50 | private static final long serialVersionUID = 1L; 51 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/Like.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import lombok.experimental.Accessors; 13 | 14 | /** 15 | * 16 | * @TableName like 17 | */ 18 | @TableName(value ="`like`")//like 为sql关键字,mp不加``会报错 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Accessors(chain = true) 23 | public class Like implements Serializable { 24 | /** 25 | * 26 | */ 27 | @TableId(value = "id", type = IdType.AUTO) 28 | private Integer id; 29 | 30 | /** 31 | * 32 | */ 33 | @TableField(value = "pid") 34 | private Integer pid; 35 | 36 | /** 37 | * 38 | */ 39 | @TableField(value = "cid") 40 | private Integer cid; 41 | 42 | /** 43 | * 44 | */ 45 | @TableField(value = "sub_id") 46 | private Integer subId; 47 | 48 | /** 49 | * 50 | */ 51 | @TableField(value = "uid") 52 | private Integer uid; 53 | 54 | @TableField(exist = false) 55 | private static final long serialVersionUID = 1L; 56 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/utils/JwtUtils.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.utils; 2 | 3 | 4 | import java.util.Date; 5 | 6 | 7 | import io.jsonwebtoken.Claims; 8 | import io.jsonwebtoken.Jwts; 9 | import io.jsonwebtoken.SignatureAlgorithm; 10 | 11 | /** 12 | * @Author:Ming 13 | * @Date: 2022/11/9 22:01 14 | */ 15 | public class JwtUtils { 16 | //有效期 17 | public static final long EXPIRE = 1000*60*60*24; //24小时 18 | private static String signature = "ming"; 19 | 20 | public static String getJwtToken(String id){ 21 | String JwtToken =Jwts.builder() 22 | //JWT头信息 23 | //.setId()//唯一ID 24 | //.setIssuer()//签发者 25 | .setHeaderParam("typ", "JWT") 26 | .setHeaderParam("alg", "HS2256") 27 | 28 | //设置分类;设置过期时间 一个当前时间,一个加上设置的过期时间常量 29 | .setSubject("security")//主题 30 | .setIssuedAt(new Date())//签发时间 31 | .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) 32 | 33 | //设置token主体信息,存储用户信息 34 | .claim("uid", id) 35 | .signWith(SignatureAlgorithm.HS256, signature) 36 | .compact(); 37 | return JwtToken; 38 | } 39 | 40 | public static Claims parseJwtToken(String token){ 41 | return Jwts.parser().setSigningKey(signature) 42 | .parseClaimsJws(token).getBody(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/Menu.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | import lombok.Data; 10 | 11 | /** 12 | * 13 | * @TableName menu 14 | */ 15 | @TableName(value ="menu") 16 | @Data 17 | public class Menu implements Serializable { 18 | /** 19 | * 20 | */ 21 | @TableId(value = "menu_id", type = IdType.AUTO) 22 | private Integer menuId; 23 | 24 | /** 25 | * 26 | */ 27 | @TableField(value = "menu_name") 28 | private String menuName; 29 | 30 | /** 31 | * 32 | */ 33 | @TableField(value = "path") 34 | private String path; 35 | 36 | /** 37 | * 38 | */ 39 | @TableField(value = "component") 40 | private String component; 41 | 42 | /** 43 | * 44 | */ 45 | @TableField(value = "is_delete") 46 | private Integer isDelete; 47 | 48 | /** 49 | * 50 | */ 51 | @TableField(value = "create_time") 52 | private Date createTime; 53 | 54 | /** 55 | * 56 | */ 57 | @TableField(value = "perm") 58 | private String perm; 59 | 60 | @TableField(exist = false) 61 | private static final long serialVersionUID = 1L; 62 | } -------------------------------------------------------------------------------- /src/main/resources/mapper/PostMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | pid,uid,title, 23 | content,create_time,update_time, 24 | is_top,is_delete,type, 25 | likes,views 26 | 27 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | uid,username,password, 24 | nickname,sex,phone, 25 | create_time,is_delete,avatar, 26 | identity,email,birthday 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/RoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.wbm.forum.entity.Role; 6 | import com.wbm.forum.entity.SecurityUser; 7 | import com.wbm.forum.entity.User; 8 | import com.wbm.forum.entity.UserRole; 9 | import com.wbm.forum.mapper.MenuMapper; 10 | import com.wbm.forum.service.RoleService; 11 | import com.wbm.forum.mapper.RoleMapper; 12 | import com.wbm.forum.service.UserRoleService; 13 | import com.wbm.forum.service.UserService; 14 | import com.wbm.forum.utils.RedisUtils; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Service; 17 | 18 | import java.util.HashMap; 19 | import java.util.List; 20 | import java.util.Objects; 21 | import java.util.stream.Collectors; 22 | 23 | /** 24 | * @author Ming 25 | * @description 针对表【role】的数据库操作Service实现 26 | * @createDate 2023-03-13 17:31:13 27 | */ 28 | @Service 29 | public class RoleServiceImpl extends ServiceImpl 30 | implements RoleService{ 31 | 32 | @Autowired 33 | private UserRoleService userRoleService; 34 | 35 | @Override 36 | public Boolean makeRoleForUser(User user) { 37 | UserRole userRole = new UserRole(); 38 | userRole.setUid(user.getUid()); 39 | //1:超级管理员;2:普通用户;3:管理员 40 | userRole.setRoleId(2); 41 | return userRoleService.save(userRole); 42 | } 43 | } 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | 4 | import cn.hutool.core.util.StrUtil; 5 | import com.wbm.forum.common.Code; 6 | import com.wbm.forum.common.Result; 7 | import com.wbm.forum.entity.SecurityUser; 8 | import com.wbm.forum.entity.User; 9 | import com.wbm.forum.exception.MyServiceException; 10 | import com.wbm.forum.service.UserService; 11 | import com.wbm.forum.utils.RedisUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.core.context.SecurityContextHolder; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.PostMapping; 16 | import org.springframework.web.bind.annotation.RequestBody; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | /** 20 | * @Author:Ming 21 | * @Date: 2022/11/9 20:14 22 | */ 23 | @RestController 24 | public class LoginController { 25 | @Autowired 26 | private UserService userService; 27 | @Autowired 28 | private RedisUtils redisUtils; 29 | 30 | @PostMapping(value = "/login") 31 | public Result login(@RequestBody User user){ 32 | return userService.login(user); 33 | } 34 | 35 | @GetMapping(value = "/logout") 36 | public Result logout(){ 37 | SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 38 | String login = "login-"+securityUser.getUser().getUid(); 39 | redisUtils.delete(login); 40 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/FastJson.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import com.alibaba.fastjson.serializer.SerializeConfig; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import com.alibaba.fastjson.serializer.ToStringSerializer; 6 | import com.alibaba.fastjson.support.config.FastJsonConfig; 7 | import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.http.converter.HttpMessageConverter; 11 | 12 | /** 13 | * @Author:Ming 14 | * @Date: 2023/2/25 17:57 15 | */ 16 | @Configuration 17 | public class FastJson { 18 | @Bean //使用@Bean注入fast]sonHttpMessageconvert 19 | public HttpMessageConverter fastJsonHttpMessageConverters(){ 20 | //1.需要定义一个Convert转换消息的对象 21 | FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); 22 | FastJsonConfig fastJsonConfig = new FastJsonConfig(); 23 | fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); 24 | fastJsonConfig.setDateFormat("yyyy-MM-dd HH :mm:ss "); 25 | SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance); 26 | fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance); 27 | fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig) ; 28 | HttpMessageConverter converter = fastJsonHttpMessageConverter; 29 | return converter; 30 | } 31 | 32 | /* public void configureMessageConverters(List> converters){ 33 | converters.add (fastJsonHttpMessageConverters()); 34 | }*/ 35 | 36 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/runner/PostRunner.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.runner; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.wbm.forum.entity.Like; 5 | import com.wbm.forum.entity.Post; 6 | import com.wbm.forum.mapper.LikeMapper; 7 | import com.wbm.forum.mapper.PostMapper; 8 | import com.wbm.forum.utils.RedisUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.stereotype.Component; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/14 19:41 19 | */ 20 | @Component 21 | public class PostRunner implements CommandLineRunner { 22 | @Autowired 23 | private RedisUtils redisUtils; 24 | @Autowired 25 | private PostMapper postMapper; 26 | @Autowired 27 | private LikeMapper likeMapper; 28 | @Override 29 | public void run(String... args) throws Exception { 30 | List postList = postMapper.selectList(null); 31 | Map postViews = postList.stream() 32 | .collect(Collectors.toMap(post -> post.getPid().toString(),post -> post.getViews().intValue())); 33 | redisUtils.hmsetInt("postViews",postViews); 34 | postList.forEach(post -> { 35 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 36 | wrapper.eq(Like::getPid,post.getPid()); 37 | List likes = likeMapper.selectList(wrapper); 38 | for (Like like : likes) { 39 | redisUtils.sSet("postLikes"+post.getPid().toString(),like.getUid()); 40 | } 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/handler/AuthenticationEntryPointImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.wbm.forum.common.Code; 5 | import com.wbm.forum.common.Result; 6 | import com.wbm.forum.utils.WebUtils; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.security.authentication.BadCredentialsException; 9 | import org.springframework.security.authentication.InsufficientAuthenticationException; 10 | import org.springframework.security.core.AuthenticationException; 11 | import org.springframework.security.web.AuthenticationEntryPoint; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | /** 18 | * @Author:Ming 19 | * @Date: 2022/11/8 21:19 20 | */ 21 | @Component 22 | public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { 23 | @Override 24 | public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 25 | AuthenticationException authenticationException) { 26 | // 27 | Result result ; 28 | if (authenticationException instanceof BadCredentialsException) { 29 | result = new Result(HttpStatus.UNAUTHORIZED.value(), authenticationException.getMessage()); 30 | } else if (authenticationException instanceof InsufficientAuthenticationException) { 31 | result = new Result(HttpStatus.UNAUTHORIZED.value(), authenticationException.getMessage()); 32 | } else { 33 | result = new Result(Code.LOGIN_FAIL.getCode(), "认证失败"); 34 | } 35 | WebUtils.renderString(httpServletResponse, JSON.toJSONString(result)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/Comment.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | import java.util.Date; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Data; 13 | import lombok.NoArgsConstructor; 14 | import lombok.experimental.Accessors; 15 | 16 | /** 17 | * 18 | * @TableName comment 19 | */ 20 | @TableName(value ="comment") 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @Accessors(chain = true) 25 | public class Comment implements Serializable { 26 | /** 27 | * 自增id评论id 28 | */ 29 | @TableId(value = "cid", type = IdType.AUTO) 30 | private Integer cid; 31 | 32 | /** 33 | * 帖子id 34 | */ 35 | @TableField(value = "pid") 36 | private Integer pid; 37 | 38 | /** 39 | * 楼层 40 | */ 41 | @TableField(value = "floor") 42 | private Integer floor; 43 | 44 | /** 45 | * 回复人 46 | */ 47 | @TableField(value = "reply_id") 48 | private Integer replyId; 49 | 50 | /** 51 | * 回复内容 52 | */ 53 | @TableField(value = "content") 54 | private String content; 55 | 56 | /** 57 | * 回复时间 58 | */ 59 | @TableField(value = "create_time") 60 | private LocalDateTime createTime; 61 | 62 | /** 63 | * 64 | */ 65 | @TableField(value = "is_delete") 66 | private String isDelete; 67 | 68 | /** 69 | * 70 | */ 71 | @TableField(value = "likes") 72 | private Long likes; 73 | 74 | @TableField(exist = false) 75 | private static final long serialVersionUID = 1L; 76 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/job/UpdatePostLikes.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.job; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.wbm.forum.entity.Like; 6 | import com.wbm.forum.entity.Post; 7 | import com.wbm.forum.service.LikeService; 8 | import com.wbm.forum.service.PostService; 9 | import com.wbm.forum.utils.RedisUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.scheduling.annotation.Scheduled; 12 | import org.springframework.stereotype.Component; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/15 0:05 19 | */ 20 | @Component 21 | public class UpdatePostLikes { 22 | @Autowired 23 | private RedisUtils redisUtils; 24 | @Autowired 25 | private PostService postService; 26 | @Autowired 27 | private LikeService likeService; 28 | 29 | @Scheduled(cron = "0/5 * * * * ?") 30 | public void updateLikes(){ 31 | List list = postService.list(); 32 | list.forEach(post -> { 33 | Set objects = redisUtils.sGet("postLikes" + post.getPid()); 34 | if (objects.size()>0){ 35 | for (Object o : objects) { 36 | Like like = new Like(); 37 | like.setPid(post.getPid()).setUid((Integer) o); 38 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 39 | wrapper.eq(Like::getPid,like.getPid()).eq(Like::getUid,like.getUid()); 40 | Like one = likeService.getOne(wrapper); 41 | if (ObjectUtil.isNull(one)){ 42 | likeService.save(like); 43 | } 44 | } 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/SubComment.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | import java.util.Date; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Data; 13 | import lombok.NoArgsConstructor; 14 | import lombok.experimental.Accessors; 15 | 16 | /** 17 | * 18 | * @TableName sub_comment 19 | */ 20 | @TableName(value ="sub_comment") 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @Accessors(chain = true) 25 | public class SubComment implements Serializable { 26 | /** 27 | * 自增id 28 | */ 29 | @TableId(value = "sub_id", type = IdType.AUTO) 30 | private Integer subId; 31 | 32 | /** 33 | * 从属评论的id 34 | */ 35 | @TableField(value = "root_id") 36 | private Integer rootId; 37 | 38 | /** 39 | * 回复人的id 40 | */ 41 | @TableField(value = "reply_id") 42 | private Integer replyId; 43 | 44 | /** 45 | * 被回复人的id 46 | */ 47 | @TableField(value = "target_id") 48 | private Integer targetId; 49 | 50 | /** 51 | * 回复内容 52 | */ 53 | @TableField(value = "content") 54 | private String content; 55 | 56 | /** 57 | * 58 | */ 59 | @TableField(value = "create_time") 60 | private LocalDateTime createTime; 61 | 62 | /** 63 | * 0:未删除,1:删除 64 | */ 65 | @TableField(value = "id_deleted") 66 | private String idDeleted; 67 | 68 | /** 69 | * 70 | */ 71 | @TableField(value = "likes") 72 | private Long likes; 73 | 74 | @TableField(exist = false) 75 | private static final long serialVersionUID = 1L; 76 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/job/UpdateCommentLikes.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.job; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.wbm.forum.entity.Comment; 6 | import com.wbm.forum.entity.Like; 7 | import com.wbm.forum.service.CommentService; 8 | import com.wbm.forum.service.LikeService; 9 | import com.wbm.forum.utils.RedisUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.scheduling.annotation.Scheduled; 12 | import org.springframework.stereotype.Component; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/15 0:05 19 | */ 20 | @Component 21 | public class UpdateCommentLikes { 22 | @Autowired 23 | private RedisUtils redisUtils; 24 | @Autowired 25 | private CommentService commentService; 26 | @Autowired 27 | private LikeService likeService; 28 | 29 | @Scheduled(cron = "0/5 * * * * ?") 30 | public void updateLikes(){ 31 | List list = commentService.list(); 32 | list.forEach(comment -> { 33 | Set objects = redisUtils.sGet("commentLikes" + comment.getCid()); 34 | if (objects.size()>0){ 35 | for (Object o : objects) { 36 | Like like = new Like(); 37 | like.setCid(comment.getCid()).setUid((Integer) o); 38 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 39 | wrapper.eq(Like::getCid,like.getCid()).eq(Like::getUid,like.getUid()); 40 | Like one = likeService.getOne(wrapper); 41 | if (ObjectUtil.isNull(one)){ 42 | likeService.save(like); 43 | } 44 | } 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/ImageController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.core.util.IdUtil; 5 | import cn.hutool.core.util.StrUtil; 6 | import cn.hutool.json.JSONObject; 7 | import com.wbm.forum.common.Result; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | import org.springframework.web.multipart.MultipartFile; 11 | import java.io.File; 12 | import java.io.IOException; 13 | 14 | /** 15 | * @Author:Ming 16 | * @Date: 2022/12/9 22:08 17 | */ 18 | @RestController 19 | @RequestMapping("/img") 20 | public class ImageController { 21 | 22 | @PostMapping("/upload") 23 | // @PreAuthorize("hasAuthority('system:image:upload')") 24 | public Object ImageUpload(@RequestParam("file") MultipartFile file){ 25 | String path = "http://localhost:8080/image/"; 26 | JSONObject obj = new JSONObject(); 27 | if (file.isEmpty()){ 28 | obj.set("errno",1); 29 | obj.set("message","失败信息"); 30 | return obj; 31 | } 32 | String uploadPath = "F://fileData"; 33 | File folder = new File(uploadPath); 34 | if (!folder.exists()){ 35 | folder.mkdir(); 36 | } 37 | String originName = file.getOriginalFilename(); 38 | String type = FileUtil.extName(originName); 39 | String uuid = IdUtil.fastSimpleUUID() + StrUtil.DOT+type; 40 | try { 41 | file.transferTo(new File(folder,uuid)); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } 45 | String url = path+uuid; 46 | obj.set("errno",0); 47 | JSONObject data = new JSONObject(); 48 | data.set("url",url); 49 | data.set("href",url); 50 | obj.set("data",data); 51 | return obj; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/job/UpdateSubCommentLikes.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.job; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.wbm.forum.entity.Like; 6 | import com.wbm.forum.entity.SubComment; 7 | import com.wbm.forum.service.LikeService; 8 | import com.wbm.forum.service.SubCommentService; 9 | import com.wbm.forum.utils.RedisUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.scheduling.annotation.Scheduled; 12 | import org.springframework.stereotype.Component; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/15 0:05 19 | */ 20 | @Component 21 | public class UpdateSubCommentLikes { 22 | @Autowired 23 | private RedisUtils redisUtils; 24 | @Autowired 25 | private SubCommentService subCommentService; 26 | @Autowired 27 | private LikeService likeService; 28 | 29 | @Scheduled(cron = "0/5 * * * * ?") 30 | public void updateLikes(){ 31 | List list = subCommentService.list(); 32 | list.forEach(subComment -> { 33 | Set objects = redisUtils.sGet("sucCommentLikes" + subComment.getSubId()); 34 | if (objects.size()>0){ 35 | for (Object o : objects) { 36 | Like like = new Like(); 37 | like.setSubId(subComment.getSubId()).setUid((Integer) o); 38 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 39 | wrapper.eq(Like::getSubId,like.getSubId()).eq(Like::getUid,like.getUid()); 40 | Like one = likeService.getOne(wrapper); 41 | if (ObjectUtil.isNull(one)){ 42 | likeService.save(like); 43 | } 44 | } 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/SecurityUser.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import java.util.Collection; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * @Author:Ming 15 | * @Date: 2022/11/9 21:53 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SecurityUser implements UserDetails{ 21 | 22 | private User user; 23 | private List permission; 24 | private List path; 25 | private List component; 26 | 27 | @Override 28 | public Collection getAuthorities() { 29 | /* List authorityList = new ArrayList<>(); 30 | for (String s : permission) { 31 | SimpleGrantedAuthority authority = new SimpleGrantedAuthority(s); 32 | authorityList.add(authority); 33 | }*/ 34 | return permission.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); 35 | } 36 | 37 | @Override 38 | public String getPassword() { 39 | return user.getPassword(); 40 | } 41 | 42 | @Override 43 | public String getUsername() { 44 | return user.getPassword(); 45 | } 46 | 47 | @Override 48 | public boolean isAccountNonExpired() { 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean isAccountNonLocked() { 54 | return true; 55 | } 56 | 57 | @Override 58 | public boolean isCredentialsNonExpired() { 59 | return true; 60 | } 61 | 62 | @Override 63 | public boolean isEnabled() { 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/EmailController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | 4 | import cn.hutool.core.lang.Validator; 5 | import cn.hutool.core.util.StrUtil; 6 | import com.wbm.forum.common.Code; 7 | import com.wbm.forum.common.Result; 8 | import com.wbm.forum.utils.RedisUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.mail.SimpleMailMessage; 12 | import org.springframework.mail.javamail.JavaMailSender; 13 | import org.springframework.validation.annotation.Validated; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | import javax.websocket.server.PathParam; 17 | import java.util.Random; 18 | 19 | /** 20 | * @Author:Ming 21 | * @Date: 2022/11/10 16:47 22 | */ 23 | @RestController 24 | public class EmailController { 25 | 26 | @Autowired 27 | private RedisUtils redisUtils; 28 | @Autowired 29 | private JavaMailSender javaMailSender; 30 | 31 | @Value("${spring.mail.username}") 32 | private String from; 33 | 34 | @GetMapping(value = "/email") 35 | public Result getEmail(@PathParam("emailReceiver") String emailReceiver){ 36 | if (!Validator.isEmail(emailReceiver)){ 37 | return Result.error(Code.ERROR.getCode(),"请输入邮箱地址"); 38 | } 39 | SimpleMailMessage mailMessage = new SimpleMailMessage(); 40 | mailMessage.setFrom(from); 41 | mailMessage.setTo(emailReceiver); 42 | mailMessage.setSubject("luntan|验证码"); 43 | Random random = new Random(); 44 | StringBuilder code = new StringBuilder(); 45 | for (int i = 0;i<6;i++){ 46 | int r = random.nextInt(10); 47 | code.append(r); 48 | } 49 | String text = "【校园论坛】您的验证码为:"+code+",请勿泄露给他人,有效期为10分钟。"; 50 | mailMessage.setText(text); 51 | redisUtils.set(emailReceiver,code.toString(),10L); 52 | javaMailSender.send(mailMessage); 53 | return Result.success(Code.SUCCESS.getCode(),"验证码发送成功"); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/Post.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | import java.util.Date; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Data; 13 | import lombok.NoArgsConstructor; 14 | import lombok.experimental.Accessors; 15 | 16 | /** 17 | * 18 | * @TableName post 19 | */ 20 | @TableName(value ="post") 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @Accessors(chain = true) 25 | public class Post implements Serializable { 26 | /** 27 | * 自增id 28 | */ 29 | @TableId(value = "pid", type = IdType.AUTO) 30 | private Integer pid; 31 | 32 | /** 33 | * 楼主 34 | */ 35 | @TableField(value = "uid") 36 | private Integer uid; 37 | 38 | /** 39 | * 标题 40 | */ 41 | @TableField(value = "title") 42 | private String title; 43 | 44 | /** 45 | * 内容 46 | */ 47 | @TableField(value = "content") 48 | private String content; 49 | 50 | /** 51 | * 发帖时间 52 | */ 53 | @TableField(value = "create_time") 54 | private LocalDateTime createTime; 55 | 56 | /** 57 | * 58 | */ 59 | @TableField(value = "update_time") 60 | private LocalDateTime updateTime; 61 | 62 | /** 63 | * 是否置顶,1为置顶 64 | */ 65 | @TableField(value = "is_top") 66 | private String isTop; 67 | 68 | /** 69 | * 是否删除,1为删除 70 | */ 71 | @TableField(value = "is_delete") 72 | private String isDelete; 73 | 74 | /** 75 | * 76 | */ 77 | @TableField(value = "type") 78 | private String type; 79 | 80 | /** 81 | * 82 | */ 83 | @TableField(value = "likes") 84 | private Long likes; 85 | 86 | /** 87 | * 88 | */ 89 | @TableField(value = "views") 90 | private Long views; 91 | 92 | @TableField(exist = false) 93 | private static final long serialVersionUID = 1L; 94 | } -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/runner/CommentRunner.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.runner; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.wbm.forum.entity.Comment; 5 | import com.wbm.forum.entity.Like; 6 | import com.wbm.forum.entity.SubComment; 7 | import com.wbm.forum.mapper.CommentMapper; 8 | import com.wbm.forum.mapper.LikeMapper; 9 | import com.wbm.forum.mapper.SubCommentMapper; 10 | import com.wbm.forum.utils.RedisUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.CommandLineRunner; 13 | import org.springframework.stereotype.Component; 14 | import java.util.List; 15 | 16 | /** 17 | * @Author:Ming 18 | * @Date: 2023/3/15 19:40 19 | */ 20 | @Component 21 | public class CommentRunner implements CommandLineRunner { 22 | @Autowired 23 | private RedisUtils redisUtils; 24 | @Autowired 25 | private CommentMapper commentMapper; 26 | @Autowired 27 | private SubCommentMapper subCommentMapper; 28 | @Autowired 29 | private LikeMapper likeMapper; 30 | 31 | 32 | @Override 33 | public void run(String... args) throws Exception { 34 | List comments = commentMapper.selectList(null); 35 | comments.forEach(comment -> { 36 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 37 | wrapper.eq(Like::getCid,comment.getCid()); 38 | List likes = likeMapper.selectList(wrapper); 39 | for (Like like : likes) { 40 | redisUtils.sSet("commentLikes"+comment.getCid().toString(),like.getUid()); 41 | } 42 | }); 43 | 44 | List subComments = subCommentMapper.selectList(null); 45 | subComments.forEach(subComment -> { 46 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 47 | wrapper.eq(Like::getSubId,subComment.getSubId()); 48 | List likes = likeMapper.selectList(wrapper); 49 | for (Like like : likes) { 50 | redisUtils.sSet("sucCommentLikes"+subComment.getSubId().toString(),like.getUid()); 51 | } 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import com.wbm.forum.common.Code; 6 | import com.wbm.forum.entity.SecurityUser; 7 | import com.wbm.forum.entity.User; 8 | import com.wbm.forum.exception.MyServiceException; 9 | import com.wbm.forum.mapper.MenuMapper; 10 | import com.wbm.forum.mapper.UserMapper; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | import org.springframework.security.core.userdetails.UserDetailsService; 14 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 15 | import org.springframework.stereotype.Service; 16 | import java.util.List; 17 | import java.util.Objects; 18 | import java.util.stream.Collectors; 19 | 20 | /** 21 | * @Author:Ming 22 | * @Date: 2022/11/9 21:55 23 | */ 24 | @Service 25 | public class UserDetailsServiceImpl implements UserDetailsService { 26 | @Autowired 27 | private UserMapper userMapper; 28 | @Autowired 29 | private MenuMapper menuMapper; 30 | @Override 31 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 32 | LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); 33 | lambdaQueryWrapper.eq(User::getUsername,username); 34 | User user = userMapper.selectOne(lambdaQueryWrapper); 35 | if (ObjectUtil.isNull(user)){ 36 | throw new MyServiceException(Code.USER_NON_EXISTENT.getCode(),Code.USER_NON_EXISTENT.getMsg()); 37 | } 38 | List permission = menuMapper.selectPermissionByUid(user.getUid()); 39 | List path = menuMapper.selectPathByUid(user.getUid()) 40 | .stream().filter(Objects::nonNull).collect(Collectors.toList()); 41 | List component = menuMapper.selectComponentByUid(user.getUid()) 42 | .stream().filter(Objects::nonNull).collect(Collectors.toList()); 43 | return new SecurityUser(user,permission,path,component); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.redis.connection.RedisConnectionFactory; 7 | import org.springframework.data.redis.core.RedisTemplate; 8 | import org.springframework.data.redis.serializer.StringRedisSerializer; 9 | 10 | /** 11 | * @Author:Ming 12 | * @Date: 2023/2/25 16:57 13 | */ 14 | @Configuration 15 | public class RedisConfig { 16 | 17 | @Bean 18 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 19 | RedisTemplate template = new RedisTemplate<>(); 20 | template.setConnectionFactory(redisConnectionFactory); 21 | 22 | // String的序列化 23 | StringRedisSerializer stringSerializer = new StringRedisSerializer(); 24 | // key采用String的序列化方式 25 | template.setKeySerializer(stringSerializer); 26 | // hash的key采用String的序列化方式 27 | template.setHashKeySerializer(stringSerializer); 28 | 29 | // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = jackson2JsonRedisSerializerConfig(); 30 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); 31 | //value采用jackson序列化方式 32 | template.setValueSerializer(fastJsonRedisSerializer); 33 | //hash的value也采用jackson序列化方式 34 | template.setHashValueSerializer(fastJsonRedisSerializer); 35 | 36 | template.afterPropertiesSet(); 37 | 38 | 39 | return template; 40 | } 41 | 42 | // private Jackson2JsonRedisSerializer jackson2JsonRedisSerializerConfig() { 43 | // // jackson序列化所有的类 44 | // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 45 | // // jackson序列化的一些配置 46 | // ObjectMapper om = new ObjectMapper(); 47 | // om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 48 | // om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance); 49 | // om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 50 | // om.registerModule(new JavaTimeModule()); 51 | // jackson2JsonRedisSerializer.setObjectMapper(om); 52 | // return jackson2JsonRedisSerializer; 53 | // } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.entity; 2 | 3 | import com.alibaba.fastjson.annotation.JSONField; 4 | import com.baomidou.mybatisplus.annotation.IdType; 5 | import com.baomidou.mybatisplus.annotation.TableField; 6 | import com.baomidou.mybatisplus.annotation.TableId; 7 | import com.baomidou.mybatisplus.annotation.TableName; 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | import java.util.Date; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | import lombok.experimental.Accessors; 16 | 17 | /** 18 | * 19 | * @TableName user 20 | */ 21 | @TableName(value ="user") 22 | @Data 23 | @AllArgsConstructor 24 | @NoArgsConstructor 25 | @Accessors(chain = true) 26 | public class User implements Serializable { 27 | /** 28 | * uid 29 | */ 30 | @TableId(value = "uid", type = IdType.AUTO) 31 | private Integer uid; 32 | 33 | /** 34 | * 用户名 35 | */ 36 | @TableField(value = "username") 37 | private String username; 38 | 39 | /** 40 | * 密码 41 | */ 42 | @TableField(value = "password") 43 | private String password; 44 | 45 | /** 46 | * 昵称 47 | */ 48 | @TableField(value = "nickname") 49 | private String nickname; 50 | 51 | /** 52 | * 性别 53 | */ 54 | @TableField(value = "sex") 55 | private String sex; 56 | 57 | /** 58 | * 手机号 59 | */ 60 | @TableField(value = "phone") 61 | private String phone; 62 | 63 | /** 64 | * 创建时间 65 | */ 66 | @TableField(value = "create_time") 67 | private LocalDateTime createTime; 68 | 69 | /** 70 | * 是否删除 71 | */ 72 | @TableField(value = "is_delete") 73 | private String isDelete; 74 | 75 | /** 76 | * 头像 77 | */ 78 | @TableField(value = "avatar") 79 | private String avatar; 80 | 81 | /** 82 | * 绑定学号或工号 83 | */ 84 | @TableField(value = "identity") 85 | private String identity; 86 | 87 | /** 88 | * 邮箱 89 | */ 90 | @TableField(value = "email") 91 | private String email; 92 | 93 | /** 94 | * 出生日期 95 | */ 96 | @TableField(value = "birthday") 97 | @JSONField(format="yyyy-MM-dd") 98 | private Date birthday; 99 | 100 | @TableField(exist = false) 101 | private static final long serialVersionUID = 1L; 102 | } -------------------------------------------------------------------------------- /src/main/resources/mapper/MenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | menu_id,menu_name,path, 19 | component,is_delete,create_time, 20 | perm 21 | 22 | 30 | 38 | 46 | 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/SubCommentController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.wbm.forum.common.Code; 5 | import com.wbm.forum.common.Result; 6 | import com.wbm.forum.exception.MyServiceException; 7 | import com.wbm.forum.service.SubCommentService; 8 | import com.wbm.forum.utils.RedisUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | import javax.websocket.server.PathParam; 13 | import java.util.Map; 14 | 15 | /** 16 | * @Author:Ming 17 | * @Date: 2023/3/7 1:33 18 | */ 19 | @RestController 20 | @RequestMapping("/subComment") 21 | public class SubCommentController { 22 | @Autowired 23 | private SubCommentService subCommentService; 24 | @Autowired 25 | private RedisUtils redisUtils; 26 | 27 | @GetMapping("/{cid}") 28 | public Result getSubComment(@PathVariable Integer cid, @PathParam("pageNum") Integer pageNum, @PathParam("pageSize") Integer pageSize){ 29 | Map subComment = subCommentService.getSubComment(cid, pageNum, pageSize); 30 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg(),subComment); 31 | } 32 | @PostMapping 33 | public Result postSubComment(@RequestBody JSONObject jsonObject){ 34 | subCommentService.postSubComment(jsonObject); 35 | return Result.success(Code.SUCCESS.getCode(),"回复成功"); 36 | } 37 | @DeleteMapping(value = "/{subId}") 38 | @PreAuthorize("hasAuthority('system:comment:delete')") 39 | public Result deleteComment(@PathVariable Integer subId){ 40 | subCommentService.removeById(subId); 41 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 42 | } 43 | @PutMapping("/doLike/{subId}/{uid}") 44 | public Result doLike(@PathVariable("subId") Integer subId,@PathVariable("uid")Integer uid){ 45 | boolean b = redisUtils.sHasKey("sucCommentLikes" + subId, uid); 46 | if (b){ 47 | throw new MyServiceException(Code.ERROR.getCode(),"已点赞"); 48 | }else { 49 | redisUtils.sSet("sucCommentLikes" + subId,uid); 50 | return Result.success(Code.SUCCESS.getCode(),"点赞成功"); 51 | } 52 | } 53 | @PutMapping("/unDoLike/{subId}/{uid}") 54 | public Result unDoLike(@PathVariable("subId") Integer subId,@PathVariable("uid")Integer uid){ 55 | boolean b = redisUtils.sHasKey("sucCommentLikes" + subId, uid); 56 | if (b) { 57 | redisUtils.setRemove("sucCommentLikes" + subId, uid); 58 | return Result.success(Code.SUCCESS.getCode(),"取消成功"); 59 | }else { 60 | throw new MyServiceException(Code.ERROR.getCode(),"没有点赞"); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/VerifyCodeController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.io.FastByteArrayOutputStream; 4 | import cn.hutool.core.lang.UUID; 5 | import cn.hutool.core.util.StrUtil; 6 | import com.google.code.kaptcha.impl.DefaultKaptcha; 7 | import com.wbm.forum.common.Code; 8 | import com.wbm.forum.common.Result; 9 | import com.wbm.forum.utils.RedisUtils; 10 | import org.apache.tomcat.util.codec.binary.Base64; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PathVariable; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | import javax.imageio.ImageIO; 17 | import java.awt.image.BufferedImage; 18 | import java.io.IOException; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * @Author:Ming 24 | * @Date: 2022/11/10 16:52 25 | */ 26 | @RestController 27 | public class VerifyCodeController { 28 | 29 | @Autowired 30 | private DefaultKaptcha defaultKaptcha; 31 | @Autowired 32 | private RedisUtils redisUtils; 33 | 34 | @GetMapping(value = "/verifyCode") 35 | public Result verifyCode() throws IOException { 36 | String uuid = UUID.randomUUID().toString(); 37 | String text = defaultKaptcha.createText(); 38 | redisUtils.set(uuid,text,30L); 39 | BufferedImage bi = defaultKaptcha.createImage(text); 40 | FastByteArrayOutputStream stream = new FastByteArrayOutputStream(); 41 | ImageIO.write(bi, "jpg", stream); 42 | String code = Base64.encodeBase64String(stream.toByteArray()); 43 | Map map = new HashMap<>(); 44 | map.put("uuid",uuid); 45 | map.put("verifyCode",code); 46 | return Result.success(Code.VERIFY_CODE_SUCCESS.getCode(), Code.VERIFY_CODE_SUCCESS.getMsg(),map); 47 | } 48 | @PostMapping(value = "/checkVerify/{verifyCode}/{uuid}") 49 | public Result check(@PathVariable("verifyCode") String verifyCode,@PathVariable("uuid") String uuid){ 50 | if (uuid == null || verifyCode == null){ 51 | return Result.error(Code.VERIFICATION_FAIL.getCode(), Code.VERIFICATION_FAIL.getMsg()); 52 | } 53 | String text = redisUtils.strGet(uuid); 54 | if (StrUtil.isBlank(text)){ 55 | return Result.error(Code.VERIFY_CODE_EXPIRED.getCode(), Code.VERIFY_CODE_EXPIRED.getMsg()); 56 | } 57 | if (text.equals(verifyCode)){ 58 | redisUtils.delete(uuid); 59 | return Result.success(Code.VERIFICATION_SUCCESS.getCode(), Code.VERIFICATION_SUCCESS.getMsg()); 60 | } 61 | return Result.error(Code.VERIFICATION_FAIL.getCode(), Code.VERIFICATION_FAIL.getMsg()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/filter/JwtFilter.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.filter; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import cn.hutool.json.JSONUtil; 6 | import com.alibaba.fastjson.JSON; 7 | import com.wbm.forum.common.Result; 8 | import com.wbm.forum.entity.SecurityUser; 9 | import com.wbm.forum.utils.JwtUtils; 10 | import com.wbm.forum.utils.RedisUtils; 11 | import com.wbm.forum.utils.WebUtils; 12 | import io.jsonwebtoken.Claims; 13 | import io.jsonwebtoken.JwtException; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.http.HttpStatus; 16 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 17 | import org.springframework.security.core.context.SecurityContextHolder; 18 | import org.springframework.stereotype.Component; 19 | import org.springframework.web.filter.OncePerRequestFilter; 20 | 21 | import javax.servlet.FilterChain; 22 | import javax.servlet.ServletException; 23 | import javax.servlet.http.HttpServletRequest; 24 | import javax.servlet.http.HttpServletResponse; 25 | import java.io.IOException; 26 | 27 | /** 28 | * @Author:Ming 29 | * @Date: 2022/11/6 23:58 30 | */ 31 | @Component 32 | public class JwtFilter extends OncePerRequestFilter { 33 | @Autowired 34 | private RedisUtils redisUtils; 35 | @Override 36 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 37 | //获取token 38 | String token = request.getHeader("token"); 39 | if (StrUtil.isBlank(token)){ 40 | filterChain.doFilter(request,response); 41 | return ; 42 | } 43 | String uid; 44 | //解析token 45 | //要异常处理 46 | Claims claims = null; 47 | try { 48 | claims = JwtUtils.parseJwtToken(token); 49 | }catch (JwtException e){ 50 | Result result = new Result(HttpStatus.UNAUTHORIZED.value(),"请重新登录"); 51 | WebUtils.renderString(response,JSON.toJSONString(result)); 52 | return; 53 | } 54 | uid = (String) claims.get("uid"); 55 | String key = "login-"+uid; 56 | String s = redisUtils.strGet(key); 57 | if (ObjectUtil.isNull(s)){ 58 | Result result = new Result(HttpStatus.UNAUTHORIZED.value(),"请重新登录"); 59 | WebUtils.renderString(response,JSON.toJSONString(result)); 60 | return; 61 | } 62 | SecurityUser securityUser = JSON.parseObject(s,SecurityUser.class); 63 | if (ObjectUtil.isNull(securityUser)){ 64 | Result result = new Result(HttpStatus.UNAUTHORIZED.value(),"请重新登录"); 65 | WebUtils.renderString(response,JSON.toJSONString(result)); 66 | return; 67 | } 68 | UsernamePasswordAuthenticationToken authenticationToken = 69 | new UsernamePasswordAuthenticationToken(securityUser,null,securityUser.getAuthorities()); 70 | SecurityContextHolder.getContext().setAuthentication(authenticationToken); 71 | filterChain.doFilter(request,response); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/MenuController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 | import com.baomidou.mybatisplus.core.metadata.IPage; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.wbm.forum.common.Code; 9 | import com.wbm.forum.common.Result; 10 | import com.wbm.forum.entity.Menu; 11 | import com.wbm.forum.entity.Role; 12 | import com.wbm.forum.entity.RoleMenu; 13 | import com.wbm.forum.entity.User; 14 | import com.wbm.forum.entity.vo.RoleMenuVO; 15 | import com.wbm.forum.mapper.RoleMapper; 16 | import com.wbm.forum.service.MenuService; 17 | import com.wbm.forum.service.RoleMenuService; 18 | import com.wbm.forum.utils.BeanCopyUtils; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.security.access.prepost.PreAuthorize; 21 | import org.springframework.stereotype.Repository; 22 | import org.springframework.web.bind.annotation.*; 23 | 24 | import javax.websocket.server.PathParam; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | 28 | /** 29 | * @Author:Ming 30 | * @Date: 2023/3/13 22:25 31 | */ 32 | @RestController 33 | @RequestMapping("/menu") 34 | @PreAuthorize("hasAuthority('system:menu:manage')") 35 | public class MenuController { 36 | 37 | @Autowired 38 | private MenuService menuService; 39 | 40 | @Autowired 41 | private RoleMenuService roleMenuService; 42 | 43 | @GetMapping 44 | public Result getAllMenu(){ 45 | List list = menuService.list(); 46 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg(),list); 47 | } 48 | @GetMapping("/role/{roleId}/{pageNum}/{pageSize}") 49 | public Result getRoleForMenu(@PathVariable("roleId") Integer roleId, @PathVariable("pageNum") Integer pageNum, 50 | @PathVariable("pageSize") Integer pageSize){ 51 | IPage roleMenuVOIPage = menuService.selectMenuByRoleId(new Page<>(pageNum, pageSize), roleId); 52 | int total = (int) roleMenuVOIPage.getTotal(); 53 | List records = roleMenuVOIPage.getRecords(); 54 | HashMap map = new HashMap<>(); 55 | map.put("total",total); 56 | map.put("roleMenu",records); 57 | return Result.success(Code.SUCCESS.getCode(),"",map); 58 | } 59 | 60 | @PostMapping("/add") 61 | public Result addRoleMenu(@RequestBody RoleMenu roleMenu){ 62 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 63 | wrapper.eq(Menu::getMenuId,roleMenu.getMenuId()); 64 | Menu one = menuService.getOne(wrapper); 65 | if (ObjectUtil.isNull(one)){ 66 | return Result.error(Code.ERROR_ADD.getCode(), Code.ERROR_ADD.getMsg()); 67 | } 68 | boolean save = roleMenuService.save(roleMenu); 69 | if (save){ 70 | return Result.success(Code.SUCCESS.getCode(),"添加成功"); 71 | }else { 72 | return Result.error(Code.ERROR_ADD.getCode(), Code.ERROR_ADD.getMsg()); 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.config; 2 | 3 | import com.wbm.forum.filter.JwtFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.http.HttpMethod; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.config.http.SessionCreationPolicy; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | import org.springframework.security.web.AuthenticationEntryPoint; 15 | import org.springframework.security.web.access.AccessDeniedHandler; 16 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 17 | import org.springframework.web.cors.CorsConfiguration; 18 | import org.springframework.web.cors.CorsConfigurationSource; 19 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 20 | import java.util.Arrays; 21 | 22 | /** 23 | * @Author:Ming 24 | * @Date: 2022/11/9 20:14 25 | */ 26 | @EnableWebSecurity 27 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 28 | 29 | @Autowired 30 | private JwtFilter jwtFilter; 31 | @Autowired 32 | private AuthenticationEntryPoint authenticationEntryPoint; 33 | @Autowired 34 | private AccessDeniedHandler accessDeniedHandler; 35 | 36 | @Bean 37 | @Override 38 | protected AuthenticationManager authenticationManager() throws Exception { 39 | return super.authenticationManager(); 40 | } 41 | 42 | @Bean 43 | PasswordEncoder passwordEncoder(){ 44 | return new BCryptPasswordEncoder(); 45 | } 46 | 47 | @Override 48 | protected void configure(HttpSecurity http) throws Exception { 49 | http 50 | .authorizeRequests() 51 | .antMatchers("/","/login").anonymous() 52 | .antMatchers("/image/**","/logout","/checkVerify/{verifyCode}/{uuid}","/verifyCode","/img/upload", 53 | "/email/**", "/user/forget/**","/user/register").permitAll() 54 | .anyRequest().authenticated() 55 | .and() 56 | .csrf() 57 | .disable() 58 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 59 | .and() 60 | .rememberMe() 61 | .and().cors().configurationSource(corsConfigurationSource()); 62 | http 63 | .logout().disable(); 64 | //添加过滤器 65 | http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); 66 | 67 | //配置异常处理器 68 | http.exceptionHandling() 69 | .authenticationEntryPoint(authenticationEntryPoint) 70 | .accessDeniedHandler(accessDeniedHandler); 71 | } 72 | //跨域 73 | CorsConfigurationSource corsConfigurationSource(){ 74 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 75 | corsConfiguration.setAllowedHeaders(Arrays.asList("*")); 76 | corsConfiguration.setAllowedMethods(Arrays.asList("*")); 77 | corsConfiguration.setAllowedOrigins(Arrays.asList("*")); 78 | corsConfiguration.setMaxAge(3600L); 79 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 80 | source.registerCorsConfiguration("/**",corsConfiguration); 81 | return source; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/CommentController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.date.LocalDateTimeUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.wbm.forum.common.Code; 7 | import com.wbm.forum.common.Result; 8 | import com.wbm.forum.entity.Comment; 9 | import com.wbm.forum.entity.Post; 10 | import com.wbm.forum.exception.MyServiceException; 11 | import com.wbm.forum.mapper.PostMapper; 12 | import com.wbm.forum.service.CommentService; 13 | import com.wbm.forum.utils.RedisUtils; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.access.prepost.PreAuthorize; 16 | import org.springframework.web.bind.annotation.*; 17 | import javax.websocket.server.PathParam; 18 | import java.util.Map; 19 | 20 | /** 21 | * @Author:Ming 22 | * @Date: 2022/11/19 14:39 23 | */ 24 | @RestController 25 | @RequestMapping(value = "/comment") 26 | public class CommentController { 27 | @Autowired 28 | private CommentService commentService; 29 | @Autowired 30 | private PostMapper postMapper; 31 | @Autowired 32 | private RedisUtils redisUtils; 33 | 34 | 35 | @GetMapping(value = "/{pid}") 36 | @PreAuthorize("hasAuthority('system:comment:get')") 37 | public Result getComment(@PathVariable Integer pid,@PathParam("pageNum") Integer pageNum, @PathParam("pageSize") Integer pageSize){ 38 | Map comment = commentService.getComment(pid, pageNum, pageSize); 39 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg(),comment); 40 | } 41 | 42 | @PostMapping 43 | @PreAuthorize("hasAuthority('system:comment:post')") 44 | public Result doComment(@RequestBody JSONObject jsonObject){ 45 | Integer pid = jsonObject.getInteger("pid"); 46 | String content = jsonObject.getString("content"); 47 | Integer uid = jsonObject.getInteger("uid"); 48 | if (pid == null || uid == null || StrUtil.isBlank(content)){ 49 | throw new MyServiceException(Code.ERROR.getCode(),"回复帖子失败"); 50 | } 51 | Comment comment = new Comment(); 52 | comment.setContent(content).setPid(pid).setReplyId(uid).setLikes(0L); 53 | Boolean res = commentService.doComment(comment); 54 | if (res){ 55 | Post post = new Post(); 56 | post.setPid(pid).setUpdateTime(LocalDateTimeUtil.now()); 57 | postMapper.updateById(post); 58 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg()); 59 | }else { 60 | return Result.success(Code.ERROR_ADD.getCode(),"回复失败"); 61 | } 62 | } 63 | 64 | 65 | @DeleteMapping(value = "/{cid}") 66 | @PreAuthorize("hasAuthority('system:comment:delete')") 67 | public Result deleteComment(@PathVariable Integer cid){ 68 | commentService.removeById(cid); 69 | // commentService.deleteComment(cid); 70 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 71 | } 72 | 73 | @PutMapping("/doLike/{cid}/{uid}") 74 | public Result doLike(@PathVariable("cid") Integer cid,@PathVariable("uid")Integer uid){ 75 | boolean b = redisUtils.sHasKey("commentLikes" + cid, uid); 76 | if (b){ 77 | throw new MyServiceException(Code.ERROR.getCode(),"已点赞"); 78 | }else { 79 | redisUtils.sSet("commentLikes" + cid,uid); 80 | return Result.success(Code.SUCCESS.getCode(),"点赞成功"); 81 | } 82 | } 83 | @PutMapping("/unDoLike/{cid}/{uid}") 84 | public Result unDoLike(@PathVariable("cid") Integer cid,@PathVariable("uid")Integer uid){ 85 | boolean b = redisUtils.sHasKey("commentLikes" + cid, uid); 86 | if (b) { 87 | redisUtils.setRemove("commentLikes" + cid, uid); 88 | return Result.success(Code.SUCCESS.getCode(),"取消成功"); 89 | }else { 90 | throw new MyServiceException(Code.ERROR.getCode(),"没有点赞"); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://localhost:3306/forum?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8 4 | username: root 5 | password: 6 | driver-class-name: com.mysql.jdbc.Driver 7 | type: com.alibaba.druid.pool.DruidDataSource 8 | druid: 9 | # 配置初始化大小、最小、最大 10 | initial-size: 5 11 | minIdle: 10 12 | max-active: 20 13 | # 配置获取连接等待超时的时间(单位:毫秒) 14 | max-wait: 60000 15 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 16 | time-between-eviction-runs-millis: 2000 17 | # 配置一个连接在池中最小生存的时间,单位是毫秒 18 | min-evictable-idle-time-millis: 600000 19 | max-evictable-idle-time-millis: 900000 20 | # 用来测试连接是否可用的SQL语句,默认值每种数据库都不相同,这是mysql 21 | validationQuery: select 1 22 | # 应用向连接池申请连接,并且testOnBorrow为false时,连接池将会判断连接是否处于空闲状态,如果是,则验证这条连接是否可用 23 | testWhileIdle: true 24 | # 如果为true,默认是false,应用向连接池申请连接时,连接池会判断这条连接是否是可用的 25 | testOnBorrow: false 26 | # 如果为true(默认false),当应用使用完连接,连接池回收连接的时候会判断该连接是否还可用 27 | testOnReturn: false 28 | # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle 29 | poolPreparedStatements: true 30 | # 要启用PSCache,必须配置大于0,当大于0时, poolPreparedStatements自动触发修改为true, 31 | # 在Druid中,不会存在Oracle下PSCache占用内存过多的问题, 32 | # 可以把这个数值配置大一些,比如说100 33 | maxOpenPreparedStatements: 20 34 | # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作 35 | keepAlive: true 36 | # Spring 监控,利用aop 对指定接口的执行时间,jdbc数进行记录 37 | aop-patterns: "com.springboot.template.dao.*" 38 | ########### 启用内置过滤器(第一个 stat必须,否则监控不到SQL)########## 39 | filters: stat,wall,log4j2 40 | # 自己配置监控统计拦截的filter 41 | filter: 42 | # 开启druiddatasource的状态监控 43 | stat: 44 | enabled: true 45 | db-type: mysql 46 | # 开启慢sql监控,超过2s 就认为是慢sql,记录到日志中 47 | log-slow-sql: true 48 | slow-sql-millis: 2000 49 | # 日志监控,使用slf4j 进行日志输出 50 | slf4j: 51 | enabled: true 52 | statement-log-error-enabled: true 53 | statement-create-after-log-enabled: false 54 | statement-close-after-log-enabled: false 55 | result-set-open-after-log-enabled: false 56 | result-set-close-after-log-enabled: false 57 | ########## 配置WebStatFilter,用于采集web关联监控的数据 ########## 58 | web-stat-filter: 59 | enabled: true # 启动 StatFilter 60 | url-pattern: /* # 过滤所有url 61 | exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 排除一些不必要的url 62 | session-stat-enable: true # 开启session统计功能 63 | session-stat-max-count: 1000 # session的最大个数,默认100 64 | ########## 配置StatViewServlet(监控页面),用于展示Druid的统计信息 ########## 65 | stat-view-servlet: 66 | enabled: true # 启用StatViewServlet 67 | url-pattern: /druid/* # 访问内置监控页面的路径,内置监控页面的首页是/druid/index.html 68 | reset-enable: false # 不允许清空统计数据,重新计算 69 | login-username: root # 配置监控页面访问密码 70 | login-password: 123 71 | allow: 127.0.0.1,localhost # 允许访问的地址,如果allow没有配置或者为空,则允许所有访问 72 | deny: # 拒绝访问的地址,deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝 73 | redis: 74 | port: 6379 75 | mail: 76 | #填写邮箱的账号密码 77 | host: smtp.163.com 78 | username: 79 | password: 80 | port: 994 81 | default-encoding: utf-8 82 | properties: 83 | mail: 84 | smtp: 85 | ssl: 86 | enable: true 87 | auth: true 88 | servlet: 89 | multipart: 90 | enabled: true 91 | max-file-size: 10MB 92 | max-request-size: 20MB 93 | server: 94 | port: 8080 95 | mybatis-plus: 96 | global-config: 97 | db-config: 98 | logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) 99 | logic-delete-value: 1 # 逻辑已删除值(默认为 1) 100 | logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) 101 | mapper-locations: classpath:mapper/*.xml 102 | configuration: 103 | # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 104 | cache-enabled: false 105 | #mybatis-plus配置控制台打印完整带参数SQL语句 106 | # level: 107 | # com.wbm.forum.mapper: debug -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/CommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import cn.hutool.core.convert.Convert; 4 | import cn.hutool.core.util.ObjectUtil; 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 9 | import com.wbm.forum.entity.Comment; 10 | import com.wbm.forum.entity.SecurityUser; 11 | import com.wbm.forum.entity.SubComment; 12 | import com.wbm.forum.entity.User; 13 | import com.wbm.forum.entity.vo.CommentVO; 14 | import com.wbm.forum.mapper.CommentMapper; 15 | import com.wbm.forum.mapper.SubCommentMapper; 16 | import com.wbm.forum.mapper.UserMapper; 17 | import com.wbm.forum.service.CommentService; 18 | import com.wbm.forum.utils.BeanCopyUtils; 19 | import com.wbm.forum.utils.RedisUtils; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.security.core.context.SecurityContextHolder; 22 | import org.springframework.stereotype.Service; 23 | 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.Set; 28 | 29 | /** 30 | * @author Ming 31 | * @description 针对表【comment】的数据库操作Service实现 32 | * @createDate 2022-11-12 13:10:05 33 | */ 34 | @Service 35 | public class CommentServiceImpl extends ServiceImpl 36 | implements CommentService { 37 | 38 | @Autowired 39 | private UserMapper userMapper; 40 | @Autowired 41 | private SubCommentMapper subCommentMapper; 42 | @Autowired 43 | private RedisUtils redisUtils; 44 | 45 | @Override 46 | public Map getComment(Integer pid, Integer pageNum, Integer pageSize) { 47 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 48 | queryWrapper.eq(Comment::getPid,pid); 49 | Page commentPage = page(new Page<>(pageNum, pageSize),queryWrapper); 50 | int total = (int) commentPage.getTotal(); 51 | List commentVOS = BeanCopyUtils.copyBeanList(commentPage.getRecords(), CommentVO.class); 52 | for (CommentVO commentVO : commentVOS) { 53 | User user = getUserInfo(commentVO.getReplyId()); 54 | commentVO.setAvatar(user.getAvatar()).setReplyName(user.getNickname()); 55 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 56 | wrapper.eq(SubComment::getRootId,commentVO.getCid()); 57 | List subComments = subCommentMapper.selectList(wrapper); 58 | commentVO.setSubCommentNum(subComments.size()).setLikes(getLikes(commentVO.getCid())); 59 | Boolean like = isLike(commentVO.getCid()); 60 | if (like){ 61 | commentVO.setIsLike("1"); 62 | } 63 | } 64 | HashMap map = new HashMap<>(); 65 | map.put("total",total); 66 | map.put("comment",commentVOS); 67 | return map; 68 | } 69 | 70 | @Override 71 | public Boolean doComment(Comment comment) { 72 | LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); 73 | lambdaQueryWrapper 74 | .select(Comment::getFloor) 75 | .orderByDesc(Comment::getFloor).eq(Comment::getPid,comment.getPid()); 76 | List comments = list(lambdaQueryWrapper); 77 | if (comments.size()==0){ 78 | comment.setFloor(2); 79 | }else { 80 | Integer lastFloor = comments.get(0).getFloor(); 81 | comment.setFloor(lastFloor+1); 82 | } 83 | return save(comment); 84 | } 85 | 86 | public User getUserInfo(Integer uid){ 87 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 88 | wrapper.eq(User::getUid,uid); 89 | User user = userMapper.selectOne(wrapper); 90 | return user; 91 | } 92 | 93 | public Integer getLikes(Integer cid){ 94 | Set objects = redisUtils.setMembers("commentLikes" + cid); 95 | return objects.size(); 96 | } 97 | 98 | public Boolean isLike(Integer cid){ 99 | SecurityUser principal = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 100 | Set objects = redisUtils.setMembers("commentLikes" + cid); 101 | return objects.contains(principal.getUser().getUid()); 102 | } 103 | } 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/test/java/com/wbm/forum/ForumApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.collection.ListUtil; 5 | import cn.hutool.core.util.ArrayUtil; 6 | import cn.hutool.core.util.ObjectUtil; 7 | import cn.hutool.core.util.StrUtil; 8 | import com.alibaba.fastjson.JSON; 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 10 | import com.baomidou.mybatisplus.core.metadata.IPage; 11 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 12 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 13 | import com.wbm.forum.common.Code; 14 | import com.wbm.forum.common.Result; 15 | import com.wbm.forum.entity.*; 16 | import com.wbm.forum.entity.vo.*; 17 | import com.wbm.forum.mapper.*; 18 | import com.wbm.forum.service.RoleService; 19 | import com.wbm.forum.service.UserRoleService; 20 | import com.wbm.forum.service.UserService; 21 | import com.wbm.forum.utils.BeanCopyUtils; 22 | import com.wbm.forum.utils.RedisUtils; 23 | import org.junit.jupiter.api.Test; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 27 | import org.springframework.security.crypto.password.PasswordEncoder; 28 | 29 | import javax.websocket.server.PathParam; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | import java.util.stream.Collectors; 34 | 35 | @SpringBootTest 36 | class ForumApplicationTests { 37 | private final RedisUtils redisUtils; 38 | @Autowired 39 | ForumApplicationTests(RedisUtils redisUtils) { 40 | this.redisUtils = redisUtils; 41 | } 42 | 43 | @Autowired 44 | private UserRoleService userRoleService; 45 | @Autowired 46 | private UserService userService; 47 | @Autowired 48 | private PostMapper postMapper; 49 | @Autowired 50 | private RoleMapper roleMapper; 51 | @Autowired 52 | private RoleService roleService; 53 | @Autowired 54 | private CommentMapper commentMapper; 55 | @Autowired 56 | private SubCommentMapper subCommentMapper; 57 | 58 | @Test 59 | void contextLoads() { 60 | } 61 | @Test 62 | public void changePwd(){ 63 | User user = new User(); 64 | PasswordEncoder encoder = new BCryptPasswordEncoder(); 65 | String encode = encoder.encode("111111"); 66 | user.setUid(1).setPassword(encode); 67 | userService.updateById(user); 68 | } 69 | @Test 70 | public void test2(){ 71 | String pwd = "$2a$10$GG3Xro1Jrs71FsLFsHxI7eGFRIqUEiE7uFLcF5rrD3YFIWB6gN/Ua"; 72 | PasswordEncoder encoder = new BCryptPasswordEncoder(); 73 | boolean encode = encoder.matches("222",pwd); 74 | System.out.println(encode); 75 | } 76 | 77 | @Test 78 | public void setCommentNum() { 79 | Page postPage = postMapper.selectPage(new Page<>(1, 10), null); 80 | List postVOS = BeanCopyUtils.copyBeanList(postPage.getRecords(), PostVO.class); 81 | List list = postVOS.stream().map(PostVO::getPid).collect(Collectors.toList()); 82 | 83 | List comments = commentMapper.selectList(Wrappers.lambdaQuery(Comment.class).in(Comment::getPid, list)); 84 | List collect = comments.stream().map(Comment::getCid).collect(Collectors.toList()); 85 | 86 | List subComments = subCommentMapper 87 | .selectList(Wrappers.lambdaQuery(SubComment.class).in(SubComment::getRootId, collect)); 88 | 89 | Map> subMap = subComments.stream().collect(Collectors.groupingBy(SubComment::getRootId)); 90 | 91 | // Map mapSub = subComments.stream().collect(Collectors.toMap(SubComment::getRootId, SubComment::getSubId)); 92 | Map> mapCom = comments.stream().collect(Collectors.groupingBy(Comment::getPid)); 93 | 94 | subMap.forEach((integer, subComments1) -> { 95 | 96 | }); 97 | 98 | postVOS.forEach(postVO -> { 99 | List comments1 = mapCom.get(postVO.getPid()); 100 | if (comments1!=null){ 101 | postVO.setCommentNum(comments1.size()); 102 | } 103 | }); 104 | System.out.println(comments); 105 | System.out.println("=========================="); 106 | postVOS.forEach(System.out::println); 107 | } 108 | @Test 109 | public void testsql(){ 110 | //List userRoleVOS = roleMapper.selectUserRole(); 111 | IPage userRoleVOIPage = roleMapper.selectUserRole(new Page<>(1, 10)); 112 | System.out.println(userRoleVOIPage.getRecords()); 113 | //userRoleVOS.forEach(System.out::println); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/SubCommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import cn.hutool.core.date.LocalDateTimeUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 9 | import com.wbm.forum.common.Code; 10 | import com.wbm.forum.common.Result; 11 | import com.wbm.forum.entity.Post; 12 | import com.wbm.forum.entity.SecurityUser; 13 | import com.wbm.forum.entity.SubComment; 14 | import com.wbm.forum.entity.User; 15 | import com.wbm.forum.entity.vo.SubCommentVO; 16 | import com.wbm.forum.exception.MyServiceException; 17 | import com.wbm.forum.mapper.PostMapper; 18 | import com.wbm.forum.mapper.SubCommentMapper; 19 | import com.wbm.forum.mapper.UserMapper; 20 | import com.wbm.forum.service.SubCommentService; 21 | import com.wbm.forum.utils.BeanCopyUtils; 22 | import com.wbm.forum.utils.RedisUtils; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.security.core.context.SecurityContextHolder; 25 | import org.springframework.stereotype.Service; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | import java.util.Set; 30 | 31 | /** 32 | * @author Ming 33 | * @description 针对表【sub_comment】的数据库操作Service实现 34 | * @createDate 2023-03-06 23:14:34 35 | */ 36 | @Service 37 | public class SubCommentServiceImpl extends ServiceImpl 38 | implements SubCommentService{ 39 | 40 | @Autowired 41 | private UserMapper userMapper; 42 | @Autowired 43 | private RedisUtils redisUtils; 44 | @Autowired 45 | private PostMapper postMapper; 46 | 47 | @Override 48 | public Map getSubComment(Integer cid, Integer pageNum, Integer pageSize) { 49 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 50 | wrapper.eq(SubComment::getRootId,cid); 51 | Page subCommentPage = page(new Page<>(pageNum, pageSize),wrapper); 52 | int total = (int) subCommentPage.getTotal(); 53 | List subComments = subCommentPage.getRecords(); 54 | List subCommentVOS = BeanCopyUtils.copyBeanList(subComments, SubCommentVO.class); 55 | for (SubCommentVO subCommentVO : subCommentVOS) { 56 | User user = getUserInfo(subCommentVO.getReplyId()); 57 | subCommentVO.setAvatar(user.getAvatar()).setReplyName(user.getNickname()).setLikes(getLikes(subCommentVO.getSubId())); 58 | Boolean like = isLike(subCommentVO.getSubId()); 59 | if (like){ 60 | subCommentVO.setIsLike("1"); 61 | } 62 | if (subCommentVO.getTargetId()!=null){ 63 | user = getUserInfo(subCommentVO.getTargetId()); 64 | subCommentVO.setTargetName(user.getNickname()); 65 | } 66 | } 67 | HashMap map = new HashMap<>(); 68 | map.put("total",total); 69 | map.put("subComment",subCommentVOS); 70 | return map; 71 | } 72 | 73 | @Override 74 | public Boolean postSubComment(JSONObject jsonObject) { 75 | Integer uid = jsonObject.getInteger("uid"); 76 | Integer cid = jsonObject.getInteger("cid"); 77 | Integer pid = jsonObject.getInteger("pid"); 78 | String content = jsonObject.getString("content"); 79 | if(uid==null || cid==null || StrUtil.isBlank(content) || pid==null){ 80 | throw new MyServiceException(Code.ERROR.getCode(),"回复失败"); 81 | } 82 | SubComment subComment = new SubComment(); 83 | subComment.setContent(content).setRootId(cid).setReplyId(uid).setLikes(0L); 84 | Integer targetId = jsonObject.getInteger("targetId"); 85 | if (targetId!=null){ 86 | subComment.setTargetId(targetId); 87 | } 88 | boolean save = save(subComment); 89 | if (save){ 90 | Post post = new Post(); 91 | post.setPid(pid).setUpdateTime(LocalDateTimeUtil.now()); 92 | postMapper.updateById(post); 93 | return true; 94 | }else { 95 | throw new MyServiceException(Code.ERROR.getCode(),"回复失败"); 96 | } 97 | 98 | } 99 | 100 | public Integer getLikes(Integer subId){ 101 | Set objects = redisUtils.setMembers("sucCommentLikes" + subId); 102 | return objects.size(); 103 | } 104 | public Boolean isLike(Integer subId){ 105 | SecurityUser principal = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 106 | Set objects = redisUtils.setMembers("sucCommentLikes" + subId); 107 | return objects.contains(principal.getUser().getUid()); 108 | } 109 | 110 | public User getUserInfo(Integer uid){ 111 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 112 | wrapper.eq(User::getUid,uid); 113 | User user = userMapper.selectOne(wrapper); 114 | return user; 115 | } 116 | } 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.alibaba.fastjson.JSON; 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 | import com.baomidou.mybatisplus.core.metadata.IPage; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.wbm.forum.common.Code; 9 | import com.wbm.forum.common.Result; 10 | import com.wbm.forum.entity.*; 11 | import com.wbm.forum.entity.vo.RoleMenuVO; 12 | import com.wbm.forum.entity.vo.UserRoleVO; 13 | import com.wbm.forum.mapper.MenuMapper; 14 | import com.wbm.forum.mapper.RoleMapper; 15 | import com.wbm.forum.mapper.UserRoleMapper; 16 | import com.wbm.forum.service.RoleMenuService; 17 | import com.wbm.forum.service.RoleService; 18 | import com.wbm.forum.service.UserRoleService; 19 | import com.wbm.forum.service.UserService; 20 | import com.wbm.forum.utils.BeanCopyUtils; 21 | import com.wbm.forum.utils.RedisUtils; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.security.core.parameters.P; 24 | import org.springframework.web.bind.annotation.*; 25 | import javax.websocket.server.PathParam; 26 | import java.util.Comparator; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Objects; 30 | import java.util.stream.Collectors; 31 | 32 | /** 33 | * @Author:Ming 34 | * @Date: 2023/3/13 0:00 35 | */ 36 | @RestController 37 | @RequestMapping("/role") 38 | public class RoleController { 39 | 40 | @Autowired 41 | private UserRoleService userRoleService; 42 | @Autowired 43 | private UserService userService; 44 | @Autowired 45 | private RedisUtils redisUtils; 46 | @Autowired 47 | private MenuMapper menuMapper; 48 | @Autowired 49 | private RoleMapper roleMapper; 50 | @Autowired 51 | private RoleMenuService roleMenuService; 52 | @Autowired 53 | private RoleService roleService; 54 | 55 | @PostMapping("/user") 56 | public Result makeRoleForUser(@RequestBody User user){ 57 | Boolean role = roleService.makeRoleForUser(user); 58 | if (role){ 59 | userService.updateById(user); 60 | redisUtils.delete("login"+user.getUid()); 61 | User byId = userService.getById(user.getUid()); 62 | List permission = menuMapper.selectPermissionByUid(byId.getUid()); 63 | List path = menuMapper.selectPathByUid(byId.getUid()) 64 | .stream().filter(Objects::nonNull).collect(Collectors.toList()); 65 | List component = menuMapper.selectComponentByUid(byId.getUid()) 66 | .stream().filter(Objects::nonNull).collect(Collectors.toList()); 67 | SecurityUser securityUser = new SecurityUser(byId,permission,path,component); 68 | redisUtils.set("login-"+user.getUid(), JSON.toJSONString(securityUser),60*24L); 69 | HashMap map = new HashMap<>(); 70 | map.put("user", securityUser.getUser()); 71 | map.put("permission", securityUser.getPermission()); 72 | map.put("path", securityUser.getPath()); 73 | map.put("component", securityUser.getComponent()); 74 | return Result.success(Code.SUCCESS.getCode(),Code.SUCCESS.getMsg(),map); 75 | }else { 76 | return Result.error(Code.ERROR.getCode(),Code.ERROR.getMsg()); 77 | } 78 | } 79 | 80 | @GetMapping("/userRole") 81 | public Result getAllRoleForUser(@PathParam("pageNum") Integer pageNum, @PathParam("pageSize") Integer pageSize){ 82 | IPage userRoleVOIPage = roleMapper.selectUserRole(new Page<>(pageNum, pageSize)); 83 | int total = (int) userRoleVOIPage.getTotal(); 84 | List records = userRoleVOIPage.getRecords(); 85 | HashMap map = new HashMap<>(); 86 | map.put("total",total); 87 | map.put("userRole", records); 88 | return Result.success(Code.SUCCESS.getCode(),"",map); 89 | } 90 | 91 | @DeleteMapping("/{roleId}/{menuId}") 92 | public Result del(@PathVariable Integer roleId,@PathVariable Integer menuId){ 93 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 94 | wrapper.eq(RoleMenu::getRoleId,roleId) 95 | .eq(RoleMenu::getMenuId,menuId); 96 | boolean remove = roleMenuService.remove(wrapper); 97 | if (remove){ 98 | return Result.success(Code.SUCCESS.getCode(),""); 99 | }else { 100 | return Result.error(Code.ERROR_DELETE.getCode(), Code.ERROR_DELETE.getMsg()); 101 | } 102 | 103 | } 104 | @PutMapping("/{uid}/{roleId}") 105 | public Result changeRole(@PathVariable("uid") Integer uid,@PathVariable("roleId") Integer roleId){ 106 | UserRole userRole = new UserRole(); 107 | userRole.setRoleId(roleId).setUid(uid); 108 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 109 | wrapper.eq(UserRole::getUid,uid); 110 | boolean update = userRoleService.saveOrUpdate(userRole, wrapper); 111 | if (update){ 112 | return Result.success(Code.SUCCESS.getCode(),"修改成功"); 113 | }else { 114 | return Result.error(Code.ERROR_UPDATE.getCode(), Code.ERROR_UPDATE.getMsg()); 115 | } 116 | } 117 | 118 | @DeleteMapping("/{uid}") 119 | public Result delUserRole(@PathVariable("uid") Integer uid){ 120 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 121 | wrapper.eq(UserRole::getUid,uid); 122 | boolean remove = userRoleService.remove(wrapper); 123 | if (remove){ 124 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 125 | }else { 126 | return Result.error(Code.ERROR_DELETE.getCode(), Code.ERROR_DELETE.getMsg()); 127 | } 128 | 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/PostController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.wbm.forum.common.Code; 8 | import com.wbm.forum.common.Result; 9 | import com.wbm.forum.entity.Post; 10 | import com.wbm.forum.entity.vo.PostVO; 11 | import com.wbm.forum.exception.MyServiceException; 12 | import com.wbm.forum.service.PostService; 13 | import com.wbm.forum.utils.BeanCopyUtils; 14 | import com.wbm.forum.utils.RedisUtils; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.security.access.prepost.PreAuthorize; 17 | import org.springframework.web.bind.annotation.*; 18 | import javax.websocket.server.PathParam; 19 | import java.util.Date; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | /** 25 | * @Author:Ming 26 | * @Date: 2022/11/10 23:52 27 | */ 28 | @RestController 29 | @RequestMapping(value = "/post") 30 | public class PostController { 31 | 32 | @Autowired 33 | private PostService postService; 34 | @Autowired 35 | private RedisUtils redisUtils; 36 | 37 | @GetMapping 38 | public Result getAllPost(@PathParam("pageNum") Integer pageNum,@PathParam("pageSize") Integer pageSize){ 39 | Map allPost = postService.getAllPost(pageNum, pageSize); 40 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(),allPost); 41 | } 42 | 43 | @GetMapping(value = "/pid/{pid}") 44 | @PreAuthorize("hasAuthority('system:post:get')") 45 | public Result getPost(@PathVariable("pid") Integer pid){ 46 | PostVO postVO = postService.getPost(pid); 47 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(), postVO); 48 | } 49 | 50 | @GetMapping(value = "/search/{key}") 51 | @PreAuthorize("hasAuthority('system:post:get')") 52 | public Result getPostByTitle(@PathVariable("key") String key){ 53 | List postByTitle = postService.getPostByTitle(key); 54 | if(postByTitle.isEmpty()){ 55 | return Result.success(Code.ERROR_QUERY.getCode(), Code.ERROR_QUERY.getMsg()); 56 | } 57 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(),postByTitle); 58 | } 59 | 60 | @GetMapping(value = "/uid/{uid}") 61 | @PreAuthorize("hasAuthority('system:post:get')") 62 | public Result getPostByUid(@PathVariable("uid") Integer uid,@PathParam("pageNum") Integer pageNum, 63 | @PathParam("pageSize") Integer pageSize){ 64 | Map postByUid = postService.getPostByUid(uid, pageNum, pageSize); 65 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(),postByUid); 66 | } 67 | 68 | @PostMapping 69 | @PreAuthorize("hasAuthority('system:post:post')") 70 | public Result post(@RequestBody Post post){ 71 | Integer result = postService.addPost(post); 72 | if (result == 1){ 73 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg()); 74 | } 75 | return Result.error(Code.ERROR_ADD.getCode(), "发帖失败"); 76 | } 77 | @DeleteMapping(value = "/{pid}") 78 | @PreAuthorize("hasAuthority('system:post:delete')") 79 | public Result deletePost(@PathVariable Integer pid){ 80 | postService.deletePost(pid); 81 | return Result.success(Code.SUCCESS.getCode(), "删除成功"); 82 | } 83 | 84 | @PostMapping(value = "/del/{ids}") 85 | @PreAuthorize("hasAuthority('system:post:delete')") 86 | public Result deletePosts(@PathVariable List ids){ 87 | postService.removeByIds(ids); 88 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 89 | } 90 | @PutMapping("/top") 91 | public Result changeIsTop(@RequestBody Post post){ 92 | if (post.getIsTop().equals("0")){ 93 | post.setIsTop("1"); 94 | }else if (post.getIsTop().equals("1")){ 95 | post.setIsTop("0"); 96 | } 97 | postService.updateById(post); 98 | return Result.success(Code.SUCCESS.getCode(),""); 99 | } 100 | @PostMapping("/searchByTime") 101 | public Result searchByTime(@RequestBody JSONObject jsonObject,@PathParam("pageNum") Integer pageNum, 102 | @PathParam("pageSize") Integer pageSize){ 103 | Date from = jsonObject.getDate("from"); 104 | Date to = jsonObject.getDate("to"); 105 | Map map = postService.searchByTime(from, to, pageNum, pageSize); 106 | return Result.success(Code.SUCCESS.getCode(),"",map); 107 | } 108 | @PostMapping("/searchByPid") 109 | public Result searchByPid(@RequestBody Post post) { 110 | List postByPid = postService.getPostByPid(post); 111 | return Result.success(Code.SUCCESS.getCode(),"",postByPid); 112 | } 113 | @PostMapping("/selectByType") 114 | public Result selectByType(@RequestBody Post post,@PathParam("pageNum") Integer pageNum,@PathParam("pageSize") Integer pageSize){ 115 | Map map = postService.selectByType(post, pageNum, pageSize); 116 | return Result.success(Code.SUCCESS.getCode(),"",map); 117 | } 118 | @PutMapping("/views/{pid}") 119 | public Result getViews(@PathVariable Integer pid){ 120 | redisUtils.hIncrBy("postViews",pid.toString(),1); 121 | Integer views = (Integer) redisUtils.hget("postViews", pid.toString()); 122 | return Result.success(Code.SUCCESS.getCode(),"",views); 123 | } 124 | @PutMapping("/doLike/{pid}/{uid}") 125 | public Result doLike(@PathVariable("pid") Integer pid,@PathVariable("uid")Integer uid){ 126 | boolean b = redisUtils.sHasKey("postLikes" + pid, uid); 127 | if (b){ 128 | throw new MyServiceException(Code.ERROR.getCode(),"已点赞"); 129 | }else { 130 | redisUtils.sSet("postLikes" + pid,uid); 131 | return Result.success(Code.SUCCESS.getCode(),"点赞成功"); 132 | } 133 | } 134 | @PutMapping("/unDoLike/{pid}/{uid}") 135 | public Result unDoLike(@PathVariable("pid") Integer pid,@PathVariable("uid")Integer uid){ 136 | boolean b = redisUtils.sHasKey("postLikes" + pid, uid); 137 | if (b) { 138 | redisUtils.setRemove("postLikes" + pid, uid); 139 | return Result.success(Code.SUCCESS.getCode(),"取消成功"); 140 | }else { 141 | throw new MyServiceException(Code.ERROR.getCode(),"没有点赞"); 142 | } 143 | } 144 | 145 | 146 | 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/EchartsController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.convert.Convert; 5 | import cn.hutool.core.date.DateUtil; 6 | import cn.hutool.core.date.Quarter; 7 | import com.wbm.forum.common.Code; 8 | import com.wbm.forum.common.Result; 9 | import com.wbm.forum.entity.Comment; 10 | import com.wbm.forum.entity.Post; 11 | import com.wbm.forum.entity.SubComment; 12 | import com.wbm.forum.entity.User; 13 | import com.wbm.forum.service.CommentService; 14 | import com.wbm.forum.service.PostService; 15 | import com.wbm.forum.service.SubCommentService; 16 | import com.wbm.forum.service.UserService; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.security.access.prepost.PreAuthorize; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | import java.time.LocalDateTime; 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.stream.Collectors; 29 | 30 | /** 31 | * @Author:Ming 32 | * @Date: 2023/2/25 15:30 33 | */ 34 | @RestController 35 | @RequestMapping(value = "/echarts") 36 | @PreAuthorize("hasAuthority('system:management')") 37 | public class EchartsController { 38 | @Autowired 39 | private UserService userService; 40 | @Autowired 41 | private PostService postService; 42 | @Autowired 43 | private CommentService commentService; 44 | @Autowired 45 | private SubCommentService subCommentService; 46 | 47 | @GetMapping(value = "/user") 48 | public Result getUserNum(){ 49 | List list = userService.list(); 50 | int q1 = 0; 51 | int q2 = 0; 52 | int q3 = 0; 53 | int q4 = 0; 54 | for (User user : list) { 55 | LocalDateTime createTime = user.getCreateTime(); 56 | Quarter quarter = DateUtil.quarterEnum(Convert.toDate(createTime)); 57 | if (quarter.equals(Quarter.Q1)){ 58 | q1 += 1; 59 | } 60 | if (quarter.equals(Quarter.Q2)){ 61 | q2 += 1; 62 | } 63 | if (quarter.equals(Quarter.Q3)){ 64 | q3 += 1; 65 | } 66 | if (quarter.equals(Quarter.Q4)){ 67 | q4 += 1; 68 | } 69 | } 70 | ArrayList arrayList = CollUtil.newArrayList(q1,q2,q3,q4); 71 | List collect = list.stream().map(User::getSex).collect(Collectors.toList()); 72 | int man = 0; 73 | int women = 0; 74 | int other = 0; 75 | for (String s : collect) { 76 | if (s.equals("男")){ 77 | man +=1; 78 | }else if (s.equals("女")){ 79 | women +=1; 80 | }else { 81 | other +=1; 82 | } 83 | } 84 | ArrayList sex = CollUtil.newArrayList(man, women, other); 85 | Map map = new HashMap<>(); 86 | map.put("num",arrayList); 87 | map.put("sex",sex); 88 | return Result.success(Code.SUCCESS.getCode(),"",map); 89 | } 90 | @GetMapping(value = "/post") 91 | public Result getPostNum(){ 92 | List postList = postService.list(); 93 | int q1 = 0; 94 | int q2 = 0; 95 | int q3 = 0; 96 | int q4 = 0; 97 | for (Post post : postList) { 98 | LocalDateTime date = post.getCreateTime(); 99 | Quarter quarter = DateUtil.quarterEnum(Convert.toDate(date)); 100 | if (quarter.equals(Quarter.Q1)){ 101 | q1 += 1; 102 | } 103 | if (quarter.equals(Quarter.Q2)){ 104 | q2 += 1; 105 | } 106 | if (quarter.equals(Quarter.Q3)){ 107 | q3 += 1; 108 | } 109 | if (quarter.equals(Quarter.Q4)){ 110 | q4 += 1; 111 | } 112 | } 113 | ArrayList arrayList = CollUtil.newArrayList(q1,q2,q3,q4); 114 | return Result.success(Code.SUCCESS.getCode(),"",arrayList); 115 | } 116 | @GetMapping(value = "/comment") 117 | public Result commentNum(){ 118 | List comments = commentService.list(); 119 | List subComments = subCommentService.list(); 120 | int count = comments.size() + subComments.size(); 121 | return Result.success(Code.SUCCESS.getCode(),"",count); 122 | } 123 | } 124 | // @GetMapping(value = "/user") 125 | // public Result getUserNum(){ 126 | // List list = userService.list(); 127 | // int q1 = (int) list.stream() 128 | // .filter(user -> DateUtil.quarterEnum(Convert.toDate(user.getCreateTime())).equals(Quarter.Q1)).count(); 129 | // int q2 = (int) list.stream() 130 | // .filter(user -> DateUtil.quarterEnum(Convert.toDate(user.getCreateTime())).equals(Quarter.Q2)).count(); 131 | // int q3 = (int) list.stream() 132 | // .filter(user -> DateUtil.quarterEnum(Convert.toDate(user.getCreateTime())).equals(Quarter.Q3)).count(); 133 | // int q4 = (int) list.stream() 134 | // .filter(user -> DateUtil.quarterEnum(Convert.toDate(user.getCreateTime())).equals(Quarter.Q4)).count(); 135 | // ArrayList arrayList = CollUtil.newArrayList(q1,q2,q3,q4); 136 | // Map> sexMap = list.stream().collect(Collectors.groupingBy(User::getSex)); 137 | // int man = sexMap.get("男").size(); 138 | // int women = sexMap.get("女").size(); 139 | // int other = sexMap.get("保密").size(); 140 | // ArrayList sex = CollUtil.newArrayList(man, women, other); 141 | // Map map = new HashMap<>(); 142 | // map.put("num",arrayList); 143 | // map.put("sex",sex); 144 | // return Result.success(Code.SUCCESS.getCode(),"",map); 145 | // } 146 | // 147 | // @GetMapping(value = "/post") 148 | // public Result getPostNum(){ 149 | // List postList = postService.list(); 150 | // int q1 = (int) postList.stream() 151 | // .filter(post -> DateUtil.quarterEnum(Convert.toDate(post.getCreateTime())).equals(Quarter.Q1)).count(); 152 | // int q2 = (int) postList.stream() 153 | // .filter(post -> DateUtil.quarterEnum(Convert.toDate(post.getCreateTime())).equals(Quarter.Q2)).count(); 154 | // int q3 = (int) postList.stream() 155 | // .filter(post -> DateUtil.quarterEnum(Convert.toDate(post.getCreateTime())).equals(Quarter.Q3)).count(); 156 | // int q4 = (int) postList.stream() 157 | // .filter(post -> DateUtil.quarterEnum(Convert.toDate(post.getCreateTime())).equals(Quarter.Q4)).count(); 158 | // ArrayList arrayList = CollUtil.newArrayList(q1,q2,q3,q4); 159 | // return Result.success(Code.SUCCESS.getCode(),"",arrayList); 160 | // } 161 | // 162 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.4.0 9 | 10 | 11 | com.wbm 12 | forum 13 | 0.0.1-SNAPSHOT 14 | forum 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-json 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | com.alibaba 59 | druid-spring-boot-starter 60 | 1.2.8 61 | 62 | 63 | 64 | com.alibaba 65 | fastjson 66 | 1.2.83 67 | 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-mail 72 | 73 | 74 | 75 | 76 | com.github.penggle 77 | kaptcha 78 | 2.3.2 79 | 80 | 81 | 82 | cn.hutool 83 | hutool-all 84 | 5.3.9 85 | 86 | 87 | 88 | 89 | io.jsonwebtoken 90 | jjwt 91 | 0.9.1 92 | 93 | 94 | 95 | com.baomidou 96 | mybatis-plus-boot-starter 97 | 3.4.2 98 | 99 | 100 | 101 | com.zaxxer 102 | HikariCP 103 | 104 | 105 | 106 | 107 | 108 | 109 | org.springframework.boot 110 | spring-boot-starter-data-redis 111 | 112 | 113 | org.springframework.boot 114 | spring-boot-starter-security 115 | 116 | 117 | 118 | 119 | org.springframework.boot 120 | spring-boot-devtools 121 | runtime 122 | true 123 | 124 | 125 | mysql 126 | mysql-connector-java 127 | 5.1.49 128 | runtime 129 | 130 | 131 | org.springframework.boot 132 | spring-boot-configuration-processor 133 | true 134 | 135 | 136 | org.projectlombok 137 | lombok 138 | true 139 | 140 | 141 | org.springframework.boot 142 | spring-boot-starter-test 143 | test 144 | 145 | 146 | org.springframework.security 147 | spring-security-test 148 | test 149 | 150 | 151 | org.jetbrains 152 | annotations 153 | RELEASE 154 | compile 155 | 156 | 157 | 158 | 159 | 160 | 161 | org.apache.maven.plugins 162 | maven-compiler-plugin 163 | 3.8.1 164 | 165 | 1.8 166 | 1.8 167 | UTF-8 168 | 169 | 170 | 171 | org.springframework.boot 172 | spring-boot-maven-plugin 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.alibaba.fastjson.JSON; 6 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 9 | import com.wbm.forum.common.Code; 10 | import com.wbm.forum.common.Result; 11 | import com.wbm.forum.entity.SecurityUser; 12 | import com.wbm.forum.entity.User; 13 | import com.wbm.forum.entity.vo.UserVO; 14 | import com.wbm.forum.exception.MyServiceException; 15 | import com.wbm.forum.mapper.UserMapper; 16 | import com.wbm.forum.service.RoleService; 17 | import com.wbm.forum.service.UserService; 18 | import com.wbm.forum.utils.BeanCopyUtils; 19 | import com.wbm.forum.utils.JwtUtils; 20 | import com.wbm.forum.utils.RedisUtils; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.security.authentication.AuthenticationManager; 24 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 25 | import org.springframework.security.core.Authentication; 26 | import org.springframework.security.core.context.SecurityContextHolder; 27 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 28 | import org.springframework.security.crypto.password.PasswordEncoder; 29 | import org.springframework.stereotype.Service; 30 | 31 | import java.util.HashMap; 32 | import java.util.List; 33 | import java.util.Map; 34 | 35 | /** 36 | * @author Ming 37 | * @description 针对表【user】的数据库操作Service实现 38 | * @createDate 2022-11-12 14:52:05 39 | */ 40 | @Service 41 | @Slf4j 42 | public class UserServiceImpl extends ServiceImpl 43 | implements UserService { 44 | 45 | @Autowired 46 | private AuthenticationManager authenticationManager; 47 | @Autowired 48 | private RedisUtils redisUtils; 49 | @Autowired 50 | private UserMapper userMapper; 51 | @Autowired 52 | private RoleService roleService; 53 | 54 | @Override 55 | public Result login(User user) { 56 | UsernamePasswordAuthenticationToken authenticationToken 57 | = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword()); 58 | Authentication authentication = authenticationManager.authenticate(authenticationToken); 59 | if (ObjectUtil.isNull(authentication)){ 60 | throw new MyServiceException(Code.LOGIN_FAIL.getCode(),Code.LOGIN_FAIL.getMsg()); 61 | } 62 | SecurityUser securityUser = (SecurityUser) authentication.getPrincipal(); 63 | String uid = securityUser.getUser().getUid().toString(); 64 | String jwt = JwtUtils.getJwtToken(uid); 65 | String str = JSON.toJSONString(securityUser); 66 | redisUtils.set("login-"+uid, str,60*24L); 67 | HashMap map = new HashMap<>(); 68 | map.put("user", securityUser.getUser()); 69 | map.put("permission", securityUser.getPermission()); 70 | map.put("path", securityUser.getPath()); 71 | map.put("component", securityUser.getComponent()); 72 | map.put("token",jwt); 73 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(),map); 74 | } 75 | 76 | 77 | 78 | @Override 79 | public Map getAllUser(Integer pageNum, Integer pageSize) { 80 | Page userPage = userMapper.selectPage(new Page<>(pageNum,pageSize),null); 81 | List records = userPage.getRecords(); 82 | int total = (int) userPage.getTotal(); 83 | List userVOS = BeanCopyUtils.copyBeanList(records, UserVO.class); 84 | HashMap map = new HashMap<>(); 85 | map.put("userList", userVOS); 86 | map.put("total",total); 87 | return map; 88 | } 89 | 90 | @Override 91 | public Boolean changePwd(String oldPassword, String newPassword, String repeatPassword) { 92 | SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 93 | String password = securityUser.getPassword(); 94 | PasswordEncoder encoder = new BCryptPasswordEncoder(); 95 | boolean matches = encoder.matches(oldPassword,password); 96 | if (matches){ 97 | String encode = encoder.encode(newPassword); 98 | User user = securityUser.getUser(); 99 | user.setPassword(encode); 100 | int update = userMapper.updateById(user); 101 | if (1 == update){ 102 | String login = "login-"+securityUser.getUser().getUid(); 103 | redisUtils.delete(login); 104 | return true; 105 | } 106 | }else { 107 | throw new MyServiceException(Code.PASSWORD_OLD_WRONG.getCode(),"旧密码错误"); 108 | } 109 | return false; 110 | } 111 | 112 | @Override 113 | public Boolean forgetPassword(String username, String password, String email, String code) { 114 | String redisCode = redisUtils.get(email); 115 | if (StrUtil.isBlank(redisCode)){ 116 | throw new MyServiceException(Code.VERIFY_CODE_EXPIRED.getCode(),Code.VERIFY_CODE_EXPIRED.getMsg()); 117 | } 118 | if (!redisCode.equals(code)){ 119 | throw new MyServiceException(Code.VERIFICATION_FAIL.getCode(), Code.VERIFICATION_FAIL.getMsg()); 120 | } 121 | PasswordEncoder encoder = new BCryptPasswordEncoder(); 122 | String encode = encoder.encode(password); 123 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 124 | User user = new User(); 125 | user.setPassword(encode); 126 | queryWrapper 127 | .eq(User::getUsername,username) 128 | .eq(User::getEmail,email); 129 | boolean update = update(user, queryWrapper); 130 | if (update){ 131 | return true; 132 | } 133 | return false; 134 | } 135 | 136 | @Override 137 | public Boolean register(User user) { 138 | checkUsernameUnique(user.getUsername()); 139 | checkNicknameUnique(user.getNickname()); 140 | PasswordEncoder encoder = new BCryptPasswordEncoder(); 141 | String encode = encoder.encode(user.getPassword()); 142 | user.setPassword(encode).setSex("保密"); 143 | int insert = userMapper.insert(user); 144 | if (StrUtil.isNotBlank(user.getIdentity())){ 145 | roleService.makeRoleForUser(user); 146 | } 147 | if (1==insert){ 148 | redisUtils.hset("userMap",user.getUid().toString(),user); 149 | return true; 150 | } 151 | return false; 152 | } 153 | public void checkUsernameUnique(String username){ 154 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 155 | queryWrapper.eq(User::getUsername,username); 156 | User user = userMapper.selectOne(queryWrapper); 157 | if (ObjectUtil.isNotNull(user)){ 158 | throw new MyServiceException(Code.REGISTER_ERROR.getCode(), "用户名已存在"); 159 | } 160 | } 161 | public void checkNicknameUnique(String nickname){ 162 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 163 | wrapper.eq(User::getUsername,nickname); 164 | User user = userMapper.selectOne(wrapper); 165 | if (ObjectUtil.isNotNull(user)){ 166 | throw new MyServiceException(Code.REGISTER_ERROR.getCode(), "昵称已存在"); 167 | } 168 | } 169 | } 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.controller; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.alibaba.fastjson.JSON; 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 8 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 9 | import com.wbm.forum.common.Code; 10 | import com.wbm.forum.common.Result; 11 | import com.wbm.forum.entity.SecurityUser; 12 | import com.wbm.forum.entity.User; 13 | import com.wbm.forum.entity.dto.UserDTO; 14 | import com.wbm.forum.entity.vo.UserVO; 15 | import com.wbm.forum.exception.MyServiceException; 16 | import com.wbm.forum.service.UserService; 17 | import com.wbm.forum.utils.BeanCopyUtils; 18 | import com.wbm.forum.utils.RedisUtils; 19 | import lombok.extern.slf4j.Slf4j; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.security.core.context.SecurityContextHolder; 22 | import org.springframework.validation.annotation.Validated; 23 | import org.springframework.web.bind.annotation.*; 24 | import javax.websocket.server.PathParam; 25 | import java.util.Date; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | /** 31 | * @Author:Ming 32 | * @Date: 2023/2/25 14:44 33 | */ 34 | @RestController 35 | @RequestMapping(value = "/user") 36 | @Slf4j 37 | public class UserController { 38 | 39 | @Autowired 40 | private UserService userService; 41 | @Autowired 42 | private RedisUtils redisUtils; 43 | 44 | @GetMapping("/all") 45 | public Result allUser(@PathParam("pageNum") Integer pageNum, @PathParam("pageSize") Integer pageSize){ 46 | Map allUser = userService.getAllUser(pageNum, pageSize); 47 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg(),allUser); 48 | } 49 | 50 | @PostMapping 51 | public Result addUser(@RequestBody User user){ 52 | if (StrUtil.isBlank(user.getPassword()) ){ 53 | user.setPassword("000000"); 54 | } 55 | Boolean register = userService.register(user); 56 | if (register){ 57 | return Result.success(Code.SUCCESS.getCode(),"添加成功"); 58 | } 59 | return Result.error(Code.ERROR_ADD.getCode(),Code.ERROR_ADD.getMsg()); 60 | } 61 | 62 | @DeleteMapping("/{uid}") 63 | public Result deleteUser(@PathVariable Integer uid){ 64 | boolean b = userService.removeById(uid); 65 | if (b){ 66 | redisUtils.hDelete("userMap",uid.toString()); 67 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 68 | } 69 | return Result.error(Code.ERROR_DELETE.getCode(),Code.ERROR_DELETE.getMsg()); 70 | } 71 | @PostMapping(value = "/del/{ids}") 72 | public Result deleteUsers(@PathVariable List ids){ 73 | boolean b = userService.removeByIds(ids); 74 | if (b){ 75 | ids.forEach(i -> redisUtils.hDelete("userMap",i.toString())); 76 | return Result.success(Code.SUCCESS.getCode(),"删除成功"); 77 | } 78 | return Result.error(Code.ERROR_DELETE.getCode(),Code.ERROR_DELETE.getMsg()); 79 | } 80 | @PutMapping 81 | public Result update(@RequestBody UserDTO userDTO){ 82 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 83 | queryWrapper.eq(User::getNickname,userDTO.getNickname()); 84 | User one = userService.getOne(queryWrapper); 85 | if (ObjectUtil.isNotEmpty(one)&& !(one.getUid().equals(userDTO.getUid()))){ 86 | throw new MyServiceException(Code.ERROR_UPDATE.getCode(),"昵称已存在"); 87 | } 88 | User user = BeanCopyUtils.copyBean(userDTO, User.class); 89 | boolean res = userService.updateById(user); 90 | if (res){ 91 | User byId = userService.getById(user.getUid()); 92 | redisUtils.hset("userMap",byId.getUid().toString(),byId); 93 | return Result.success(Code.SUCCESS.getCode(), "修改成功",byId); 94 | }else { 95 | return Result.error(Code.ERROR_UPDATE.getCode(), Code.ERROR_UPDATE.getMsg()); 96 | } 97 | } 98 | 99 | @PostMapping("/changPwd") 100 | public Result changePassword(@RequestBody JSONObject jsonObject){ 101 | String oldPassword = jsonObject.getString("oldPassword"); 102 | String newPassword = jsonObject.getString("newPassword"); 103 | String repeatPassword = jsonObject.getString("repeatPassword"); 104 | if (StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword) || StrUtil.isBlank(repeatPassword)){ 105 | Result.error(Code.PASSWORD_UPDATE_FAIL.getCode(), Code.PASSWORD_UPDATE_FAIL.getMsg()); 106 | } 107 | if (!newPassword.equals(repeatPassword)){ 108 | return Result.error(Code.PASSWORD_TWICE_FAIL.getCode(), Code.PASSWORD_TWICE_FAIL.getMsg()); 109 | } 110 | Boolean changePwd = userService.changePwd(oldPassword, newPassword, repeatPassword); 111 | if (changePwd){ 112 | SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 113 | String login = "login-"+securityUser.getUser().getUid(); 114 | redisUtils.delete(login); 115 | return Result.success(Code.SUCCESS.getCode(), "修改密码成功,请重新登录"); 116 | }else { 117 | return Result.error(Code.PASSWORD_UPDATE_FAIL.getCode(), Code.PASSWORD_UPDATE_FAIL.getMsg()); 118 | } 119 | } 120 | 121 | @PostMapping("/forget") 122 | public Result forgetPassword(@RequestBody JSONObject jsonObject){ 123 | String username = jsonObject.getString("username"); 124 | String password = jsonObject.getString("password"); 125 | String email = jsonObject.getString("email"); 126 | String code = jsonObject.getString("code"); 127 | if (StrUtil.isBlank(username) || StrUtil.isBlank(password) || StrUtil.isBlank(email) || StrUtil.isBlank(code)){ 128 | return Result.error(Code.ERROR_UPDATE.getCode(), Code.ERROR_UPDATE.getMsg()); 129 | } 130 | Boolean flag = userService.forgetPassword(username, password, email, code); 131 | if (flag){ 132 | return Result.success(Code.SUCCESS.getCode(), Code.SUCCESS.getMsg()); 133 | } 134 | return Result.error(Code.ERROR_UPDATE.getCode(), Code.ERROR_UPDATE.getMsg()); 135 | } 136 | 137 | @PostMapping("/register") 138 | public Result register(@RequestBody User user){ 139 | if (StrUtil.isNotBlank(user.getUsername()) && StrUtil.isNotBlank(user.getPassword()) 140 | && StrUtil.isNotBlank(user.getNickname())&&StrUtil.isNotBlank(user.getEmail())){ 141 | Boolean register = userService.register(user); 142 | if (register){ 143 | return Result.success(Code.SUCCESS.getCode(), "注册成功"); 144 | } 145 | } 146 | return Result.error(Code.REGISTER_ERROR.getCode(), Code.REGISTER_ERROR.getMsg()); 147 | } 148 | 149 | @PostMapping("/searchByTime") 150 | public Result searchByTime(@RequestBody JSONObject jsonObject,@PathParam("pageNum") Integer pageNum,@PathParam("pageSize") Integer pageSize){ 151 | Date from = jsonObject.getDate("from"); 152 | Date to = jsonObject.getDate("to"); 153 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 154 | wrapper.between(User::getCreateTime, from, to); 155 | Page page = userService.page(new Page<>(pageNum, pageSize), wrapper); 156 | List list = page.getRecords(); 157 | int total = (int) page.getTotal(); 158 | List userVOS = BeanCopyUtils.copyBeanList(list, UserVO.class); 159 | HashMap map = new HashMap<>(); 160 | map.put("total",total); 161 | map.put("user",userVOS); 162 | return Result.success(Code.SUCCESS.getCode(),"",map); 163 | } 164 | 165 | @PostMapping("/searchByUid") 166 | public Result searchByPid(@RequestBody User user){ 167 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 168 | wrapper.eq(User::getUid,user.getUid()); 169 | List list = userService.list(wrapper); 170 | List userVOS = BeanCopyUtils.copyBeanList(list, UserVO.class); 171 | return Result.success(Code.SUCCESS.getCode(),"",userVOS); 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/service/impl/PostServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.service.impl; 2 | 3 | import cn.hutool.core.convert.Convert; 4 | import cn.hutool.core.util.ObjectUtil; 5 | import cn.hutool.core.util.StrUtil; 6 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 7 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 8 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 9 | import com.wbm.forum.common.Code; 10 | import com.wbm.forum.entity.*; 11 | import com.wbm.forum.entity.vo.PostVO; 12 | import com.wbm.forum.exception.MyServiceException; 13 | import com.wbm.forum.mapper.CommentMapper; 14 | import com.wbm.forum.mapper.PostMapper; 15 | import com.wbm.forum.mapper.SubCommentMapper; 16 | import com.wbm.forum.mapper.UserMapper; 17 | import com.wbm.forum.service.PostService; 18 | import com.wbm.forum.utils.BeanCopyUtils; 19 | import com.wbm.forum.utils.RedisUtils; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.springframework.beans.BeanUtils; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.security.core.context.SecurityContextHolder; 24 | import org.springframework.stereotype.Service; 25 | 26 | import java.util.*; 27 | 28 | /** 29 | * @author Ming 30 | * @description 针对表【post】的数据库操作Service实现 31 | * @createDate 2022-11-10 21:47:48 32 | */ 33 | @Service 34 | @Slf4j 35 | public class PostServiceImpl extends ServiceImpl 36 | implements PostService { 37 | 38 | @Autowired 39 | private PostMapper postMapper; 40 | @Autowired 41 | private UserMapper userMapper; 42 | @Autowired 43 | private CommentMapper commentMapper; 44 | @Autowired 45 | private SubCommentMapper subCommentMapper; 46 | @Autowired 47 | private RedisUtils redisUtils; 48 | 49 | @Override 50 | public PostVO getPost(Integer pid) { 51 | Post post = postMapper.selectById(pid); 52 | PostVO postVO = new PostVO(); 53 | BeanUtils.copyProperties(post, postVO); 54 | User user = userMapper.selectById(post.getUid()); 55 | postVO.setAvatar(user.getAvatar()).setNickname(user.getNickname()).setLikes(getLikes(pid)); 56 | Boolean like = isLike(pid); 57 | if (like){ 58 | postVO.setIsLike("1"); 59 | } 60 | return postVO; 61 | } 62 | 63 | @Override 64 | public Map getPostByUid(Integer uid,Integer pageNum,Integer pageSize) { 65 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 66 | queryWrapper.eq(Post::getUid,uid) 67 | .orderBy(true,false,Post::getCreateTime);;; 68 | Page postPage = postMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper); 69 | List postVOS = BeanCopyUtils.copyBeanList(postPage.getRecords(), PostVO.class); 70 | postVOS.forEach(this::setCommentNum); 71 | int total = (int) postPage.getTotal(); 72 | Map map = new HashMap<>(); 73 | map.put("post", postVOS); 74 | map.put("total",total); 75 | return map; 76 | } 77 | 78 | @Override 79 | public Map getAllPost(Integer pageNum, Integer pageSize) { 80 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 81 | queryWrapper.orderBy(true,false,Post::getIsTop) 82 | .orderBy(true,false,Post::getUpdateTime); 83 | Page posts = postMapper.selectPage(new Page<>(pageNum,pageSize),queryWrapper); 84 | List postVOS = BeanCopyUtils.copyBeanList(posts.getRecords(), PostVO.class); 85 | postVOS.forEach(this::setUserInfo); 86 | postVOS.forEach(this::setCommentNum); 87 | int total = (int) posts.getTotal(); 88 | Map map = new HashMap<>(); 89 | map.put("post", postVOS); 90 | map.put("total",total); 91 | return map; 92 | } 93 | 94 | 95 | @Override 96 | public Integer addPost(Post post) { 97 | if (StrUtil.isBlank(post.getTitle())|| StrUtil.isBlank(post.getType())||StrUtil.isBlank(post.getContent())){ 98 | throw new MyServiceException(Code.ERROR.getCode(),"发帖失败"); 99 | } 100 | SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 101 | post.setUid(securityUser.getUser().getUid()).setViews(1L).setLikes(0L); 102 | return postMapper.insert(post); 103 | } 104 | 105 | @Override 106 | public Integer deletePost(Integer pid) { 107 | return postMapper.deleteById(pid); 108 | } 109 | 110 | @Override 111 | public List getPostByTitle(String key) { 112 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 113 | wrapper.like(Post::getTitle,key); 114 | List postList = postMapper.selectList(wrapper); 115 | return BeanCopyUtils.copyBeanList(postList, PostVO.class); 116 | } 117 | 118 | @Override 119 | public List getPostByPid(Post post) { 120 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 121 | wrapper.eq(Post::getPid,post.getPid()); 122 | List list = list(wrapper); 123 | List postVOS = BeanCopyUtils.copyBeanList(list, PostVO.class); 124 | postVOS.forEach(this::setUserInfo); 125 | postVOS.forEach(this::setCommentNum); 126 | return postVOS; 127 | } 128 | 129 | @Override 130 | public Map searchByTime(Date from, Date to, Integer pageNum, Integer pageSize) { 131 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 132 | wrapper.between(Post::getCreateTime, from, to); 133 | Page page = page(new Page<>(pageNum, pageSize), wrapper); 134 | List list = page.getRecords(); 135 | List postVOS = BeanCopyUtils.copyBeanList(list, PostVO.class); 136 | postVOS.forEach(this::setUserInfo); 137 | postVOS.forEach(this::setCommentNum); 138 | int total = (int) page.getTotal(); 139 | HashMap map = new HashMap<>(); 140 | map.put("total",total); 141 | map.put("post",postVOS); 142 | return map; 143 | } 144 | 145 | @Override 146 | public Map selectByType(Post post, Integer pageNum, Integer pageSize) { 147 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 148 | wrapper.eq(Post::getType,post.getType()) 149 | .orderBy(true,false,Post::getIsTop) 150 | .orderBy(true,false,Post::getUpdateTime); 151 | Page page = page(new Page<>(pageNum, pageSize), wrapper); 152 | List list = page.getRecords(); 153 | List postVOS = BeanCopyUtils.copyBeanList(list, PostVO.class); 154 | postVOS.forEach(this::setUserInfo); 155 | postVOS.forEach(this::setCommentNum); 156 | int total = (int) page.getTotal(); 157 | HashMap map = new HashMap<>(); 158 | map.put("total",total); 159 | map.put("post",postVOS); 160 | return map; 161 | } 162 | 163 | public Integer getLikes(Integer pid){ 164 | Set objects = redisUtils.setMembers("postLikes" + pid); 165 | return objects.size(); 166 | } 167 | public Boolean isLike(Integer pid){ 168 | SecurityUser principal = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 169 | Set objects = redisUtils.setMembers("postLikes" + pid); 170 | return objects.contains(principal.getUser().getUid()); 171 | } 172 | 173 | public void setUserInfo(PostVO postVO){ 174 | Object userRedis = redisUtils.hget("userMap", postVO.getUid().toString()); 175 | User user = Convert.convert(User.class, userRedis); 176 | if (ObjectUtil.isNull(userRedis)){ 177 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 178 | queryWrapper.eq(User::getUid, postVO.getUid()); 179 | user = userMapper.selectOne(queryWrapper); 180 | } 181 | postVO.setNickname(user.getNickname()).setAvatar(user.getAvatar()); 182 | } 183 | 184 | public void setCommentNum(PostVO postVO) { 185 | LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper(); 186 | lambdaQueryWrapper.eq(Comment::getPid, postVO.getPid()); 187 | List comments = commentMapper.selectList(lambdaQueryWrapper); 188 | int sub = 0; 189 | for (Comment comment : comments) { 190 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 191 | wrapper.eq(SubComment::getRootId,comment.getCid()); 192 | int size = subCommentMapper.selectList(wrapper).size(); 193 | sub +=size; 194 | } 195 | int size = comments.size(); 196 | postVO.setCommentNum(size+sub); 197 | } 198 | } 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /src/main/java/com/wbm/forum/utils/RedisUtils.java: -------------------------------------------------------------------------------- 1 | package com.wbm.forum.utils; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.connection.RedisKeyCommands; 5 | import org.springframework.data.redis.core.*; 6 | import org.springframework.stereotype.Component; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.*; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * @Author:Ming 13 | * @Date: 2022/11/10 1:19 14 | */ 15 | @Component 16 | public class RedisUtils { 17 | @Autowired 18 | private RedisTemplate redisTemplate; 19 | @Autowired 20 | private StringRedisTemplate stringRedisTemplate; 21 | 22 | public String strGet(String key){ 23 | return stringRedisTemplate.opsForValue().get(key); 24 | } 25 | public void set(String key,String value){ 26 | stringRedisTemplate.opsForValue().set(key, value); 27 | } 28 | public void set(String key,String value,Long expireTime){ 29 | stringRedisTemplate.opsForValue().set(key,value,expireTime,TimeUnit.MINUTES); 30 | } 31 | 32 | public String get(String key){ 33 | return stringRedisTemplate.opsForValue().get(key); 34 | } 35 | 36 | public Boolean hasKey(String key) { 37 | return redisTemplate.hasKey(key); 38 | } 39 | public void delete(String key) { 40 | redisTemplate.delete(key); 41 | } 42 | public void deleteByKeys(String key) { 43 | Set keys = redisTemplate.keys(key+"*"); 44 | redisTemplate.delete(keys); 45 | } 46 | 47 | 48 | 49 | public List getKeys(String pattern) { 50 | return redisTemplate.execute(connection -> { 51 | RedisKeyCommands command = connection.keyCommands(); 52 | ScanOptions scanOpts = ScanOptions.scanOptions().match(pattern).count(100).build(); 53 | Cursor cursor = command.scan(scanOpts); 54 | Set set = new HashSet<>(); 55 | while (cursor.hasNext()) { 56 | byte[] bytes = cursor.next(); 57 | set.add(new String(bytes, StandardCharsets.UTF_8)); 58 | } 59 | return new ArrayList<>(set); 60 | }, true); 61 | } 62 | 63 | /** 64 | * 集合添加 65 | * 66 | * @param key Redis键名 67 | * @param value 值 68 | */ 69 | public void add(String key, Object value) { 70 | SetOperations set = redisTemplate.opsForSet(); 71 | set.add(key, value); 72 | } 73 | 74 | /** 75 | * 集合获取 76 | * 77 | * @param key Redis键名 78 | * @return 集合 79 | */ 80 | public Set setMembers(String key) { 81 | SetOperations set = redisTemplate.opsForSet(); 82 | return set.members(key); 83 | } 84 | 85 | // ============================set============================= 86 | 87 | /** 88 | * 根据key获取Set中的所有值 89 | * 90 | * @param key 键 91 | * @return 92 | */ 93 | public Set sGet(String key) { 94 | try { 95 | return redisTemplate.opsForSet().members(key); 96 | } catch (Exception e) { 97 | e.printStackTrace(); 98 | return null; 99 | } 100 | } 101 | 102 | /** 103 | * 根据value从一个set中查询,是否存在 104 | * 105 | * @param key 键 106 | * @param value 值 107 | * @return true 存在 false不存在 108 | */ 109 | public boolean sHasKey(String key, Object value) { 110 | try { 111 | return redisTemplate.opsForSet().isMember(key, value); 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | return false; 115 | } 116 | } 117 | 118 | /** 119 | * 将数据放入set缓存 120 | * 121 | * @param key 键 122 | * @param values 值 可以是多个 123 | * @return 成功个数 124 | */ 125 | public long sSet(String key, Object... values) { 126 | try { 127 | return redisTemplate.opsForSet().add(key, values); 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | return 0; 131 | } 132 | } 133 | /** 134 | * 获取set缓存的长度 135 | * 136 | * @param key 键 137 | * @return 138 | */ 139 | public long sGetSetSize(String key) { 140 | try { 141 | return redisTemplate.opsForSet().size(key); 142 | } catch (Exception e) { 143 | e.printStackTrace(); 144 | return 0; 145 | } 146 | } 147 | 148 | /** 149 | * 移除值为value的 150 | * 151 | * @param key 键 152 | * @param values 值 可以是多个 153 | * @return 移除的个数 154 | */ 155 | public long setRemove(String key, Object... values) { 156 | try { 157 | Long count = redisTemplate.opsForSet().remove(key, values); 158 | return count; 159 | } catch (Exception e) { 160 | e.printStackTrace(); 161 | return 0; 162 | } 163 | } 164 | /** -------------------hash相关操作------------------------- */ 165 | /** 166 | * HashGet 167 | * 168 | * @param key 键 不能为null 169 | * @param item 项 不能为null 170 | * @return 值 171 | */ 172 | public Object hget(String key, String item) { 173 | return redisTemplate.opsForHash().get(key, item); 174 | } 175 | 176 | /** 177 | * 获取hashKey对应的所有键值 178 | * 179 | * @param key 键 180 | * @return 对应的多个键值 181 | */ 182 | public Map hmget(String key) { 183 | return redisTemplate.opsForHash().entries(key); 184 | } 185 | 186 | 187 | /** 188 | * 获取存储在哈希表中指定字段的值 189 | * 190 | * @param key 191 | * @param field 192 | * @return 193 | */ 194 | public Object hGet(String key, String field) { 195 | return redisTemplate.opsForHash().get(key, field); 196 | } 197 | 198 | /** 199 | * 获取所有给定字段的值 200 | * 201 | * @param key 202 | * @return 203 | */ 204 | public Map hGetAll(String key) { 205 | return redisTemplate.opsForHash().entries(key); 206 | } 207 | 208 | /** 209 | * HashSet 210 | * 211 | * @param key 键 212 | * @param map 对应多个键值 213 | * @return true 成功 false 失败 214 | */ 215 | public boolean hmset(String key, Map map) { 216 | try { 217 | redisTemplate.opsForHash().putAll(key, map); 218 | return true; 219 | } catch (Exception e) { 220 | e.printStackTrace(); 221 | return false; 222 | } 223 | } 224 | 225 | public boolean hmsetInt(String key, Map map) { 226 | try { 227 | redisTemplate.opsForHash().putAll(key, map); 228 | return true; 229 | } catch (Exception e) { 230 | e.printStackTrace(); 231 | return false; 232 | } 233 | } 234 | /** 235 | * 向一张hash表中放入数据,如果不存在将创建 236 | * @param key 键 237 | * @param item 项 238 | * @param value 值 239 | * @return true 成功 false失败 240 | */ 241 | public boolean hset(String key, String item, Object value) { 242 | try { 243 | redisTemplate.opsForHash().put(key, item, value); 244 | return true; 245 | } catch (Exception e) { 246 | e.printStackTrace(); 247 | return false; 248 | } 249 | } 250 | /** 251 | * 获取所有给定字段的值 252 | * 253 | * @param key 254 | * @param fields 255 | * @return 256 | */ 257 | public List hMultiGet(String key, Collection fields) { 258 | return redisTemplate.opsForHash().multiGet(key, fields); 259 | } 260 | 261 | public void hPut(String key, String hashKey, String value) { 262 | redisTemplate.opsForHash().put(key, hashKey, value); 263 | } 264 | 265 | public void hPutAll(String key, Map maps) { 266 | redisTemplate.opsForHash().putAll(key, maps); 267 | } 268 | 269 | /** 270 | * 仅当hashKey不存在时才设置 271 | * 272 | * @param key 273 | * @param hashKey 274 | * @param value 275 | * @return 276 | */ 277 | public Boolean hPutIfAbsent(String key, String hashKey, String value) { 278 | return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value); 279 | } 280 | 281 | /** 282 | * 删除一个或多个哈希表字段 283 | * 284 | * @param key 285 | * @param fields 286 | * @return 287 | */ 288 | public Long hDelete(String key, Object... fields) { 289 | return redisTemplate.opsForHash().delete(key, fields); 290 | } 291 | 292 | /** 293 | * 查看哈希表 key 中,指定的字段是否存在 294 | * 295 | * @param key 296 | * @param field 297 | * @return 298 | */ 299 | public boolean hExists(String key, String field) { 300 | return redisTemplate.opsForHash().hasKey(key, field); 301 | } 302 | 303 | /** 304 | * 为哈希表 key 中的指定字段的整数值加上增量 increment 305 | * 306 | * @param key 307 | * @param field 308 | * @param increment 309 | * @return 310 | */ 311 | public Long hIncrBy(String key, Object field, long increment) { 312 | return redisTemplate.opsForHash().increment(key, field, increment); 313 | } 314 | 315 | /** 316 | * 为哈希表 key 中的指定字段的整数值加上增量 increment 317 | * 318 | * @param key 319 | * @param field 320 | * @param delta 321 | * @return 322 | */ 323 | public Double hIncrByFloat(String key, Object field, double delta) { 324 | return redisTemplate.opsForHash().increment(key, field, delta); 325 | } 326 | 327 | /** 328 | * 获取所有哈希表中的字段 329 | * 330 | * @param key 331 | * @return 332 | */ 333 | public Set hKeys(String key) { 334 | return redisTemplate.opsForHash().keys(key); 335 | } 336 | 337 | /** 338 | * 获取哈希表中字段的数量 339 | * 340 | * @param key 341 | * @return 342 | */ 343 | public Long hSize(String key) { 344 | return redisTemplate.opsForHash().size(key); 345 | } 346 | 347 | /** 348 | * 获取哈希表中所有值 349 | * 350 | * @param key 351 | * @return 352 | */ 353 | public List hValues(String key) { 354 | return redisTemplate.opsForHash().values(key); 355 | } 356 | 357 | } 358 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | --------------------------------------------------------------------------------