├── .gitignore ├── README.md ├── pom.xml ├── sangeng-admin ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sangeng │ │ ├── BlogAdminApplication.java │ │ ├── config │ │ └── SecurityConfig.java │ │ ├── controller │ │ ├── ArticleController.java │ │ ├── CategoryController.java │ │ ├── LinkController.java │ │ ├── LoginController.java │ │ ├── MenuController.java │ │ ├── RoleController.java │ │ ├── TagController.java │ │ ├── UploadController.java │ │ └── UserController.java │ │ └── filter │ │ └── JwtAuthenticationTokenFilter.java │ └── resources │ └── application.yml ├── sangeng-blog ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── sangeng │ │ │ ├── SanGengBlogApplication.java │ │ │ ├── config │ │ │ ├── SecurityConfig.java │ │ │ └── SwaggerConfig.java │ │ │ ├── controller │ │ │ ├── ArticleController.java │ │ │ ├── BlogLoginController.java │ │ │ ├── CategoryController.java │ │ │ ├── CommentController.java │ │ │ ├── LinkController.java │ │ │ ├── UploadController.java │ │ │ └── UserController.java │ │ │ ├── filter │ │ │ └── JwtAuthenticationTokenFilter.java │ │ │ ├── job │ │ │ ├── TestJob.java │ │ │ └── UpdateViewCountJob.java │ │ │ └── runner │ │ │ ├── TestRunner.java │ │ │ └── ViewCountRunner.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── sangeng │ └── OSSTest.java └── sangeng-framework ├── pom.xml └── src └── main ├── java └── com │ └── sangeng │ ├── annotation │ └── SystemLog.java │ ├── aspect │ └── LogAspect.java │ ├── config │ ├── FastJsonRedisSerializer.java │ ├── MbatisPlusConfig.java │ ├── RedisConfig.java │ └── WebConfig.java │ ├── constants │ └── SystemConstants.java │ ├── domain │ ├── ResponseResult.java │ ├── dto │ │ ├── AddArticleDto.java │ │ ├── AddCommentDto.java │ │ ├── AddTagDto.java │ │ ├── ArticleDto.java │ │ ├── ChangeRoleStatusDto.java │ │ ├── EditTagDto.java │ │ └── TagListDto.java │ ├── entity │ │ ├── Article.java │ │ ├── ArticleTag.java │ │ ├── Category.java │ │ ├── Comment.java │ │ ├── Link.java │ │ ├── LoginUser.java │ │ ├── Menu.java │ │ ├── Role.java │ │ ├── RoleMenu.java │ │ ├── Tag.java │ │ ├── User.java │ │ └── UserRole.java │ └── vo │ │ ├── AdminUserInfoVo.java │ │ ├── ArticleDetailVo.java │ │ ├── ArticleListVo.java │ │ ├── ArticleVo.java │ │ ├── BlogUserLoginVo.java │ │ ├── CategoryVo.java │ │ ├── CommentVo.java │ │ ├── ExcelCategoryVo.java │ │ ├── HotArticleVo.java │ │ ├── LinkVo.java │ │ ├── MenuTreeVo.java │ │ ├── MenuVo.java │ │ ├── PageVo.java │ │ ├── RoleMenuTreeSelectVo.java │ │ ├── RoutersVo.java │ │ ├── TagVo.java │ │ ├── UserInfoAndRoleIdsVo.java │ │ ├── UserInfoVo.java │ │ └── UserVo.java │ ├── enums │ └── AppHttpCodeEnum.java │ ├── exception │ └── SystemException.java │ ├── handler │ ├── exception │ │ └── GlobalExceptionHandler.java │ ├── mybatisplus │ │ └── MyMetaObjectHandler.java │ └── security │ │ ├── AccessDeniedHandlerImpl.java │ │ └── AuthenticationEntryPointImpl.java │ ├── mapper │ ├── ArticleMapper.java │ ├── ArticleTagMapper.java │ ├── CategoryMapper.java │ ├── CommentMapper.java │ ├── LinkMapper.java │ ├── MenuMapper.java │ ├── RoleMapper.java │ ├── RoleMenuMapper.java │ ├── TagMapper.java │ ├── UserMapper.java │ └── UserRoleMapper.java │ ├── service │ ├── ArticleService.java │ ├── ArticleTagService.java │ ├── BlogLoginService.java │ ├── CategoryService.java │ ├── CommentService.java │ ├── LinkService.java │ ├── LoginService.java │ ├── MenuService.java │ ├── RoleMenuService.java │ ├── RoleService.java │ ├── TagService.java │ ├── UploadService.java │ ├── UserRoleService.java │ ├── UserService.java │ └── impl │ │ ├── ArticleServiceImpl.java │ │ ├── ArticleTagServiceImpl.java │ │ ├── BlogLoginServiceImpl.java │ │ ├── CategoryServiceImpl.java │ │ ├── CommentServiceImpl.java │ │ ├── LinkServiceImpl.java │ │ ├── MenuServiceImpl.java │ │ ├── OssUploadService.java │ │ ├── PermissionService.java │ │ ├── RoleMenuServiceImpl.java │ │ ├── RoleServiceImpl.java │ │ ├── SystemLoginServiceImpl.java │ │ ├── TagServiceImpl.java │ │ ├── UserDetailsServiceImpl.java │ │ ├── UserRoleServiceImpl.java │ │ └── UserServiceImpl.java │ └── utils │ ├── BeanCopyUtils.java │ ├── JwtUtil.java │ ├── PathUtils.java │ ├── RedisCache.java │ ├── SecurityUtils.java │ ├── SystemConverter.java │ └── WebUtils.java └── resources └── mapper ├── MenuMapper.xml └── RoleMapper.xml /.gitignore: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Build Tools 3 | 4 | .gradle 5 | /build/ 6 | !gradle/wrapper/gradle-wrapper.jar 7 | 8 | target/ 9 | !.mvn/wrapper/maven-wrapper.jar 10 | 11 | ###################################################################### 12 | # IDE 13 | 14 | ### STS ### 15 | .apt_generated 16 | .classpath 17 | .factorypath 18 | .project 19 | .settings 20 | .springBeans 21 | 22 | ### IntelliJ IDEA ### 23 | .idea 24 | *.iws 25 | *.iml 26 | *.ipr 27 | 28 | ### NetBeans ### 29 | nbproject/private/ 30 | build/* 31 | nbbuild/ 32 | dist/ 33 | nbdist/ 34 | .nb-gradle/ 35 | 36 | ###################################################################### 37 | # Others 38 | *.log 39 | *.xml.versionsBackup 40 | *.swp 41 | 42 | !*/build/*.java 43 | !*/build/*.html 44 | !*/build/*.xml 45 | 46 | ### Mac 47 | .DS_Store 48 | */.DS_Store 49 | 50 | ### VS Code ### 51 | *.project 52 | *.factorypath 53 | 54 | ### Compiled class file 55 | *.class 56 | 57 | ### Log file 58 | *.log 59 | 60 | ### BlueJ files 61 | *.ctxt 62 | 63 | ### Mobile Tools for Java (J2ME) 64 | .mtj.tmp/ 65 | 66 | ### Package Files 67 | *.war 68 | *.nar 69 | *.ear 70 | *.zip 71 | *.tar.gz 72 | *.rar 73 | 74 | ### VSCode 75 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SGBlog 2 | SpringBoot博客系统-包含前台后台-适合作为Java学习的第一练手项目 3 | 视频从零到1手把手教你如何写一个完整的项目,相关课程资料全部免费获取。 4 | 5 | 项目介绍: https://www.bilibili.com/video/BV1hq4y1F7zk 6 | 视频讲解:https://www.bilibili.com/video/BV1hq4y1F7zk 7 | 8 | 前端代码:https://github.com/sangengcaotang/SGBlog-front-end 9 | 10 | 如果能帮助到学习路上的你,请给个Star! 11 | 12 | 13 | 14 | 后端工程请使用JDK8!!!! 15 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.sangeng 8 | SGBlog 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | sangeng-framework 13 | sangeng-admin 14 | sangeng-blog 15 | 16 | 17 | 18 | UTF-8 19 | 1.8 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-dependencies 28 | 2.5.0 29 | pom 30 | import 31 | 32 | 33 | 34 | com.alibaba 35 | fastjson 36 | 1.2.33 37 | 38 | 39 | 40 | io.jsonwebtoken 41 | jjwt 42 | 0.9.0 43 | 44 | 45 | 46 | com.baomidou 47 | mybatis-plus-boot-starter 48 | 3.4.3 49 | 50 | 51 | 52 | 53 | com.aliyun.oss 54 | aliyun-sdk-oss 55 | 3.10.2 56 | 57 | 58 | 59 | 60 | com.alibaba 61 | easyexcel 62 | 3.0.5 63 | 64 | 65 | 66 | io.springfox 67 | springfox-swagger2 68 | 2.9.2 69 | 70 | 71 | io.springfox 72 | springfox-swagger-ui 73 | 2.9.2 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-compiler-plugin 83 | 3.1 84 | 85 | ${java.version} 86 | ${java.version} 87 | ${project.build.sourceEncoding} 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /sangeng-admin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | SGBlog 7 | com.sangeng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | sangeng-admin 13 | 14 | 15 | 16 | 17 | com.sangeng 18 | sangeng-framework 19 | 1.0-SNAPSHOT 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/BlogAdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.sangeng; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @Author 三更 B站: https://space.bilibili.com/663528522 9 | */ 10 | @SpringBootApplication 11 | @MapperScan("com.sangeng.mapper") 12 | public class BlogAdminApplication { 13 | public static void main(String[] args) { 14 | SpringApplication.run(BlogAdminApplication.class, args); 15 | } 16 | } -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import com.sangeng.filter.JwtAuthenticationTokenFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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 | 18 | @Configuration 19 | @EnableGlobalMethodSecurity(prePostEnabled = true) 20 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 21 | 22 | @Override 23 | @Bean 24 | public AuthenticationManager authenticationManagerBean() throws Exception { 25 | return super.authenticationManagerBean(); 26 | } 27 | 28 | @Autowired 29 | private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; 30 | @Autowired 31 | AuthenticationEntryPoint authenticationEntryPoint; 32 | @Autowired 33 | AccessDeniedHandler accessDeniedHandler; 34 | 35 | 36 | @Override 37 | protected void configure(HttpSecurity http) throws Exception { 38 | http 39 | //关闭csrf 40 | .csrf().disable() 41 | //不通过Session获取SecurityContext 42 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 43 | .and() 44 | .authorizeRequests() 45 | // 对于登录接口 允许匿名访问 46 | .antMatchers("/user/login").anonymous() 47 | // //注销接口需要认证才能访问 48 | // .antMatchers("/logout").authenticated() 49 | // .antMatchers("/user/userInfo").authenticated() 50 | // .antMatchers("/upload").authenticated() 51 | // 除上面外的所有请求全部不需要认证即可访问 52 | .anyRequest().authenticated(); 53 | 54 | //配置异常处理器 55 | http.exceptionHandling() 56 | .authenticationEntryPoint(authenticationEntryPoint) 57 | .accessDeniedHandler(accessDeniedHandler); 58 | //关闭默认的注销功能 59 | http.logout().disable(); 60 | //把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中 61 | http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 62 | //允许跨域 63 | http.cors(); 64 | } 65 | 66 | @Bean 67 | public PasswordEncoder passwordEncoder(){ 68 | return new BCryptPasswordEncoder(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/ArticleController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.dto.AddArticleDto; 5 | import com.sangeng.domain.dto.ArticleDto; 6 | import com.sangeng.domain.entity.Article; 7 | import com.sangeng.domain.vo.ArticleVo; 8 | import com.sangeng.domain.vo.PageVo; 9 | import com.sangeng.service.ArticleService; 10 | import com.sangeng.service.CategoryService; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | /** 15 | * @Author 三更 B站: https://space.bilibili.com/663528522 16 | */ 17 | @RestController 18 | @RequestMapping("/content/article") 19 | public class ArticleController { 20 | 21 | @Autowired 22 | private ArticleService articleService; 23 | 24 | @PostMapping 25 | public ResponseResult add(@RequestBody AddArticleDto article){ 26 | return articleService.add(article); 27 | } 28 | 29 | 30 | @GetMapping("/list") 31 | public ResponseResult list(Article article, Integer pageNum, Integer pageSize) 32 | { 33 | PageVo pageVo = articleService.selectArticlePage(article,pageNum,pageSize); 34 | return ResponseResult.okResult(pageVo); 35 | } 36 | 37 | @GetMapping(value = "/{id}") 38 | public ResponseResult getInfo(@PathVariable(value = "id")Long id){ 39 | ArticleVo article = articleService.getInfo(id); 40 | return ResponseResult.okResult(article); 41 | } 42 | 43 | @PutMapping 44 | public ResponseResult edit(@RequestBody ArticleDto article){ 45 | articleService.edit(article); 46 | return ResponseResult.okResult(); 47 | } 48 | @DeleteMapping("/{id}") 49 | public ResponseResult delete(@PathVariable Long id){ 50 | articleService.removeById(id); 51 | return ResponseResult.okResult(); 52 | } 53 | } -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/CategoryController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.alibaba.excel.EasyExcel; 4 | import com.alibaba.fastjson.JSON; 5 | import com.sangeng.domain.ResponseResult; 6 | import com.sangeng.domain.entity.Category; 7 | import com.sangeng.domain.vo.CategoryVo; 8 | import com.sangeng.domain.vo.ExcelCategoryVo; 9 | import com.sangeng.domain.vo.PageVo; 10 | import com.sangeng.enums.AppHttpCodeEnum; 11 | import com.sangeng.service.CategoryService; 12 | import com.sangeng.utils.BeanCopyUtils; 13 | import com.sangeng.utils.WebUtils; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.access.prepost.PreAuthorize; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | import java.io.IOException; 21 | import java.io.UnsupportedEncodingException; 22 | import java.util.List; 23 | 24 | /** 25 | * @Author 三更 B站: https://space.bilibili.com/663528522 26 | */ 27 | @RestController 28 | @RequestMapping("/content/category") 29 | public class CategoryController { 30 | @Autowired 31 | private CategoryService categoryService; 32 | 33 | @GetMapping("/listAllCategory") 34 | public ResponseResult listAllCategory(){ 35 | List list = categoryService.listAllCategory(); 36 | return ResponseResult.okResult(list); 37 | } 38 | @PutMapping 39 | public ResponseResult edit(@RequestBody Category category){ 40 | categoryService.updateById(category); 41 | return ResponseResult.okResult(); 42 | } 43 | 44 | @DeleteMapping(value = "/{id}") 45 | public ResponseResult remove(@PathVariable(value = "id")Long id){ 46 | categoryService.removeById(id); 47 | return ResponseResult.okResult(); 48 | } 49 | 50 | @GetMapping(value = "/{id}") 51 | public ResponseResult getInfo(@PathVariable(value = "id")Long id){ 52 | Category category = categoryService.getById(id); 53 | return ResponseResult.okResult(category); 54 | } 55 | @PostMapping 56 | public ResponseResult add(@RequestBody Category category){ 57 | categoryService.save(category); 58 | return ResponseResult.okResult(); 59 | } 60 | /** 61 | * 获取用户列表 62 | */ 63 | @GetMapping("/list") 64 | public ResponseResult list(Category category, Integer pageNum, Integer pageSize) { 65 | PageVo pageVo = categoryService.selectCategoryPage(category,pageNum,pageSize); 66 | return ResponseResult.okResult(pageVo); 67 | } 68 | 69 | 70 | @PreAuthorize("@ps.hasPermission('content:category:export')") 71 | @GetMapping("/export") 72 | public void export(HttpServletResponse response){ 73 | try { 74 | //设置下载文件的请求头 75 | WebUtils.setDownLoadHeader("分类.xlsx",response); 76 | //获取需要导出的数据 77 | List categoryVos = categoryService.list(); 78 | 79 | List excelCategoryVos = BeanCopyUtils.copyBeanList(categoryVos, ExcelCategoryVo.class); 80 | //把数据写入到Excel中 81 | EasyExcel.write(response.getOutputStream(), ExcelCategoryVo.class).autoCloseStream(Boolean.FALSE).sheet("分类导出") 82 | .doWrite(excelCategoryVos); 83 | 84 | } catch (Exception e) { 85 | //如果出现异常也要响应json 86 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR); 87 | WebUtils.renderString(response, JSON.toJSONString(result)); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/LinkController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.Link; 5 | import com.sangeng.domain.vo.PageVo; 6 | import com.sangeng.service.LinkService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | /** 12 | * @Author 三更 B站: https://space.bilibili.com/663528522 13 | */ 14 | @RestController 15 | @RequestMapping("/content/link") 16 | public class LinkController { 17 | @Autowired 18 | private LinkService linkService; 19 | 20 | /** 21 | * 获取友链列表 22 | */ 23 | @GetMapping("/list") 24 | public ResponseResult list(Link link, Integer pageNum, Integer pageSize) 25 | { 26 | PageVo pageVo = linkService.selectLinkPage(link,pageNum,pageSize); 27 | return ResponseResult.okResult(pageVo); 28 | } 29 | 30 | @PostMapping 31 | public ResponseResult add(@RequestBody Link link){ 32 | linkService.save(link); 33 | return ResponseResult.okResult(); 34 | } 35 | 36 | @DeleteMapping("/{id}") 37 | public ResponseResult delete(@PathVariable Long id){ 38 | linkService.removeById(id); 39 | return ResponseResult.okResult(); 40 | } 41 | 42 | @PutMapping 43 | public ResponseResult edit(@RequestBody Link link){ 44 | linkService.updateById(link); 45 | return ResponseResult.okResult(); 46 | } 47 | 48 | @PutMapping("/changeLinkStatus") 49 | public ResponseResult changeLinkStatus(@RequestBody Link link){ 50 | linkService.updateById(link); 51 | return ResponseResult.okResult(); 52 | } 53 | 54 | 55 | 56 | @GetMapping(value = "/{id}") 57 | public ResponseResult getInfo(@PathVariable(value = "id")Long id){ 58 | Link link = linkService.getById(id); 59 | return ResponseResult.okResult(link); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.LoginUser; 5 | import com.sangeng.domain.entity.Menu; 6 | import com.sangeng.domain.entity.User; 7 | import com.sangeng.domain.vo.AdminUserInfoVo; 8 | import com.sangeng.domain.vo.RoutersVo; 9 | import com.sangeng.domain.vo.UserInfoVo; 10 | import com.sangeng.enums.AppHttpCodeEnum; 11 | import com.sangeng.exception.SystemException; 12 | import com.sangeng.service.BlogLoginService; 13 | import com.sangeng.service.LoginService; 14 | import com.sangeng.service.MenuService; 15 | import com.sangeng.service.RoleService; 16 | import com.sangeng.utils.BeanCopyUtils; 17 | import com.sangeng.utils.RedisCache; 18 | import com.sangeng.utils.SecurityUtils; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.util.StringUtils; 21 | import org.springframework.web.bind.annotation.*; 22 | 23 | import java.util.List; 24 | 25 | @RestController 26 | public class LoginController { 27 | @Autowired 28 | private LoginService loginService; 29 | 30 | @Autowired 31 | private MenuService menuService; 32 | 33 | @Autowired 34 | private RoleService roleService; 35 | 36 | 37 | @PostMapping("/user/login") 38 | public ResponseResult login(@RequestBody User user){ 39 | if(!StringUtils.hasText(user.getUserName())){ 40 | //提示 必须要传用户名 41 | throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME); 42 | } 43 | return loginService.login(user); 44 | } 45 | 46 | @PostMapping("/user/logout") 47 | public ResponseResult logout(){ 48 | return loginService.logout(); 49 | } 50 | 51 | 52 | 53 | @GetMapping("getInfo") 54 | public ResponseResult getInfo(){ 55 | //获取当前登录的用户 56 | LoginUser loginUser = SecurityUtils.getLoginUser(); 57 | //根据用户id查询权限信息 58 | List perms = menuService.selectPermsByUserId(loginUser.getUser().getId()); 59 | //根据用户id查询角色信息 60 | List roleKeyList = roleService.selectRoleKeyByUserId(loginUser.getUser().getId()); 61 | 62 | //获取用户信息 63 | User user = loginUser.getUser(); 64 | UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class); 65 | //封装数据返回 66 | 67 | AdminUserInfoVo adminUserInfoVo = new AdminUserInfoVo(perms,roleKeyList,userInfoVo); 68 | return ResponseResult.okResult(adminUserInfoVo); 69 | } 70 | 71 | 72 | @GetMapping("getRouters") 73 | public ResponseResult getRouters(){ 74 | Long userId = SecurityUtils.getUserId(); 75 | //查询menu 结果是tree的形式 76 | List menus = menuService.selectRouterMenuTreeByUserId(userId); 77 | //封装数据返回 78 | return ResponseResult.okResult(new RoutersVo(menus)); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/MenuController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.Menu; 5 | import com.sangeng.domain.vo.MenuTreeVo; 6 | import com.sangeng.domain.vo.MenuVo; 7 | import com.sangeng.domain.vo.RoleMenuTreeSelectVo; 8 | import com.sangeng.service.MenuService; 9 | import com.sangeng.utils.BeanCopyUtils; 10 | import com.sangeng.utils.SecurityUtils; 11 | import com.sangeng.utils.SystemConverter; 12 | import org.springframework.beans.BeanUtils; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | /** 21 | * @Author 三更 B站: https://space.bilibili.com/663528522 22 | */ 23 | @RestController 24 | @RequestMapping("/system/menu") 25 | public class MenuController { 26 | 27 | @Autowired 28 | private MenuService menuService; 29 | 30 | /** 31 | * 获取菜单下拉树列表 32 | */ 33 | @GetMapping("/treeselect") 34 | public ResponseResult treeselect() { 35 | //复用之前的selectMenuList方法。方法需要参数,参数可以用来进行条件查询,而这个方法不需要条件,所以直接new Menu()传入 36 | List menus = menuService.selectMenuList(new Menu()); 37 | List options = SystemConverter.buildMenuSelectTree(menus); 38 | return ResponseResult.okResult(options); 39 | } 40 | 41 | /** 42 | * 加载对应角色菜单列表树 43 | */ 44 | @GetMapping(value = "/roleMenuTreeselect/{roleId}") 45 | public ResponseResult roleMenuTreeSelect(@PathVariable("roleId") Long roleId) { 46 | List menus = menuService.selectMenuList(new Menu()); 47 | List checkedKeys = menuService.selectMenuListByRoleId(roleId); 48 | List menuTreeVos = SystemConverter.buildMenuSelectTree(menus); 49 | RoleMenuTreeSelectVo vo = new RoleMenuTreeSelectVo(checkedKeys,menuTreeVos); 50 | return ResponseResult.okResult(vo); 51 | } 52 | /** 53 | * 获取菜单列表 54 | */ 55 | @GetMapping("/list") 56 | public ResponseResult list(Menu menu) { 57 | List menus = menuService.selectMenuList(menu); 58 | List menuVos = BeanCopyUtils.copyBeanList(menus, MenuVo.class); 59 | return ResponseResult.okResult(menuVos); 60 | } 61 | 62 | @PostMapping 63 | public ResponseResult add(@RequestBody Menu menu) 64 | { 65 | menuService.save(menu); 66 | return ResponseResult.okResult(); 67 | } 68 | 69 | 70 | /** 71 | * 根据菜单编号获取详细信息 72 | */ 73 | @GetMapping(value = "/{menuId}") 74 | public ResponseResult getInfo(@PathVariable Long menuId) 75 | { 76 | return ResponseResult.okResult(menuService.getById(menuId)); 77 | } 78 | 79 | /** 80 | * 修改菜单 81 | */ 82 | @PutMapping 83 | public ResponseResult edit(@RequestBody Menu menu) { 84 | if (menu.getId().equals(menu.getParentId())) { 85 | return ResponseResult.errorResult(500,"修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); 86 | } 87 | menuService.updateById(menu); 88 | return ResponseResult.okResult(); 89 | } 90 | 91 | /** 92 | * 删除菜单 93 | */ 94 | @DeleteMapping("/{menuId}") 95 | public ResponseResult remove(@PathVariable("menuId") Long menuId) { 96 | if (menuService.hasChild(menuId)) { 97 | return ResponseResult.errorResult(500,"存在子菜单不允许删除"); 98 | } 99 | menuService.removeById(menuId); 100 | return ResponseResult.okResult(); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.dto.ChangeRoleStatusDto; 5 | import com.sangeng.domain.entity.Role; 6 | import com.sangeng.service.RoleService; 7 | import com.sangeng.utils.BeanCopyUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @Author 三更 B站: https://space.bilibili.com/663528522 15 | */ 16 | @RestController 17 | @RequestMapping("/system/role") 18 | public class RoleController { 19 | 20 | @Autowired 21 | private RoleService roleService; 22 | 23 | 24 | @GetMapping("/listAllRole") 25 | public ResponseResult listAllRole(){ 26 | List roles = roleService.selectRoleAll(); 27 | return ResponseResult.okResult(roles); 28 | } 29 | 30 | /** 31 | * 根据角色编号获取详细信息 32 | */ 33 | @GetMapping(value = "/{roleId}") 34 | public ResponseResult getInfo(@PathVariable Long roleId) 35 | { 36 | Role role = roleService.getById(roleId); 37 | return ResponseResult.okResult(role); 38 | } 39 | 40 | /** 41 | * 修改保存角色 42 | */ 43 | @PutMapping 44 | public ResponseResult edit(@RequestBody Role role) 45 | { 46 | roleService.updateRole(role); 47 | return ResponseResult.okResult(); 48 | } 49 | 50 | /** 51 | * 删除角色 52 | * @param id 53 | */ 54 | @DeleteMapping("/{id}") 55 | public ResponseResult remove(@PathVariable(name = "id") Long id) { 56 | roleService.removeById(id); 57 | return ResponseResult.okResult(); 58 | } 59 | 60 | 61 | /** 62 | * 新增角色 63 | */ 64 | @PostMapping 65 | public ResponseResult add( @RequestBody Role role) 66 | { 67 | roleService.insertRole(role); 68 | return ResponseResult.okResult(); 69 | 70 | } 71 | @GetMapping("/list") 72 | public ResponseResult list(Role role, Integer pageNum, Integer pageSize) { 73 | return roleService.selectRolePage(role,pageNum,pageSize); 74 | } 75 | 76 | @PutMapping("/changeStatus") 77 | public ResponseResult changeStatus(@RequestBody ChangeRoleStatusDto roleStatusDto){ 78 | Role role = new Role(); 79 | role.setId(roleStatusDto.getRoleId()); 80 | role.setStatus(roleStatusDto.getStatus()); 81 | return ResponseResult.okResult(roleService.updateById(role)); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/TagController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.dto.AddTagDto; 5 | import com.sangeng.domain.dto.EditTagDto; 6 | import com.sangeng.domain.dto.TagListDto; 7 | import com.sangeng.domain.entity.Tag; 8 | import com.sangeng.domain.vo.PageVo; 9 | import com.sangeng.domain.vo.TagVo; 10 | import com.sangeng.service.TagService; 11 | import com.sangeng.utils.BeanCopyUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.access.prepost.PostAuthorize; 14 | import org.springframework.security.access.prepost.PreAuthorize; 15 | import org.springframework.web.bind.annotation.*; 16 | 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequestMapping("/content/tag") 21 | public class TagController { 22 | @Autowired 23 | private TagService tagService; 24 | 25 | @GetMapping("/list") 26 | public ResponseResult list(Integer pageNum, Integer pageSize, TagListDto tagListDto){ 27 | return tagService.pageTagList(pageNum,pageSize,tagListDto); 28 | } 29 | 30 | @PostMapping 31 | public ResponseResult add(@RequestBody AddTagDto tagDto){ 32 | Tag tag = BeanCopyUtils.copyBean(tagDto, Tag.class); 33 | tagService.save(tag); 34 | return ResponseResult.okResult(); 35 | } 36 | 37 | @DeleteMapping("/{id}") 38 | public ResponseResult delete(@PathVariable Long id){ 39 | tagService.removeById(id); 40 | return ResponseResult.okResult(); 41 | } 42 | 43 | @PutMapping 44 | public ResponseResult edit(@RequestBody EditTagDto tagDto){ 45 | Tag tag = BeanCopyUtils.copyBean(tagDto,Tag.class); 46 | tagService.updateById(tag); 47 | return ResponseResult.okResult(); 48 | } 49 | 50 | 51 | @GetMapping(value = "/{id}") 52 | public ResponseResult getInfo(@PathVariable(value = "id")Long id){ 53 | Tag tag = tagService.getById(id); 54 | return ResponseResult.okResult(tag); 55 | } 56 | 57 | 58 | @GetMapping("/listAllTag") 59 | public ResponseResult listAllTag(){ 60 | List list = tagService.listAllTag(); 61 | return ResponseResult.okResult(list); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/UploadController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.enums.AppHttpCodeEnum; 5 | import com.sangeng.service.UploadService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * @Author 三更 B站: https://space.bilibili.com/663528522 16 | */ 17 | @RestController 18 | public class UploadController { 19 | 20 | @Autowired 21 | private UploadService uploadService; 22 | 23 | @PostMapping("/upload") 24 | public ResponseResult uploadImg(@RequestParam("img") MultipartFile multipartFile) { 25 | try { 26 | return uploadService.uploadImg(multipartFile); 27 | } catch (IOException e) { 28 | e.printStackTrace(); 29 | throw new RuntimeException("文件上传上传失败"); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.Role; 5 | import com.sangeng.domain.entity.User; 6 | import com.sangeng.domain.vo.UserInfoAndRoleIdsVo; 7 | import com.sangeng.enums.AppHttpCodeEnum; 8 | import com.sangeng.exception.SystemException; 9 | import com.sangeng.service.RoleService; 10 | import com.sangeng.service.UserService; 11 | import com.sangeng.utils.SecurityUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.util.StringUtils; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.Arrays; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | /** 22 | * @Author 三更 B站: https://space.bilibili.com/663528522 23 | */ 24 | @RestController 25 | @RequestMapping("/system/user") 26 | public class UserController { 27 | 28 | @Autowired 29 | private UserService userService; 30 | @Autowired 31 | private RoleService roleService; 32 | /** 33 | * 获取用户列表 34 | */ 35 | @GetMapping("/list") 36 | public ResponseResult list(User user, Integer pageNum, Integer pageSize) { 37 | return userService.selectUserPage(user,pageNum,pageSize); 38 | } 39 | 40 | /** 41 | * 新增用户 42 | */ 43 | @PostMapping 44 | public ResponseResult add(@RequestBody User user) 45 | { 46 | if(!StringUtils.hasText(user.getUserName())){ 47 | throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME); 48 | } 49 | if (!userService.checkUserNameUnique(user.getUserName())){ 50 | throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST); 51 | } 52 | if (!userService.checkPhoneUnique(user)){ 53 | throw new SystemException(AppHttpCodeEnum.PHONENUMBER_EXIST); 54 | } 55 | if (!userService.checkEmailUnique(user)){ 56 | throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST); 57 | } 58 | return userService.addUser(user); 59 | } 60 | 61 | /** 62 | * 根据用户编号获取详细信息 63 | */ 64 | @GetMapping(value = { "/{userId}" }) 65 | public ResponseResult getUserInfoAndRoleIds(@PathVariable(value = "userId") Long userId) 66 | { 67 | List roles = roleService.selectRoleAll(); 68 | User user = userService.getById(userId); 69 | //当前用户所具有的角色id列表 70 | List roleIds = roleService.selectRoleIdByUserId(userId); 71 | 72 | UserInfoAndRoleIdsVo vo = new UserInfoAndRoleIdsVo(user,roles,roleIds); 73 | return ResponseResult.okResult(vo); 74 | } 75 | 76 | /** 77 | * 修改用户 78 | */ 79 | @PutMapping 80 | public ResponseResult edit(@RequestBody User user) { 81 | userService.updateUser(user); 82 | return ResponseResult.okResult(); 83 | } 84 | 85 | /** 86 | * 删除用户 87 | */ 88 | @DeleteMapping("/{userIds}") 89 | public ResponseResult remove(@PathVariable List userIds) { 90 | if(userIds.contains(SecurityUtils.getUserId())){ 91 | return ResponseResult.errorResult(500,"不能删除当前你正在使用的用户"); 92 | } 93 | userService.removeByIds(userIds); 94 | return ResponseResult.okResult(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/java/com/sangeng/filter/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.filter; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.LoginUser; 6 | import com.sangeng.enums.AppHttpCodeEnum; 7 | import com.sangeng.utils.JwtUtil; 8 | import com.sangeng.utils.RedisCache; 9 | import com.sangeng.utils.WebUtils; 10 | import io.jsonwebtoken.Claims; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.context.SecurityContextHolder; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.util.StringUtils; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import javax.servlet.FilterChain; 19 | import javax.servlet.ServletException; 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | import java.io.IOException; 23 | import java.util.Objects; 24 | 25 | @Component 26 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 27 | 28 | @Autowired 29 | private RedisCache redisCache; 30 | 31 | @Override 32 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 33 | //获取请求头中的token 34 | String token = request.getHeader("token"); 35 | if(!StringUtils.hasText(token)){ 36 | //说明该接口不需要登录 直接放行 37 | filterChain.doFilter(request, response); 38 | return; 39 | } 40 | //解析获取userid 41 | Claims claims = null; 42 | try { 43 | claims = JwtUtil.parseJWT(token); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | //token超时 token非法 47 | //响应告诉前端需要重新登录 48 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); 49 | WebUtils.renderString(response, JSON.toJSONString(result)); 50 | return; 51 | } 52 | String userId = claims.getSubject(); 53 | //从redis中获取用户信息 54 | LoginUser loginUser = redisCache.getCacheObject("login:" + userId); 55 | //如果获取不到 56 | if(Objects.isNull(loginUser)){ 57 | //说明登录过期 提示重新登录 58 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); 59 | WebUtils.renderString(response, JSON.toJSONString(result)); 60 | return; 61 | } 62 | //存入SecurityContextHolder 63 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,null); 64 | SecurityContextHolder.getContext().setAuthentication(authenticationToken); 65 | 66 | filterChain.doFilter(request, response); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /sangeng-admin/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8989 3 | spring: 4 | datasource: 5 | url: jdbc:mysql://localhost:3306/sg_blog?characterEncoding=utf-8&serverTimezone=UTC 6 | username: root 7 | password: root 8 | driver-class-name: com.mysql.cj.jdbc.Driver 9 | servlet: 10 | multipart: 11 | max-file-size: 2MB 12 | max-request-size: 5MB 13 | 14 | mybatis-plus: 15 | configuration: 16 | # 日志 17 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 18 | global-config: 19 | db-config: 20 | logic-delete-field: delFlag 21 | logic-delete-value: 1 22 | logic-not-delete-value: 0 23 | id-type: auto 24 | -------------------------------------------------------------------------------- /sangeng-blog/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | SGBlog 7 | com.sangeng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | sangeng-blog 13 | 14 | 15 | 16 | com.sangeng 17 | sangeng-framework 18 | 1.0-SNAPSHOT 19 | 20 | 21 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/SanGengBlogApplication.java: -------------------------------------------------------------------------------- 1 | package com.sangeng; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 8 | 9 | @SpringBootApplication 10 | @MapperScan("com.sangeng.mapper") 11 | @EnableScheduling 12 | @EnableSwagger2 13 | public class SanGengBlogApplication { 14 | public static void main(String[] args) { 15 | SpringApplication.run(SanGengBlogApplication.class,args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import com.sangeng.filter.JwtAuthenticationTokenFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 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.WebSecurityConfigurerAdapter; 10 | import org.springframework.security.config.http.SessionCreationPolicy; 11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.security.web.AuthenticationEntryPoint; 14 | import org.springframework.security.web.access.AccessDeniedHandler; 15 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 16 | 17 | @Configuration 18 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 19 | 20 | @Override 21 | @Bean 22 | public AuthenticationManager authenticationManagerBean() throws Exception { 23 | return super.authenticationManagerBean(); 24 | } 25 | 26 | @Autowired 27 | private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; 28 | @Autowired 29 | AuthenticationEntryPoint authenticationEntryPoint; 30 | @Autowired 31 | AccessDeniedHandler accessDeniedHandler; 32 | 33 | 34 | @Override 35 | protected void configure(HttpSecurity http) throws Exception { 36 | http 37 | //关闭csrf 38 | .csrf().disable() 39 | //不通过Session获取SecurityContext 40 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 41 | .and() 42 | .authorizeRequests() 43 | // 对于登录接口 允许匿名访问 44 | .antMatchers("/login").anonymous() 45 | //注销接口需要认证才能访问 46 | .antMatchers("/logout").authenticated() 47 | .antMatchers("/user/userInfo").authenticated() 48 | // .antMatchers("/upload").authenticated() 49 | // 除上面外的所有请求全部不需要认证即可访问 50 | .anyRequest().permitAll(); 51 | 52 | //配置异常处理器 53 | http.exceptionHandling() 54 | .authenticationEntryPoint(authenticationEntryPoint) 55 | .accessDeniedHandler(accessDeniedHandler); 56 | //关闭默认的注销功能 57 | http.logout().disable(); 58 | //把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中 59 | http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 60 | //允许跨域 61 | http.cors(); 62 | } 63 | 64 | @Bean 65 | public PasswordEncoder passwordEncoder(){ 66 | return new BCryptPasswordEncoder(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.RequestHandlerSelectors; 7 | import springfox.documentation.service.ApiInfo; 8 | import springfox.documentation.service.Contact; 9 | import springfox.documentation.spi.DocumentationType; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | 12 | @Configuration 13 | public class SwaggerConfig { 14 | @Bean 15 | public Docket customDocket() { 16 | return new Docket(DocumentationType.SWAGGER_2) 17 | .apiInfo(apiInfo()) 18 | .select() 19 | .apis(RequestHandlerSelectors.basePackage("com.sangeng.controller")) 20 | .build(); 21 | } 22 | 23 | private ApiInfo apiInfo() { 24 | Contact contact = new Contact("三更草堂", "http://www.sangeng.com", "my@my.com"); 25 | return new ApiInfoBuilder() 26 | .title("文档标题1") 27 | .description("文档描述2") 28 | .contact(contact) // 联系方式 29 | .version("1.1.1") // 版本 30 | .build(); 31 | } 32 | } -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/ArticleController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.sangeng.domain.ResponseResult; 6 | import com.sangeng.domain.entity.Article; 7 | import com.sangeng.service.ArticleService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import java.util.List; 12 | 13 | @RestController 14 | @RequestMapping("/article") 15 | public class ArticleController { 16 | 17 | @Autowired 18 | private ArticleService articleService; 19 | 20 | @GetMapping("/hotArticleList") 21 | public ResponseResult hotArticleList(){ 22 | 23 | ResponseResult result = articleService.hotArticleList(); 24 | return result; 25 | } 26 | 27 | @GetMapping("/articleList") 28 | public ResponseResult articleList(Integer pageNum,Integer pageSize,Long categoryId){ 29 | return articleService.articleList(pageNum,pageSize,categoryId); 30 | } 31 | 32 | @PutMapping("/updateViewCount/{id}") 33 | public ResponseResult updateViewCount(@PathVariable("id") Long id){ 34 | return articleService.updateViewCount(id); 35 | } 36 | 37 | @GetMapping("/{id}") 38 | public ResponseResult getArticleDetail(@PathVariable("id") Long id){ 39 | return articleService.getArticleDetail(id); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/BlogLoginController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.User; 5 | import com.sangeng.enums.AppHttpCodeEnum; 6 | import com.sangeng.exception.SystemException; 7 | import com.sangeng.service.BlogLoginService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.util.StringUtils; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @RestController 15 | public class BlogLoginController { 16 | @Autowired 17 | private BlogLoginService blogLoginService; 18 | 19 | @PostMapping("/login") 20 | public ResponseResult login(@RequestBody User user){ 21 | if(!StringUtils.hasText(user.getUserName())){ 22 | //提示 必须要传用户名 23 | throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME); 24 | } 25 | return blogLoginService.login(user); 26 | } 27 | @PostMapping("/logout") 28 | public ResponseResult logout(){ 29 | return blogLoginService.logout(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/CategoryController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.service.CategoryService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | @RequestMapping("/category") 13 | public class CategoryController { 14 | 15 | @Autowired 16 | private CategoryService categoryService; 17 | 18 | @GetMapping("/getCategoryList") 19 | public ResponseResult getCategoryList(){ 20 | return categoryService.getCategoryList(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/CommentController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.constants.SystemConstants; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.dto.AddCommentDto; 6 | import com.sangeng.domain.entity.Comment; 7 | import com.sangeng.service.CommentService; 8 | import com.sangeng.utils.BeanCopyUtils; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiImplicitParam; 11 | import io.swagger.annotations.ApiImplicitParams; 12 | import io.swagger.annotations.ApiOperation; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | @RestController 17 | @RequestMapping("/comment") 18 | @Api(tags = "评论",description = "评论相关接口") 19 | public class CommentController { 20 | 21 | @Autowired 22 | private CommentService commentService; 23 | 24 | @GetMapping("/commentList") 25 | public ResponseResult commentList(Long articleId,Integer pageNum,Integer pageSize){ 26 | return commentService.commentList(SystemConstants.ARTICLE_COMMENT,articleId,pageNum,pageSize); 27 | } 28 | 29 | @PostMapping 30 | public ResponseResult addComment(@RequestBody AddCommentDto addCommentDto){ 31 | Comment comment = BeanCopyUtils.copyBean(addCommentDto, Comment.class); 32 | return commentService.addComment(comment); 33 | } 34 | 35 | 36 | @GetMapping("/linkCommentList") 37 | @ApiOperation(value = "友链评论列表",notes = "获取一页友链评论") 38 | @ApiImplicitParams({ 39 | @ApiImplicitParam(name = "pageNum",value = "页号"), 40 | @ApiImplicitParam(name = "pageSize",value = "每页大小") 41 | } 42 | ) 43 | public ResponseResult linkCommentList(Integer pageNum,Integer pageSize){ 44 | return commentService.commentList(SystemConstants.LINK_COMMENT,null,pageNum,pageSize); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/LinkController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.service.LinkService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | @RequestMapping("/link") 12 | public class LinkController { 13 | 14 | @Autowired 15 | private LinkService linkService; 16 | 17 | @GetMapping("/getAllLink") 18 | public ResponseResult getAllLink(){ 19 | return linkService.getAllLink(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/UploadController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.service.UploadService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import java.io.IOException; 13 | 14 | @RestController 15 | public class UploadController { 16 | @Autowired 17 | private UploadService uploadService; 18 | 19 | @PostMapping("/upload") 20 | public ResponseResult uploadImg(MultipartFile img) throws IOException { 21 | return uploadService.uploadImg(img); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.controller; 2 | 3 | import com.sangeng.annotation.SystemLog; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.User; 6 | import com.sangeng.service.UserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | @RestController 11 | @RequestMapping("/user") 12 | public class UserController { 13 | 14 | @Autowired 15 | private UserService userService; 16 | 17 | @GetMapping("/userInfo") 18 | public ResponseResult userInfo(){ 19 | return userService.userInfo(); 20 | } 21 | 22 | @PutMapping("/userInfo") 23 | @SystemLog(businessName = "更新用户信息") 24 | public ResponseResult updateUserInfo(@RequestBody User user){ 25 | return userService.updateUserInfo(user); 26 | } 27 | 28 | @PostMapping("/register") 29 | public ResponseResult register(@RequestBody User user){ 30 | return userService.register(user); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/filter/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.filter; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.LoginUser; 6 | import com.sangeng.enums.AppHttpCodeEnum; 7 | import com.sangeng.utils.JwtUtil; 8 | import com.sangeng.utils.RedisCache; 9 | import com.sangeng.utils.WebUtils; 10 | import io.jsonwebtoken.Claims; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.context.SecurityContextHolder; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.util.StringUtils; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import javax.servlet.FilterChain; 19 | import javax.servlet.ServletException; 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | import java.io.IOException; 23 | import java.util.Objects; 24 | 25 | @Component 26 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 27 | 28 | @Autowired 29 | private RedisCache redisCache; 30 | 31 | @Override 32 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 33 | //获取请求头中的token 34 | String token = request.getHeader("token"); 35 | if(!StringUtils.hasText(token)){ 36 | //说明该接口不需要登录 直接放行 37 | filterChain.doFilter(request, response); 38 | return; 39 | } 40 | //解析获取userid 41 | Claims claims = null; 42 | try { 43 | claims = JwtUtil.parseJWT(token); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | //token超时 token非法 47 | //响应告诉前端需要重新登录 48 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); 49 | WebUtils.renderString(response, JSON.toJSONString(result)); 50 | return; 51 | } 52 | String userId = claims.getSubject(); 53 | //从redis中获取用户信息 54 | LoginUser loginUser = redisCache.getCacheObject("bloglogin:" + userId); 55 | //如果获取不到 56 | if(Objects.isNull(loginUser)){ 57 | //说明登录过期 提示重新登录 58 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); 59 | WebUtils.renderString(response, JSON.toJSONString(result)); 60 | return; 61 | } 62 | //存入SecurityContextHolder 63 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,null); 64 | SecurityContextHolder.getContext().setAuthentication(authenticationToken); 65 | 66 | filterChain.doFilter(request, response); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/job/TestJob.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.job; 2 | 3 | 4 | import org.springframework.scheduling.annotation.Scheduled; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class TestJob { 9 | 10 | @Scheduled(cron = "0/5 * * * * ?") 11 | public void testJob(){ 12 | //要执行的代码 13 | System.out.println("定时任务执行了"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/job/UpdateViewCountJob.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.job; 2 | 3 | import com.sangeng.domain.entity.Article; 4 | import com.sangeng.service.ArticleService; 5 | import com.sangeng.utils.RedisCache; 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 | @Component 15 | public class UpdateViewCountJob { 16 | 17 | @Autowired 18 | private RedisCache redisCache; 19 | 20 | @Autowired 21 | private ArticleService articleService; 22 | 23 | @Scheduled(cron = "0/55 * * * * ?") 24 | public void updateViewCount(){ 25 | //获取redis中的浏览量 26 | Map viewCountMap = redisCache.getCacheMap("article:viewCount"); 27 | 28 | List
articles = viewCountMap.entrySet() 29 | .stream() 30 | .map(entry -> new Article(Long.valueOf(entry.getKey()), entry.getValue().longValue())) 31 | .collect(Collectors.toList()); 32 | //更新到数据库中 33 | articleService.updateBatchById(articles); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/runner/TestRunner.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.runner; 2 | 3 | import org.springframework.boot.CommandLineRunner; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class TestRunner implements CommandLineRunner { 8 | @Override 9 | public void run(String... args) throws Exception { 10 | System.out.println("程序初始化"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/java/com/sangeng/runner/ViewCountRunner.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.runner; 2 | 3 | import com.sangeng.domain.entity.Article; 4 | import com.sangeng.mapper.ArticleMapper; 5 | import com.sangeng.utils.RedisCache; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.function.Function; 13 | import java.util.stream.Collectors; 14 | 15 | @Component 16 | public class ViewCountRunner implements CommandLineRunner { 17 | 18 | @Autowired 19 | private ArticleMapper articleMapper; 20 | 21 | @Autowired 22 | private RedisCache redisCache; 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | //查询博客信息 id viewCount 27 | List
articles = articleMapper.selectList(null); 28 | Map viewCountMap = articles.stream() 29 | .collect(Collectors.toMap(article -> article.getId().toString(), article -> { 30 | return article.getViewCount().intValue();// 31 | })); 32 | //存储到redis中 33 | redisCache.setCacheMap("article:viewCount",viewCountMap); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sangeng-blog/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7777 3 | spring: 4 | datasource: 5 | url: jdbc:mysql://localhost:3306/sg_blog?characterEncoding=utf-8&serverTimezone=Asia/Shanghai 6 | username: root 7 | password: root 8 | driver-class-name: com.mysql.cj.jdbc.Driver 9 | servlet: 10 | multipart: 11 | max-file-size: 2MB 12 | max-request-size: 5MB 13 | mybatis-plus: 14 | configuration: 15 | # 日志 16 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 17 | global-config: 18 | db-config: 19 | logic-delete-field: delFlag 20 | logic-delete-value: 1 21 | logic-not-delete-value: 0 22 | id-type: auto 23 | 24 | 25 | oss: 26 | accessKey: daddasd 27 | secretKey: weqeqwe 28 | bucket: sg-blog -------------------------------------------------------------------------------- /sangeng-blog/src/test/java/com/sangeng/OSSTest.java: -------------------------------------------------------------------------------- 1 | package com.sangeng; 2 | 3 | import com.google.gson.Gson; 4 | import com.qiniu.common.QiniuException; 5 | import com.qiniu.http.Response; 6 | import com.qiniu.storage.Configuration; 7 | import com.qiniu.storage.Region; 8 | import com.qiniu.storage.UploadManager; 9 | import com.qiniu.storage.model.DefaultPutRet; 10 | import com.qiniu.util.Auth; 11 | import org.junit.jupiter.api.Test; 12 | import org.springframework.boot.context.properties.ConfigurationProperties; 13 | import org.springframework.boot.test.context.SpringBootTest; 14 | 15 | import java.io.*; 16 | 17 | @SpringBootTest(classes = SanGengBlogApplication.class) 18 | @ConfigurationProperties(prefix = "oss") 19 | public class OSSTest { 20 | 21 | private String accessKey; 22 | private String secretKey; 23 | private String bucket; 24 | 25 | public void setAccessKey(String accessKey) { 26 | this.accessKey = accessKey; 27 | } 28 | 29 | public void setSecretKey(String secretKey) { 30 | this.secretKey = secretKey; 31 | } 32 | 33 | public void setBucket(String bucket) { 34 | this.bucket = bucket; 35 | } 36 | 37 | @Test 38 | public void testOss(){ 39 | //构造一个带指定 Region 对象的配置类 40 | Configuration cfg = new Configuration(Region.autoRegion()); 41 | //...其他参数参考类注释 42 | 43 | UploadManager uploadManager = new UploadManager(cfg); 44 | //...生成上传凭证,然后准备上传 45 | // String accessKey = "your access key"; 46 | // String secretKey = "your secret key"; 47 | // String bucket = "sg-blog"; 48 | 49 | //默认不指定key的情况下,以文件内容的hash值作为文件名 50 | String key = "2022/sg.png"; 51 | 52 | try { 53 | // byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8"); 54 | // ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes); 55 | 56 | 57 | InputStream inputStream = new FileInputStream("C:\\Users\\root\\Desktop\\Snipaste_2022-02-28_22-48-37.png"); 58 | Auth auth = Auth.create(accessKey, secretKey); 59 | String upToken = auth.uploadToken(bucket); 60 | 61 | try { 62 | Response response = uploadManager.put(inputStream,key,upToken,null, null); 63 | //解析上传成功的结果 64 | DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class); 65 | System.out.println(putRet.key); 66 | System.out.println(putRet.hash); 67 | } catch (QiniuException ex) { 68 | Response r = ex.response; 69 | System.err.println(r.toString()); 70 | try { 71 | System.err.println(r.bodyString()); 72 | } catch (QiniuException ex2) { 73 | //ignore 74 | } 75 | } 76 | } catch (Exception ex) { 77 | //ignore 78 | } 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /sangeng-framework/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | SGBlog 7 | com.sangeng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | sangeng-framework 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | 21 | org.projectlombok 22 | lombok 23 | true 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-test 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-security 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-data-redis 39 | 40 | 41 | 42 | com.alibaba 43 | fastjson 44 | 45 | 46 | 47 | io.jsonwebtoken 48 | jjwt 49 | 50 | 51 | 52 | com.baomidou 53 | mybatis-plus-boot-starter 54 | 55 | 56 | 57 | mysql 58 | mysql-connector-java 59 | 60 | 61 | 62 | 63 | com.aliyun.oss 64 | aliyun-sdk-oss 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-starter-aop 71 | 72 | 73 | 74 | com.alibaba 75 | easyexcel 76 | 77 | 78 | io.springfox 79 | springfox-swagger2 80 | 81 | 82 | io.springfox 83 | springfox-swagger-ui 84 | 85 | 86 | 87 | com.qiniu 88 | qiniu-java-sdk 89 | [7.7.0, 7.7.99] 90 | 91 | 92 | 93 | io.springfox 94 | springfox-swagger2 95 | 96 | 97 | io.springfox 98 | springfox-swagger-ui 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/annotation/SystemLog.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.annotation; 2 | 3 | 4 | import org.aspectj.lang.annotation.Around; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface SystemLog { 14 | String businessName(); 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/aspect/LogAspect.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.aspect; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sangeng.annotation.SystemLog; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.aspectj.lang.ProceedingJoinPoint; 7 | import org.aspectj.lang.annotation.Around; 8 | import org.aspectj.lang.annotation.Aspect; 9 | import org.aspectj.lang.annotation.Pointcut; 10 | import org.aspectj.lang.reflect.MethodSignature; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.context.request.RequestAttributes; 13 | import org.springframework.web.context.request.RequestContextHolder; 14 | import org.springframework.web.context.request.ServletRequestAttributes; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | 18 | @Component 19 | @Aspect 20 | @Slf4j 21 | public class LogAspect { 22 | 23 | @Pointcut("@annotation(com.sangeng.annotation.SystemLog)") 24 | public void pt(){ 25 | 26 | } 27 | 28 | @Around("pt()") 29 | public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable { 30 | 31 | Object ret; 32 | try { 33 | handleBefore(joinPoint); 34 | ret = joinPoint.proceed(); 35 | handleAfter(ret); 36 | } finally { 37 | // 结束后换行 38 | log.info("=======End=======" + System.lineSeparator()); 39 | } 40 | 41 | return ret; 42 | } 43 | 44 | private void handleAfter(Object ret) { 45 | // 打印出参 46 | log.info("Response : {}", JSON.toJSONString(ret)); 47 | } 48 | 49 | private void handleBefore(ProceedingJoinPoint joinPoint) { 50 | 51 | ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 52 | HttpServletRequest request = requestAttributes.getRequest(); 53 | //获取被增强方法上的注解对象 54 | SystemLog systemLog = getSystemLog(joinPoint); 55 | log.info("=======Start======="); 56 | // 打印请求 URL 57 | log.info("URL : {}",request.getRequestURL()); 58 | // 打印描述信息 59 | log.info("BusinessName : {}",systemLog.businessName()); 60 | // 打印 Http method 61 | log.info("HTTP Method : {}",request.getMethod()); 62 | // 打印调用 controller 的全路径以及执行方法 63 | log.info("Class Method : {}.{}",joinPoint.getSignature().getDeclaringTypeName(),((MethodSignature) joinPoint.getSignature()).getName()); 64 | // 打印请求的 IP 65 | log.info("IP : {}",request.getRemoteHost()); 66 | // 打印请求入参 67 | log.info("Request Args : {}", JSON.toJSONString(joinPoint.getArgs()) ); 68 | } 69 | 70 | private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) { 71 | MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); 72 | SystemLog systemLog = methodSignature.getMethod().getAnnotation(SystemLog.class); 73 | return systemLog; 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/config/FastJsonRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import com.fasterxml.jackson.databind.JavaType; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.type.TypeFactory; 8 | import org.springframework.data.redis.serializer.RedisSerializer; 9 | import org.springframework.data.redis.serializer.SerializationException; 10 | import com.alibaba.fastjson.parser.ParserConfig; 11 | import org.springframework.util.Assert; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * Redis使用FastJson序列化 16 | * 17 | * @author sg 18 | */ 19 | public class FastJsonRedisSerializer implements RedisSerializer 20 | { 21 | 22 | public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 23 | 24 | private Class clazz; 25 | 26 | static 27 | { 28 | ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 29 | } 30 | 31 | public FastJsonRedisSerializer(Class clazz) 32 | { 33 | super(); 34 | this.clazz = clazz; 35 | } 36 | 37 | @Override 38 | public byte[] serialize(T t) throws SerializationException 39 | { 40 | if (t == null) 41 | { 42 | return new byte[0]; 43 | } 44 | return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); 45 | } 46 | 47 | @Override 48 | public T deserialize(byte[] bytes) throws SerializationException 49 | { 50 | if (bytes == null || bytes.length <= 0) 51 | { 52 | return null; 53 | } 54 | String str = new String(bytes, DEFAULT_CHARSET); 55 | 56 | return JSON.parseObject(str, clazz); 57 | } 58 | 59 | 60 | protected JavaType getJavaType(Class clazz) 61 | { 62 | return TypeFactory.defaultInstance().constructType(clazz); 63 | } 64 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/config/MbatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @Author 三更 B站: https://space.bilibili.com/663528522 10 | */ 11 | @Configuration 12 | public class MbatisPlusConfig { 13 | 14 | /** 15 | * 3.4.0之后版本 16 | * @return 17 | */ 18 | @Bean 19 | public MybatisPlusInterceptor mybatisPlusInterceptor(){ 20 | MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); 21 | mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 22 | return mybatisPlusInterceptor; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.RedisConnectionFactory; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.serializer.StringRedisSerializer; 8 | 9 | @Configuration 10 | public class RedisConfig { 11 | 12 | @Bean 13 | @SuppressWarnings(value = { "unchecked", "rawtypes" }) 14 | public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) 15 | { 16 | RedisTemplate template = new RedisTemplate<>(); 17 | template.setConnectionFactory(connectionFactory); 18 | 19 | FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class); 20 | 21 | // 使用StringRedisSerializer来序列化和反序列化redis的key值 22 | template.setKeySerializer(new StringRedisSerializer()); 23 | template.setValueSerializer(serializer); 24 | 25 | // Hash的key也采用StringRedisSerializer的序列化方式 26 | template.setHashKeySerializer(new StringRedisSerializer()); 27 | template.setHashValueSerializer(serializer); 28 | 29 | template.afterPropertiesSet(); 30 | return template; 31 | } 32 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.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 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 12 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 13 | 14 | import java.util.List; 15 | 16 | @Configuration 17 | public class WebConfig implements WebMvcConfigurer { 18 | 19 | @Override 20 | public void addCorsMappings(CorsRegistry registry) { 21 | // 设置允许跨域的路径 22 | registry.addMapping("/**") 23 | // 设置允许跨域请求的域名 24 | .allowedOriginPatterns("*") 25 | // 是否允许cookie 26 | .allowCredentials(true) 27 | // 设置允许的请求方式 28 | .allowedMethods("GET", "POST", "DELETE", "PUT") 29 | // 设置允许的header属性 30 | .allowedHeaders("*") 31 | // 跨域允许时间 32 | .maxAge(3600); 33 | } 34 | 35 | @Bean//使用@Bean注入fastJsonHttpMessageConvert 36 | public HttpMessageConverter fastJsonHttpMessageConverters() { 37 | //1.需要定义一个Convert转换消息的对象 38 | FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); 39 | FastJsonConfig fastJsonConfig = new FastJsonConfig(); 40 | fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); 41 | fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); 42 | 43 | SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance); 44 | 45 | fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance); 46 | fastConverter.setFastJsonConfig(fastJsonConfig); 47 | HttpMessageConverter converter = fastConverter; 48 | return converter; 49 | } 50 | 51 | @Override 52 | public void configureMessageConverters(List> converters) { 53 | converters.add(fastJsonHttpMessageConverters()); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/constants/SystemConstants.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.constants; 2 | 3 | public class SystemConstants 4 | { 5 | /** 6 | * 文章是草稿 7 | */ 8 | public static final int ARTICLE_STATUS_DRAFT = 1; 9 | /** 10 | * 文章是正常分布状态 11 | */ 12 | public static final int ARTICLE_STATUS_NORMAL = 0; 13 | 14 | 15 | public static final String STATUS_NORMAL = "0"; 16 | /** 17 | * 友链状态为审核通过 18 | */ 19 | public static final String LINK_STATUS_NORMAL = "0"; 20 | /** 21 | * 评论类型为:文章评论 22 | */ 23 | public static final String ARTICLE_COMMENT = "0"; 24 | /** 25 | * 评论类型为:友联评论 26 | */ 27 | public static final String LINK_COMMENT = "1"; 28 | public static final String MENU = "C"; 29 | public static final String BUTTON = "F"; 30 | /** 正常状态 */ 31 | public static final String NORMAL = "0"; 32 | public static final String ADMAIN = "1"; 33 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/ResponseResult.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.sangeng.enums.AppHttpCodeEnum; 5 | 6 | import java.io.Serializable; 7 | 8 | @JsonInclude(JsonInclude.Include.NON_NULL) 9 | public class ResponseResult implements Serializable { 10 | private Integer code; 11 | private String msg; 12 | private T data; 13 | 14 | public ResponseResult() { 15 | this.code = AppHttpCodeEnum.SUCCESS.getCode(); 16 | this.msg = AppHttpCodeEnum.SUCCESS.getMsg(); 17 | } 18 | 19 | public ResponseResult(Integer code, T data) { 20 | this.code = code; 21 | this.data = data; 22 | } 23 | 24 | public ResponseResult(Integer code, String msg, T data) { 25 | this.code = code; 26 | this.msg = msg; 27 | this.data = data; 28 | } 29 | 30 | public ResponseResult(Integer code, String msg) { 31 | this.code = code; 32 | this.msg = msg; 33 | } 34 | 35 | public static ResponseResult errorResult(int code, String msg) { 36 | ResponseResult result = new ResponseResult(); 37 | return result.error(code, msg); 38 | } 39 | public static ResponseResult okResult() { 40 | ResponseResult result = new ResponseResult(); 41 | return result; 42 | } 43 | public static ResponseResult okResult(int code, String msg) { 44 | ResponseResult result = new ResponseResult(); 45 | return result.ok(code, null, msg); 46 | } 47 | 48 | public static ResponseResult okResult(Object data) { 49 | ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg()); 50 | if(data!=null) { 51 | result.setData(data); 52 | } 53 | return result; 54 | } 55 | 56 | public static ResponseResult errorResult(AppHttpCodeEnum enums){ 57 | return setAppHttpCodeEnum(enums,enums.getMsg()); 58 | } 59 | 60 | public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg){ 61 | return setAppHttpCodeEnum(enums,msg); 62 | } 63 | 64 | public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums){ 65 | return okResult(enums.getCode(),enums.getMsg()); 66 | } 67 | 68 | private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg){ 69 | return okResult(enums.getCode(),msg); 70 | } 71 | 72 | public ResponseResult error(Integer code, String msg) { 73 | this.code = code; 74 | this.msg = msg; 75 | return this; 76 | } 77 | 78 | public ResponseResult ok(Integer code, T data) { 79 | this.code = code; 80 | this.data = data; 81 | return this; 82 | } 83 | 84 | public ResponseResult ok(Integer code, T data, String msg) { 85 | this.code = code; 86 | this.data = data; 87 | this.msg = msg; 88 | return this; 89 | } 90 | 91 | public ResponseResult ok(T data) { 92 | this.data = data; 93 | return this; 94 | } 95 | 96 | public Integer getCode() { 97 | return code; 98 | } 99 | 100 | public void setCode(Integer code) { 101 | this.code = code; 102 | } 103 | 104 | public String getMsg() { 105 | return msg; 106 | } 107 | 108 | public void setMsg(String msg) { 109 | this.msg = msg; 110 | } 111 | 112 | public T getData() { 113 | return data; 114 | } 115 | 116 | public void setData(T data) { 117 | this.data = data; 118 | } 119 | 120 | 121 | 122 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/AddArticleDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class AddArticleDto { 15 | 16 | private Long id; 17 | //标题 18 | private String title; 19 | //文章内容 20 | private String content; 21 | //文章摘要 22 | private String summary; 23 | //所属分类id 24 | private Long categoryId; 25 | 26 | //缩略图 27 | private String thumbnail; 28 | //是否置顶(0否,1是) 29 | private String isTop; 30 | //状态(0已发布,1草稿) 31 | private String status; 32 | //访问量 33 | private Long viewCount; 34 | //是否允许评论 1是,0否 35 | private String isComment; 36 | private List tags; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/AddCommentDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | import java.util.Date; 13 | 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @ApiModel(description = "添加评论dto") 18 | public class AddCommentDto { 19 | private Long id; 20 | //评论类型(0代表文章评论,1代表友链评论) 21 | @ApiModelProperty(notes = "评论类型(0代表文章评论,1代表友链评论)") 22 | private String type; 23 | //文章id 24 | @ApiModelProperty(notes = "文章id") 25 | private Long articleId; 26 | //根评论id 27 | private Long rootId; 28 | //评论内容 29 | private String content; 30 | //所回复的目标评论的userid 31 | private Long toCommentUserId; 32 | //回复目标评论id 33 | private Long toCommentId; 34 | private Long createBy; 35 | private Date createTime; 36 | private Long updateBy; 37 | private Date updateTime; 38 | //删除标志(0代表未删除,1代表已删除) 39 | private Integer delFlag; 40 | } 41 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/AddTagDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class AddTagDto { 11 | //备注 12 | private String remark; 13 | //标签名 14 | private String name; 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/ArticleDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class ArticleDto { 13 | 14 | private Long id; 15 | //标题 16 | private String title; 17 | //文章内容 18 | private String content; 19 | //文章摘要 20 | private String summary; 21 | //所属分类id 22 | private Long categoryId; 23 | 24 | //缩略图 25 | private String thumbnail; 26 | //是否置顶(0否,1是) 27 | private String isTop; 28 | //状态(0已发布,1草稿) 29 | private String status; 30 | //访问量 31 | private Long viewCount; 32 | //是否允许评论 1是,0否 33 | private String isComment; 34 | private List tags; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/ChangeRoleStatusDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class ChangeRoleStatusDto { 11 | 12 | private Long roleId; 13 | private String status; 14 | } 15 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/EditTagDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class EditTagDto { 11 | 12 | private Long id; 13 | //备注 14 | private String remark; 15 | //标签名 16 | private String name; 17 | } 18 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/dto/TagListDto.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.dto; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class TagListDto { 12 | 13 | private String name; 14 | private String remark; 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Article.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import com.baomidou.mybatisplus.annotation.FieldFill; 6 | import com.baomidou.mybatisplus.annotation.TableField; 7 | import com.baomidou.mybatisplus.annotation.TableId; 8 | import com.baomidou.mybatisplus.annotation.TableName; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import lombok.experimental.Accessors; 13 | 14 | /** 15 | * 文章表(Article)表实体类 16 | * 17 | * @author makejava 18 | * @since 2022-02-01 11:36:28 19 | */ 20 | @SuppressWarnings("serial") 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @TableName("sg_article") 25 | @Accessors(chain = true) 26 | public class Article { 27 | @TableId 28 | private Long id; 29 | //标题 30 | private String title; 31 | //文章内容 32 | private String content; 33 | //文章摘要 34 | private String summary; 35 | //所属分类id 36 | private Long categoryId; 37 | 38 | @TableField(exist = false) 39 | private String categoryName; 40 | //缩略图 41 | private String thumbnail; 42 | //是否置顶(0否,1是) 43 | private String isTop; 44 | //状态(0已发布,1草稿) 45 | private String status; 46 | //访问量 47 | private Long viewCount; 48 | //是否允许评论 1是,0否 49 | private String isComment; 50 | 51 | @TableField(fill = FieldFill.INSERT) 52 | private Long createBy; 53 | @TableField(fill = FieldFill.INSERT) 54 | private Date createTime; 55 | @TableField(fill = FieldFill.INSERT_UPDATE) 56 | private Long updateBy; 57 | @TableField(fill = FieldFill.INSERT_UPDATE) 58 | private Date updateTime; 59 | //删除标志(0代表未删除,1代表已删除) 60 | private Integer delFlag; 61 | 62 | public Article(Long id, long viewCount) { 63 | this.id = id; 64 | this.viewCount = viewCount; 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/ArticleTag.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * 文章标签关联表(ArticleTag)实体类 12 | * 13 | * @author makejava 14 | * @since 2022-01-15 20:50:54 15 | */ 16 | @TableName(value="sg_article_tag") 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | public class ArticleTag implements Serializable { 21 | private static final long serialVersionUID = 625337492348897098L; 22 | 23 | /** 24 | * 文章id 25 | */ 26 | private Long articleId; 27 | /** 28 | * 标签id 29 | */ 30 | private Long tagId; 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Category.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | 7 | import com.baomidou.mybatisplus.annotation.TableId; 8 | import com.baomidou.mybatisplus.annotation.TableName; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | /** 13 | * 分类表(Category)表实体类 14 | * 15 | * @author makejava 16 | * @since 2022-02-02 12:29:48 17 | */ 18 | @SuppressWarnings("serial") 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @TableName("sg_category") 23 | public class Category { 24 | @TableId 25 | private Long id; 26 | 27 | //分类名 28 | private String name; 29 | //父分类id,如果没有父分类为-1 30 | private Long pid; 31 | //描述 32 | private String description; 33 | //状态0:正常,1禁用 34 | private String status; 35 | 36 | private Long createBy; 37 | 38 | private Date createTime; 39 | 40 | private Long updateBy; 41 | 42 | private Date updateTime; 43 | //删除标志(0代表未删除,1代表已删除) 44 | private Integer delFlag; 45 | 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Comment.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | 7 | import com.baomidou.mybatisplus.annotation.FieldFill; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import io.swagger.annotations.ApiModel; 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | import com.baomidou.mybatisplus.annotation.TableId; 14 | import com.baomidou.mybatisplus.annotation.TableName; 15 | /** 16 | * 评论表(Comment)表实体类 17 | * 18 | * @author makejava 19 | * @since 2022-02-08 23:49:34 20 | */ 21 | @SuppressWarnings("serial") 22 | @Data 23 | @AllArgsConstructor 24 | @NoArgsConstructor 25 | @TableName("sg_comment") 26 | @ApiModel(description = "添加评论实体类") 27 | public class Comment { 28 | @TableId 29 | private Long id; 30 | 31 | //评论类型(0代表文章评论,1代表友链评论) 32 | private String type; 33 | //文章id 34 | private Long articleId; 35 | //根评论id 36 | private Long rootId; 37 | //评论内容 38 | private String content; 39 | //所回复的目标评论的userid 40 | private Long toCommentUserId; 41 | //回复目标评论id 42 | private Long toCommentId; 43 | @TableField(fill = FieldFill.INSERT) 44 | private Long createBy; 45 | @TableField(fill = FieldFill.INSERT) 46 | private Date createTime; 47 | @TableField(fill = FieldFill.INSERT_UPDATE) 48 | private Long updateBy; 49 | @TableField(fill = FieldFill.INSERT_UPDATE) 50 | private Date updateTime; 51 | //删除标志(0代表未删除,1代表已删除) 52 | private Integer delFlag; 53 | 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Link.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import com.baomidou.mybatisplus.annotation.TableId; 10 | import com.baomidou.mybatisplus.annotation.TableName; 11 | /** 12 | * 友链(Link)表实体类 13 | * 14 | * @author makejava 15 | * @since 2022-02-03 12:22:50 16 | */ 17 | @SuppressWarnings("serial") 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @TableName("sg_link") 22 | public class Link { 23 | @TableId 24 | private Long id; 25 | 26 | 27 | private String name; 28 | 29 | private String logo; 30 | 31 | private String description; 32 | //网站地址 33 | private String address; 34 | //审核状态 (0代表审核通过,1代表审核未通过,2代表未审核) 35 | private String status; 36 | 37 | private Long createBy; 38 | 39 | private Date createTime; 40 | 41 | private Long updateBy; 42 | 43 | private Date updateTime; 44 | //删除标志(0代表未删除,1代表已删除) 45 | private Integer delFlag; 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/LoginUser.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.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.userdetails.UserDetails; 8 | 9 | import java.util.Collection; 10 | import java.util.List; 11 | 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class LoginUser implements UserDetails { 16 | 17 | private User user; 18 | 19 | 20 | private List permissions; 21 | 22 | @Override 23 | public Collection getAuthorities() { 24 | return null; 25 | } 26 | 27 | @Override 28 | public String getPassword() { 29 | return user.getPassword(); 30 | } 31 | 32 | @Override 33 | public String getUsername() { 34 | return user.getUserName(); 35 | } 36 | 37 | @Override 38 | public boolean isAccountNonExpired() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean isAccountNonLocked() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean isCredentialsNonExpired() { 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean isEnabled() { 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Menu.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import com.baomidou.mybatisplus.annotation.TableId; 13 | import com.baomidou.mybatisplus.annotation.TableName; 14 | import lombok.experimental.Accessors; 15 | 16 | /** 17 | * 菜单权限表(Menu)表实体类 18 | * 19 | * @author makejava 20 | * @since 2022-08-09 23:47:50 21 | */ 22 | @SuppressWarnings("serial") 23 | @Data 24 | @AllArgsConstructor 25 | @NoArgsConstructor 26 | @TableName("sys_menu") 27 | @Accessors(chain = true) 28 | public class Menu { 29 | //菜单ID 30 | @TableId 31 | private Long id; 32 | 33 | //菜单名称 34 | private String menuName; 35 | //父菜单ID 36 | private Long parentId; 37 | //显示顺序 38 | private Integer orderNum; 39 | //路由地址 40 | private String path; 41 | //组件路径 42 | private String component; 43 | //是否为外链(0是 1否) 44 | private Integer isFrame; 45 | //菜单类型(M目录 C菜单 F按钮) 46 | private String menuType; 47 | //菜单状态(0显示 1隐藏) 48 | private String visible; 49 | //菜单状态(0正常 1停用) 50 | private String status; 51 | //权限标识 52 | private String perms; 53 | //菜单图标 54 | private String icon; 55 | //创建者 56 | private Long createBy; 57 | //创建时间 58 | private Date createTime; 59 | //更新者 60 | private Long updateBy; 61 | //更新时间 62 | private Date updateTime; 63 | //备注 64 | private String remark; 65 | 66 | private String delFlag; 67 | 68 | @TableField(exist = false) 69 | private List children; 70 | } 71 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | 7 | import com.baomidou.mybatisplus.annotation.FieldFill; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import com.baomidou.mybatisplus.annotation.TableId; 13 | import com.baomidou.mybatisplus.annotation.TableName; 14 | /** 15 | * 角色信息表(Role)表实体类 16 | * 17 | * @author makejava 18 | * @since 2022-08-09 22:36:46 19 | */ 20 | @SuppressWarnings("serial") 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @TableName("sys_role") 25 | public class Role { 26 | //角色ID@TableId 27 | private Long id; 28 | 29 | //角色名称 30 | private String roleName; 31 | //角色权限字符串 32 | private String roleKey; 33 | //显示顺序 34 | private Integer roleSort; 35 | 36 | //角色状态(0正常 1停用) 37 | private String status; 38 | //删除标志(0代表存在 2代表删除) 39 | private String delFlag; 40 | @TableField(fill = FieldFill.INSERT) 41 | private Long createBy; 42 | @TableField(fill = FieldFill.INSERT) 43 | private Date createTime; 44 | @TableField(fill = FieldFill.INSERT_UPDATE) 45 | private Long updateBy; 46 | @TableField(fill = FieldFill.INSERT_UPDATE) 47 | private Date updateTime; 48 | //备注 49 | private String remark; 50 | 51 | //关联菜单id数组,不是表中的字段 用来接收参数使用 52 | @TableField(exist = false) 53 | private Long[] menuIds; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/RoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author 三更 B站: https://space.bilibili.com/663528522 10 | */ 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @TableName("sys_role_menu") 15 | public class RoleMenu { 16 | /** 角色ID */ 17 | private Long roleId; 18 | 19 | /** 菜单ID */ 20 | private Long menuId; 21 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/Tag.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | 7 | import com.baomidou.mybatisplus.annotation.FieldFill; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import com.baomidou.mybatisplus.annotation.TableId; 13 | import com.baomidou.mybatisplus.annotation.TableName; 14 | /** 15 | * 标签(Tag)表实体类 16 | * 17 | * @author makejava 18 | * @since 2022-07-19 22:33:36 19 | */ 20 | @SuppressWarnings("serial") 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @TableName("sg_tag") 25 | public class Tag { 26 | @TableId 27 | private Long id; 28 | 29 | 30 | @TableField(fill = FieldFill.INSERT) 31 | private Long createBy; 32 | @TableField(fill = FieldFill.INSERT) 33 | private Date createTime; 34 | @TableField(fill = FieldFill.INSERT_UPDATE) 35 | private Long updateBy; 36 | @TableField(fill = FieldFill.INSERT_UPDATE) 37 | private Date updateTime; 38 | 39 | //删除标志(0代表未删除,1代表已删除) 40 | private Integer delFlag; 41 | //备注 42 | private String remark; 43 | //标签名 44 | private String name; 45 | 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import java.util.Date; 4 | 5 | import java.io.Serializable; 6 | 7 | import com.baomidou.mybatisplus.annotation.TableField; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | import com.baomidou.mybatisplus.annotation.TableId; 12 | import com.baomidou.mybatisplus.annotation.TableName; 13 | /** 14 | * 用户表(User)表实体类 15 | * 16 | * @author makejava 17 | * @since 2022-02-03 16:25:40 18 | */ 19 | @SuppressWarnings("serial") 20 | @Data 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @TableName("sys_user") 24 | public class User { 25 | //主键@TableId 26 | private Long id; 27 | 28 | //用户名 29 | private String userName; 30 | //昵称 31 | private String nickName; 32 | //密码 33 | private String password; 34 | //用户类型:0代表普通用户,1代表管理员 35 | private String type; 36 | //账号状态(0正常 1停用) 37 | private String status; 38 | //邮箱 39 | private String email; 40 | //手机号 41 | private String phonenumber; 42 | //用户性别(0男,1女,2未知) 43 | private String sex; 44 | //头像 45 | private String avatar; 46 | //创建人的用户id 47 | private Long createBy; 48 | //创建时间 49 | private Date createTime; 50 | //更新人 51 | private Long updateBy; 52 | //更新时间 53 | private Date updateTime; 54 | //删除标志(0代表未删除,1代表已删除) 55 | private Integer delFlag; 56 | 57 | 58 | //关联角色id数组,非user表字段 59 | @TableField(exist = false) 60 | private Long[] roleIds; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/entity/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author 三更 B站: https://space.bilibili.com/663528522 10 | */ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @TableName("sys_user_role") 15 | public class UserRole { 16 | 17 | /** 用户ID */ 18 | private Long userId; 19 | 20 | /** 角色ID */ 21 | private Long roleId; 22 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/AdminUserInfoVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class AdminUserInfoVo { 15 | 16 | private List permissions; 17 | 18 | private List roles; 19 | 20 | private UserInfoVo user; 21 | } 22 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/ArticleDetailVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ArticleDetailVo { 13 | 14 | private Long id; 15 | //标题 16 | private String title; 17 | //文章摘要 18 | private String summary; 19 | //所属分类id 20 | private Long categoryId; 21 | //所属分类名 22 | private String categoryName; 23 | //缩略图 24 | private String thumbnail; 25 | 26 | //文章内容 27 | private String content; 28 | //访问量 29 | private Long viewCount; 30 | 31 | private Date createTime; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/ArticleListVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ArticleListVo { 13 | 14 | private Long id; 15 | //标题 16 | private String title; 17 | //文章摘要 18 | private String summary; 19 | //所属分类名 20 | private String categoryName; 21 | //缩略图 22 | private String thumbnail; 23 | 24 | 25 | //访问量 26 | private Long viewCount; 27 | 28 | private Date createTime; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/ArticleVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class ArticleVo { 13 | 14 | private Long id; 15 | //标题 16 | private String title; 17 | //文章内容 18 | private String content; 19 | //文章摘要 20 | private String summary; 21 | //所属分类id 22 | private Long categoryId; 23 | 24 | //缩略图 25 | private String thumbnail; 26 | //是否置顶(0否,1是) 27 | private String isTop; 28 | //状态(0已发布,1草稿) 29 | private String status; 30 | //访问量 31 | private Long viewCount; 32 | //是否允许评论 1是,0否 33 | private String isComment; 34 | private List tags; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/BlogUserLoginVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class BlogUserLoginVo { 11 | 12 | private String token; 13 | private UserInfoVo userInfo; 14 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/CategoryVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class CategoryVo { 11 | 12 | private Long id; 13 | private String name; 14 | //描述 15 | private String description; 16 | } 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/CommentVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class CommentVo { 14 | private Long id; 15 | //文章id 16 | private Long articleId; 17 | //根评论id 18 | private Long rootId; 19 | //评论内容 20 | private String content; 21 | //所回复的目标评论的userid 22 | private Long toCommentUserId; 23 | private String toCommentUserName; 24 | //回复目标评论id 25 | private Long toCommentId; 26 | 27 | private Long createBy; 28 | 29 | private Date createTime; 30 | 31 | private String username; 32 | 33 | private List children; 34 | } 35 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/ExcelCategoryVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import com.alibaba.excel.annotation.ExcelProperty; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class ExcelCategoryVo { 12 | @ExcelProperty("分类名") 13 | private String name; 14 | //描述 15 | @ExcelProperty("描述") 16 | private String description; 17 | 18 | //状态0:正常,1禁用 19 | @ExcelProperty("状态0:正常,1禁用") 20 | private String status; 21 | } 22 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/HotArticleVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class HotArticleVo { 12 | private Long id; 13 | //标题 14 | private String title; 15 | 16 | //访问量 17 | private Long viewCount; 18 | } 19 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/LinkVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class LinkVo { 11 | private Long id; 12 | 13 | 14 | private String name; 15 | 16 | private String logo; 17 | 18 | private String description; 19 | //网站地址 20 | private String address; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/MenuTreeVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author 三更 B站: https://space.bilibili.com/663528522 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Accessors(chain = true) 17 | public class MenuTreeVo { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | /** 节点ID */ 22 | private Long id; 23 | 24 | /** 节点名称 */ 25 | private String label; 26 | 27 | private Long parentId; 28 | 29 | /** 子节点 */ 30 | // @JsonInclude(JsonInclude.Include.NON_EMPTY) 31 | private List children; 32 | } 33 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/MenuVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * 菜单权限表(Menu)表实体类 16 | * 17 | * @author makejava 18 | * @since 2022-08-09 23:47:50 19 | */ 20 | @SuppressWarnings("serial") 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Accessors(chain = true) 25 | public class MenuVo { 26 | //菜单ID 27 | private Long id; 28 | 29 | //菜单名称 30 | private String menuName; 31 | //父菜单ID 32 | private Long parentId; 33 | //显示顺序 34 | private Integer orderNum; 35 | //路由地址 36 | private String path; 37 | //组件路径 38 | private String component; 39 | //是否为外链(0是 1否) 40 | private Integer isFrame; 41 | //菜单类型(M目录 C菜单 F按钮) 42 | private String menuType; 43 | //菜单状态(0显示 1隐藏) 44 | private String visible; 45 | //菜单状态(0正常 1停用) 46 | private String status; 47 | //权限标识 48 | private String perms; 49 | //菜单图标 50 | private String icon; 51 | 52 | //备注 53 | private String remark; 54 | 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/PageVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class PageVo { 13 | private List rows; 14 | private Long total; 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/RoleMenuTreeSelectVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class RoleMenuTreeSelectVo { 15 | 16 | private List checkedKeys; 17 | 18 | private List menus; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/RoutersVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import com.sangeng.domain.entity.Menu; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class RoutersVo { 13 | 14 | private List menus; 15 | } 16 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/TagVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 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 | 11 | import java.util.Date; 12 | 13 | /** 14 | * 标签(Tag)表实体类 15 | * 16 | * @author makejava 17 | * @since 2022-07-19 22:33:36 18 | */ 19 | @SuppressWarnings("serial") 20 | @Data 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | public class TagVo { 24 | private Long id; 25 | //标签名 26 | private String name; 27 | 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/UserInfoAndRoleIdsVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import com.sangeng.domain.entity.Role; 4 | import com.sangeng.domain.entity.User; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 标签(Tag)表实体类 13 | * 14 | * @author makejava 15 | * @since 2022-07-19 22:33:36 16 | */ 17 | @SuppressWarnings("serial") 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class UserInfoAndRoleIdsVo { 22 | private User user; 23 | private List roles; 24 | private List roleIds; 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/UserInfoVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | @Data 7 | @Accessors(chain = true) 8 | public class UserInfoVo { 9 | /** 10 | * 主键 11 | */ 12 | private Long id; 13 | 14 | /** 15 | * 昵称 16 | */ 17 | private String nickName; 18 | 19 | /** 20 | * 头像 21 | */ 22 | private String avatar; 23 | 24 | private String sex; 25 | 26 | private String email; 27 | 28 | 29 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/domain/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.domain.vo; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * @Author 三更 B站: https://space.bilibili.com/663528522 10 | */ 11 | @Data 12 | @Accessors(chain = true) 13 | public class UserVo { 14 | /** 15 | * 主键 16 | */ 17 | private Long id; 18 | /** 19 | * 用户名 20 | */ 21 | private String userName; 22 | /** 23 | * 昵称 24 | */ 25 | private String nickName; 26 | 27 | /** 28 | * 账号状态(0正常 1停用) 29 | */ 30 | private String status; 31 | /** 32 | * 邮箱 33 | */ 34 | private String email; 35 | /** 36 | * 手机号 37 | */ 38 | private String phonenumber; 39 | /** 40 | * 用户性别(0男,1女,2未知) 41 | */ 42 | private String sex; 43 | /** 44 | * 头像 45 | */ 46 | private String avatar; 47 | 48 | /** 49 | * 创建人的用户id 50 | */ 51 | private Long createBy; 52 | /** 53 | * 创建时间 54 | */ 55 | private Date createTime; 56 | /** 57 | * 更新人 58 | */ 59 | private Long updateBy; 60 | /** 61 | * 更新时间 62 | */ 63 | private Date updateTime; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/enums/AppHttpCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.enums; 2 | 3 | public enum AppHttpCodeEnum { 4 | // 成功 5 | SUCCESS(200,"操作成功"), 6 | // 登录 7 | NEED_LOGIN(401,"需要登录后操作"), 8 | NO_OPERATOR_AUTH(403,"无权限操作"), 9 | SYSTEM_ERROR(500,"出现错误"), 10 | USERNAME_EXIST(501,"用户名已存在"), 11 | PHONENUMBER_EXIST(502,"手机号已存在"), EMAIL_EXIST(503, "邮箱已存在"), 12 | REQUIRE_USERNAME(504, "必需填写用户名"), 13 | CONTENT_NOT_NULL(506, "评论内容不能为空"), 14 | FILE_TYPE_ERROR(507, "文件类型错误,请上传png文件"), 15 | USERNAME_NOT_NULL(508, "用户名不能为空"), 16 | NICKNAME_NOT_NULL(509, "昵称不能为空"), 17 | PASSWORD_NOT_NULL(510, "密码不能为空"), 18 | EMAIL_NOT_NULL(511, "邮箱不能为空"), 19 | NICKNAME_EXIST(512, "昵称已存在"), 20 | LOGIN_ERROR(505,"用户名或密码错误"); 21 | int code; 22 | String msg; 23 | 24 | AppHttpCodeEnum(int code, String errorMessage){ 25 | this.code = code; 26 | this.msg = errorMessage; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public String getMsg() { 34 | return msg; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/exception/SystemException.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.exception; 2 | 3 | import com.sangeng.enums.AppHttpCodeEnum; 4 | 5 | /** 6 | * @Author 三更 B站: https://space.bilibili.com/663528522 7 | */ 8 | public class SystemException extends RuntimeException{ 9 | 10 | private int code; 11 | 12 | private String msg; 13 | 14 | public int getCode() { 15 | return code; 16 | } 17 | 18 | public String getMsg() { 19 | return msg; 20 | } 21 | 22 | public SystemException(AppHttpCodeEnum httpCodeEnum) { 23 | super(httpCodeEnum.getMsg()); 24 | this.code = httpCodeEnum.getCode(); 25 | this.msg = httpCodeEnum.getMsg(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/handler/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.handler.exception; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.enums.AppHttpCodeEnum; 5 | import com.sangeng.exception.SystemException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.bind.annotation.RestControllerAdvice; 11 | 12 | 13 | @RestControllerAdvice 14 | @Slf4j 15 | public class GlobalExceptionHandler { 16 | 17 | @ExceptionHandler(SystemException.class) 18 | public ResponseResult systemExceptionHandler(SystemException e){ 19 | //打印异常信息 20 | log.error("出现了异常! {}",e); 21 | //从异常对象中获取提示信息封装返回 22 | return ResponseResult.errorResult(e.getCode(),e.getMsg()); 23 | } 24 | 25 | 26 | @ExceptionHandler(Exception.class) 27 | public ResponseResult exceptionHandler(Exception e){ 28 | //打印异常信息 29 | log.error("出现了异常! {}",e); 30 | //从异常对象中获取提示信息封装返回 31 | return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/handler/mybatisplus/MyMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.handler.mybatisplus; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import com.sangeng.utils.SecurityUtils; 5 | import org.apache.ibatis.reflection.MetaObject; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Date; 9 | 10 | @Component 11 | public class MyMetaObjectHandler implements MetaObjectHandler { 12 | @Override 13 | public void insertFill(MetaObject metaObject) { 14 | Long userId = null; 15 | // try { 16 | userId = SecurityUtils.getUserId(); 17 | // } catch (Exception e) { 18 | // e.printStackTrace(); 19 | // userId = -1L;//表示是自己创建 20 | // } 21 | this.setFieldValByName("createTime", new Date(), metaObject); 22 | this.setFieldValByName("createBy",userId , metaObject); 23 | this.setFieldValByName("updateTime", new Date(), metaObject); 24 | this.setFieldValByName("updateBy", userId, metaObject); 25 | } 26 | 27 | @Override 28 | public void updateFill(MetaObject metaObject) { 29 | this.setFieldValByName("updateTime", new Date(), metaObject); 30 | this.setFieldValByName(" ", SecurityUtils.getUserId(), metaObject); 31 | } 32 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/handler/security/AccessDeniedHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.handler.security; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.enums.AppHttpCodeEnum; 6 | import com.sangeng.utils.WebUtils; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class AccessDeniedHandlerImpl implements AccessDeniedHandler { 18 | @Override 19 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 20 | accessDeniedException.printStackTrace(); 21 | ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH); 22 | //响应给前端 23 | WebUtils.renderString(response, JSON.toJSONString(result)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/handler/security/AuthenticationEntryPointImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.handler.security; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.enums.AppHttpCodeEnum; 6 | import com.sangeng.utils.WebUtils; 7 | import org.springframework.security.authentication.BadCredentialsException; 8 | import org.springframework.security.authentication.InsufficientAuthenticationException; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.servlet.ServletException; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | 18 | @Component 19 | public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { 20 | 21 | @Override 22 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 23 | authException.printStackTrace(); 24 | //InsufficientAuthenticationException 25 | //BadCredentialsException 26 | ResponseResult result = null; 27 | if(authException instanceof BadCredentialsException){ 28 | result = ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(),authException.getMessage()); 29 | }else if(authException instanceof InsufficientAuthenticationException){ 30 | result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN); 31 | }else{ 32 | result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),"认证或授权失败"); 33 | } 34 | //响应给前端 35 | WebUtils.renderString(response, JSON.toJSONString(result)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/ArticleMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Article; 5 | 6 | public interface ArticleMapper extends BaseMapper
{ 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/ArticleTagMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.ArticleTag; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface ArticleTagMapper extends BaseMapper { 10 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Category; 5 | 6 | 7 | /** 8 | * 分类表(Category)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2022-02-02 12:31:18 12 | */ 13 | public interface CategoryMapper extends BaseMapper { 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/CommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Comment; 5 | 6 | 7 | /** 8 | * 评论表(Comment)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2022-02-08 23:49:33 12 | */ 13 | public interface CommentMapper extends BaseMapper { 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/LinkMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Link; 5 | 6 | 7 | /** 8 | * 友链(Link)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2022-02-03 12:22:49 12 | */ 13 | public interface LinkMapper extends BaseMapper { 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/MenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Menu; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * 菜单权限表(Menu)表数据库访问层 11 | * 12 | * @author makejava 13 | * @since 2022-08-09 22:32:07 14 | */ 15 | public interface MenuMapper extends BaseMapper { 16 | 17 | List selectPermsByUserId(Long userId); 18 | 19 | List selectAllRouterMenu(); 20 | 21 | List selectRouterMenuTreeByUserId(Long userId); 22 | 23 | List selectMenuListByRoleId(Long roleId); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Role; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * 角色信息表(Role)表数据库访问层 11 | * 12 | * @author makejava 13 | * @since 2022-08-09 22:36:44 14 | */ 15 | public interface RoleMapper extends BaseMapper { 16 | 17 | List selectRoleKeyByUserId(Long userId); 18 | 19 | List selectRoleIdByUserId(Long userId); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/RoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.RoleMenu; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface RoleMenuMapper extends BaseMapper { 10 | } 11 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/TagMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.Tag; 5 | 6 | 7 | /** 8 | * 标签(Tag)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2022-07-19 22:33:35 12 | */ 13 | public interface TagMapper extends BaseMapper { 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.User; 5 | 6 | 7 | /** 8 | * 用户表(User)表数据库访问层 9 | * 10 | * @author makejava 11 | * @since 2022-02-03 16:25:39 12 | */ 13 | public interface UserMapper extends BaseMapper { 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.sangeng.domain.entity.UserRole; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface UserRoleMapper extends BaseMapper { 10 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/ArticleService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.dto.AddArticleDto; 6 | import com.sangeng.domain.dto.ArticleDto; 7 | import com.sangeng.domain.entity.Article; 8 | import com.sangeng.domain.vo.ArticleVo; 9 | import com.sangeng.domain.vo.PageVo; 10 | 11 | public interface ArticleService extends IService
{ 12 | ResponseResult hotArticleList(); 13 | 14 | ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId); 15 | 16 | ResponseResult getArticleDetail(Long id); 17 | 18 | ResponseResult updateViewCount(Long id); 19 | 20 | ResponseResult add(AddArticleDto article); 21 | 22 | PageVo selectArticlePage(Article article, Integer pageNum, Integer pageSize); 23 | 24 | ArticleVo getInfo(Long id); 25 | 26 | void edit(ArticleDto article); 27 | } 28 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/ArticleTagService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.entity.ArticleTag; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface ArticleTagService extends IService { 10 | } 11 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/BlogLoginService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.User; 5 | 6 | public interface BlogLoginService { 7 | ResponseResult login(User user); 8 | 9 | ResponseResult logout(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.Category; 6 | import com.sangeng.domain.vo.CategoryVo; 7 | import com.sangeng.domain.vo.PageVo; 8 | 9 | import java.util.List; 10 | 11 | 12 | /** 13 | * 分类表(Category)表服务接口 14 | * 15 | * @author makejava 16 | * @since 2022-02-02 12:29:50 17 | */ 18 | public interface CategoryService extends IService { 19 | 20 | 21 | ResponseResult getCategoryList(); 22 | 23 | List listAllCategory(); 24 | 25 | PageVo selectCategoryPage(Category category, Integer pageNum, Integer pageSize); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.Comment; 6 | 7 | 8 | /** 9 | * 评论表(Comment)表服务接口 10 | * 11 | * @author makejava 12 | * @since 2022-02-08 23:49:35 13 | */ 14 | public interface CommentService extends IService { 15 | 16 | ResponseResult commentList(String commentType, Long articleId, Integer pageNum, Integer pageSize); 17 | 18 | ResponseResult addComment(Comment comment); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/LinkService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.Link; 6 | import com.sangeng.domain.vo.PageVo; 7 | 8 | 9 | /** 10 | * 友链(Link)表服务接口 11 | * 12 | * @author makejava 13 | * @since 2022-02-03 12:22:53 14 | */ 15 | public interface LinkService extends IService { 16 | 17 | ResponseResult getAllLink(); 18 | 19 | PageVo selectLinkPage(Link link, Integer pageNum, Integer pageSize); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.User; 5 | 6 | public interface LoginService { 7 | ResponseResult login(User user); 8 | 9 | 10 | ResponseResult logout(); 11 | } 12 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/MenuService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.entity.Menu; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * 菜单权限表(Menu)表服务接口 11 | * 12 | * @author makejava 13 | * @since 2022-08-09 22:32:09 14 | */ 15 | public interface MenuService extends IService { 16 | 17 | List selectPermsByUserId(Long id); 18 | 19 | List selectRouterMenuTreeByUserId(Long userId); 20 | 21 | List selectMenuList(Menu menu); 22 | 23 | boolean hasChild(Long menuId); 24 | 25 | List selectMenuListByRoleId(Long roleId); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/RoleMenuService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.entity.RoleMenu; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface RoleMenuService extends IService { 10 | 11 | void deleteRoleMenuByRoleId(Long id); 12 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/RoleService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.Role; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * 角色信息表(Role)表服务接口 12 | * 13 | * @author makejava 14 | * @since 2022-08-09 22:36:47 15 | */ 16 | public interface RoleService extends IService { 17 | 18 | List selectRoleKeyByUserId(Long id); 19 | 20 | ResponseResult selectRolePage(Role role, Integer pageNum, Integer pageSize); 21 | 22 | void insertRole(Role role); 23 | 24 | void updateRole(Role role); 25 | 26 | List selectRoleAll(); 27 | 28 | List selectRoleIdByUserId(Long userId); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/TagService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.dto.TagListDto; 6 | import com.sangeng.domain.entity.Tag; 7 | import com.sangeng.domain.vo.PageVo; 8 | import com.sangeng.domain.vo.TagVo; 9 | 10 | import java.util.List; 11 | 12 | 13 | /** 14 | * 标签(Tag)表服务接口 15 | * 16 | * @author makejava 17 | * @since 2022-07-19 22:33:38 18 | */ 19 | public interface TagService extends IService { 20 | 21 | ResponseResult pageTagList(Integer pageNum, Integer pageSize, TagListDto tagListDto); 22 | 23 | List listAllTag(); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/UploadService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | import java.io.IOException; 7 | 8 | public interface UploadService { 9 | ResponseResult uploadImg(MultipartFile img) throws IOException; 10 | } 11 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/UserRoleService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.entity.UserRole; 5 | 6 | /** 7 | * @Author 三更 B站: https://space.bilibili.com/663528522 8 | */ 9 | public interface UserRoleService extends IService { 10 | } 11 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.sangeng.domain.ResponseResult; 5 | import com.sangeng.domain.entity.User; 6 | 7 | 8 | /** 9 | * 用户表(User)表服务接口 10 | * 11 | * @author makejava 12 | * @since 2022-02-09 00:28:29 13 | */ 14 | public interface UserService extends IService { 15 | 16 | ResponseResult userInfo(); 17 | 18 | ResponseResult updateUserInfo(User user); 19 | 20 | ResponseResult register(User user); 21 | 22 | ResponseResult selectUserPage(User user, Integer pageNum, Integer pageSize); 23 | 24 | boolean checkUserNameUnique(String userName); 25 | 26 | boolean checkPhoneUnique(User user); 27 | 28 | boolean checkEmailUnique(User user); 29 | 30 | ResponseResult addUser(User user); 31 | 32 | void updateUser(User user); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/ArticleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.sangeng.constants.SystemConstants; 7 | import com.sangeng.domain.ResponseResult; 8 | import com.sangeng.domain.dto.AddArticleDto; 9 | import com.sangeng.domain.dto.ArticleDto; 10 | import com.sangeng.domain.entity.Article; 11 | import com.sangeng.domain.entity.ArticleTag; 12 | import com.sangeng.domain.entity.Category; 13 | import com.sangeng.domain.vo.*; 14 | import com.sangeng.mapper.ArticleMapper; 15 | import com.sangeng.service.ArticleService; 16 | import com.sangeng.service.ArticleTagService; 17 | import com.sangeng.service.CategoryService; 18 | import com.sangeng.utils.BeanCopyUtils; 19 | import com.sangeng.utils.RedisCache; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.cglib.beans.BeanCopier; 22 | import org.springframework.stereotype.Service; 23 | import org.springframework.transaction.annotation.Transactional; 24 | import org.springframework.util.StringUtils; 25 | 26 | import java.util.List; 27 | import java.util.Objects; 28 | import java.util.stream.Collectors; 29 | 30 | @Service 31 | public class ArticleServiceImpl extends ServiceImpl implements ArticleService { 32 | 33 | @Autowired 34 | private CategoryService categoryService; 35 | 36 | @Autowired 37 | private RedisCache redisCache; 38 | 39 | @Autowired 40 | private ArticleTagService articleTagService; 41 | 42 | @Override 43 | public ResponseResult hotArticleList() { 44 | //查询热门文章 封装成ResponseResult返回 45 | LambdaQueryWrapper
queryWrapper = new LambdaQueryWrapper<>(); 46 | //必须是正式文章 47 | queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL); 48 | //按照浏览量进行排序 49 | queryWrapper.orderByDesc(Article::getViewCount); 50 | //最多只查询10条 51 | Page
page = new Page(1,10); 52 | page(page,queryWrapper); 53 | 54 | List
articles = page.getRecords(); 55 | //bean拷贝 56 | // List articleVos = new ArrayList<>(); 57 | // for (Article article : articles) { 58 | // HotArticleVo vo = new HotArticleVo(); 59 | // BeanUtils.copyProperties(article,vo); 60 | // articleVos.add(vo); 61 | // } 62 | List vs = BeanCopyUtils.copyBeanList(articles, HotArticleVo.class); 63 | return ResponseResult.okResult(vs); 64 | } 65 | 66 | @Override 67 | public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) { 68 | //查询条件 69 | LambdaQueryWrapper
lambdaQueryWrapper = new LambdaQueryWrapper<>(); 70 | // 如果 有categoryId 就要 查询时要和传入的相同 71 | lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId>0 ,Article::getCategoryId,categoryId); 72 | // 状态是正式发布的 73 | lambdaQueryWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL); 74 | // 对isTop进行降序 75 | lambdaQueryWrapper.orderByDesc(Article::getIsTop); 76 | 77 | //分页查询 78 | Page
page = new Page<>(pageNum,pageSize); 79 | page(page,lambdaQueryWrapper); 80 | 81 | List
articles = page.getRecords(); 82 | //查询categoryName 83 | articles.stream() 84 | .map(article -> article.setCategoryName(categoryService.getById(article.getCategoryId()).getName())) 85 | .collect(Collectors.toList()); 86 | //articleId去查询articleName进行设置 87 | // for (Article article : articles) { 88 | // Category category = categoryService.getById(article.getCategoryId()); 89 | // article.setCategoryName(category.getName()); 90 | // } 91 | 92 | 93 | //封装查询结果 94 | List articleListVos = BeanCopyUtils.copyBeanList(page.getRecords(), ArticleListVo.class); 95 | 96 | 97 | 98 | 99 | PageVo pageVo = new PageVo(articleListVos,page.getTotal()); 100 | return ResponseResult.okResult(pageVo); 101 | } 102 | 103 | @Override 104 | public ResponseResult getArticleDetail(Long id) { 105 | //根据id查询文章 106 | Article article = getById(id); 107 | //从redis中获取viewCount 108 | Integer viewCount = redisCache.getCacheMapValue("article:viewCount", id.toString()); 109 | article.setViewCount(viewCount.longValue()); 110 | //转换成VO 111 | ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class); 112 | //根据分类id查询分类名 113 | Long categoryId = articleDetailVo.getCategoryId(); 114 | Category category = categoryService.getById(categoryId); 115 | if(category!=null){ 116 | articleDetailVo.setCategoryName(category.getName()); 117 | } 118 | //封装响应返回 119 | return ResponseResult.okResult(articleDetailVo); 120 | } 121 | 122 | @Override 123 | public ResponseResult updateViewCount(Long id) { 124 | //更新redis中对应 id的浏览量 125 | redisCache.incrementCacheMapValue("article:viewCount",id.toString(),1); 126 | return ResponseResult.okResult(); 127 | } 128 | 129 | @Override 130 | @Transactional 131 | public ResponseResult add(AddArticleDto articleDto) { 132 | //添加 博客 133 | Article article = BeanCopyUtils.copyBean(articleDto, Article.class); 134 | save(article); 135 | 136 | 137 | List articleTags = articleDto.getTags().stream() 138 | .map(tagId -> new ArticleTag(article.getId(), tagId)) 139 | .collect(Collectors.toList()); 140 | 141 | //添加 博客和标签的关联 142 | articleTagService.saveBatch(articleTags); 143 | return ResponseResult.okResult(); 144 | } 145 | 146 | @Override 147 | public PageVo selectArticlePage(Article article, Integer pageNum, Integer pageSize) { 148 | LambdaQueryWrapper
queryWrapper = new LambdaQueryWrapper(); 149 | 150 | queryWrapper.like(StringUtils.hasText(article.getTitle()),Article::getTitle, article.getTitle()); 151 | queryWrapper.like(StringUtils.hasText(article.getSummary()),Article::getSummary, article.getSummary()); 152 | 153 | Page
page = new Page<>(); 154 | page.setCurrent(pageNum); 155 | page.setSize(pageSize); 156 | page(page,queryWrapper); 157 | 158 | //转换成VO 159 | List
articles = page.getRecords(); 160 | 161 | //这里偷懒没写VO的转换 应该转换完在设置到最后的pageVo中 162 | 163 | PageVo pageVo = new PageVo(); 164 | pageVo.setTotal(page.getTotal()); 165 | pageVo.setRows(articles); 166 | return pageVo; 167 | } 168 | 169 | @Override 170 | public ArticleVo getInfo(Long id) { 171 | Article article = getById(id); 172 | //获取关联标签 173 | LambdaQueryWrapper articleTagLambdaQueryWrapper = new LambdaQueryWrapper<>(); 174 | articleTagLambdaQueryWrapper.eq(ArticleTag::getArticleId,article.getId()); 175 | List articleTags = articleTagService.list(articleTagLambdaQueryWrapper); 176 | List tags = articleTags.stream().map(articleTag -> articleTag.getTagId()).collect(Collectors.toList()); 177 | 178 | ArticleVo articleVo = BeanCopyUtils.copyBean(article,ArticleVo.class); 179 | articleVo.setTags(tags); 180 | return articleVo; 181 | } 182 | 183 | @Override 184 | public void edit(ArticleDto articleDto) { 185 | Article article = BeanCopyUtils.copyBean(articleDto, Article.class); 186 | //更新博客信息 187 | updateById(article); 188 | //删除原有的 标签和博客的关联 189 | LambdaQueryWrapper articleTagLambdaQueryWrapper = new LambdaQueryWrapper<>(); 190 | articleTagLambdaQueryWrapper.eq(ArticleTag::getArticleId,article.getId()); 191 | articleTagService.remove(articleTagLambdaQueryWrapper); 192 | //添加新的博客和标签的关联信息 193 | List articleTags = articleDto.getTags().stream() 194 | .map(tagId -> new ArticleTag(articleDto.getId(), tagId)) 195 | .collect(Collectors.toList()); 196 | articleTagService.saveBatch(articleTags); 197 | 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/ArticleTagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.sangeng.domain.entity.ArticleTag; 5 | import com.sangeng.mapper.ArticleTagMapper; 6 | import com.sangeng.service.ArticleTagService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @Author 三更 B站: https://space.bilibili.com/663528522 11 | */ 12 | @Service 13 | public class ArticleTagServiceImpl extends ServiceImpl implements ArticleTagService { 14 | } 15 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/BlogLoginServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.LoginUser; 5 | import com.sangeng.domain.entity.User; 6 | import com.sangeng.domain.vo.BlogUserLoginVo; 7 | import com.sangeng.domain.vo.UserInfoVo; 8 | import com.sangeng.service.BlogLoginService; 9 | import com.sangeng.utils.BeanCopyUtils; 10 | import com.sangeng.utils.JwtUtil; 11 | import com.sangeng.utils.RedisCache; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.authentication.AuthenticationManager; 14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 15 | import org.springframework.security.core.Authentication; 16 | import org.springframework.security.core.context.SecurityContextHolder; 17 | import org.springframework.stereotype.Service; 18 | 19 | import java.util.Objects; 20 | 21 | @Service 22 | public class BlogLoginServiceImpl implements BlogLoginService { 23 | 24 | @Autowired 25 | private AuthenticationManager authenticationManager; 26 | 27 | @Autowired 28 | private RedisCache redisCache; 29 | 30 | @Override 31 | public ResponseResult login(User user) { 32 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword()); 33 | Authentication authenticate = authenticationManager.authenticate(authenticationToken); 34 | //判断是否认证通过 35 | if(Objects.isNull(authenticate)){ 36 | throw new RuntimeException("用户名或密码错误"); 37 | } 38 | //获取userid 生成token 39 | LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); 40 | String userId = loginUser.getUser().getId().toString(); 41 | String jwt = JwtUtil.createJWT(userId); 42 | //把用户信息存入redis 43 | redisCache.setCacheObject("bloglogin:"+userId,loginUser); 44 | 45 | //把token和userinfo封装 返回 46 | //把User转换成UserInfoVo 47 | UserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class); 48 | BlogUserLoginVo vo = new BlogUserLoginVo(jwt,userInfoVo); 49 | return ResponseResult.okResult(vo); 50 | } 51 | 52 | @Override 53 | public ResponseResult logout() { 54 | //获取token 解析获取userid 55 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 56 | LoginUser loginUser = (LoginUser) authentication.getPrincipal(); 57 | //获取userid 58 | Long userId = loginUser.getUser().getId(); 59 | //删除redis中的用户信息 60 | redisCache.deleteObject("bloglogin:"+userId); 61 | return ResponseResult.okResult(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/CategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.sangeng.constants.SystemConstants; 7 | import com.sangeng.domain.ResponseResult; 8 | import com.sangeng.domain.entity.Article; 9 | import com.sangeng.domain.entity.Category; 10 | import com.sangeng.domain.vo.CategoryVo; 11 | import com.sangeng.domain.vo.PageVo; 12 | import com.sangeng.mapper.CategoryMapper; 13 | import com.sangeng.service.ArticleService; 14 | import com.sangeng.service.CategoryService; 15 | import com.sangeng.utils.BeanCopyUtils; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.util.StringUtils; 19 | 20 | import java.util.List; 21 | import java.util.Objects; 22 | import java.util.Set; 23 | import java.util.function.Function; 24 | import java.util.stream.Collectors; 25 | 26 | /** 27 | * 分类表(Category)表服务实现类 28 | * 29 | * @author makejava 30 | * @since 2022-02-02 12:29:52 31 | */ 32 | @Service("categoryService") 33 | public class CategoryServiceImpl extends ServiceImpl implements CategoryService { 34 | 35 | @Autowired 36 | private ArticleService articleService; 37 | 38 | @Override 39 | public ResponseResult getCategoryList() { 40 | //查询文章表 状态为已发布的文章 41 | LambdaQueryWrapper
articleWrapper = new LambdaQueryWrapper<>(); 42 | articleWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL); 43 | List
articleList = articleService.list(articleWrapper); 44 | //获取文章的分类id,并且去重 45 | Set categoryIds = articleList.stream() 46 | .map(article -> article.getCategoryId()) 47 | .collect(Collectors.toSet()); 48 | 49 | //查询分类表 50 | List categories = listByIds(categoryIds); 51 | categories = categories.stream(). 52 | filter(category -> SystemConstants.STATUS_NORMAL.equals(category.getStatus())) 53 | .collect(Collectors.toList()); 54 | //封装vo 55 | List categoryVos = BeanCopyUtils.copyBeanList(categories, CategoryVo.class); 56 | 57 | return ResponseResult.okResult(categoryVos); 58 | } 59 | 60 | @Override 61 | public List listAllCategory() { 62 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 63 | wrapper.eq(Category::getStatus, SystemConstants.NORMAL); 64 | List list = list(wrapper); 65 | List categoryVos = BeanCopyUtils.copyBeanList(list, CategoryVo.class); 66 | return categoryVos; 67 | } 68 | 69 | @Override 70 | public PageVo selectCategoryPage(Category category, Integer pageNum, Integer pageSize) { 71 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); 72 | 73 | queryWrapper.like(StringUtils.hasText(category.getName()),Category::getName, category.getName()); 74 | queryWrapper.eq(Objects.nonNull(category.getStatus()),Category::getStatus, category.getStatus()); 75 | 76 | Page page = new Page<>(); 77 | page.setCurrent(pageNum); 78 | page.setSize(pageSize); 79 | page(page,queryWrapper); 80 | 81 | //转换成VO 82 | List categories = page.getRecords(); 83 | 84 | PageVo pageVo = new PageVo(); 85 | pageVo.setTotal(page.getTotal()); 86 | pageVo.setRows(categories); 87 | return pageVo; 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/CommentServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.sangeng.constants.SystemConstants; 7 | import com.sangeng.domain.ResponseResult; 8 | import com.sangeng.domain.entity.Comment; 9 | import com.sangeng.domain.vo.CommentVo; 10 | import com.sangeng.domain.vo.PageVo; 11 | import com.sangeng.enums.AppHttpCodeEnum; 12 | import com.sangeng.exception.SystemException; 13 | import com.sangeng.mapper.CommentMapper; 14 | import com.sangeng.service.CommentService; 15 | import com.sangeng.service.UserService; 16 | import com.sangeng.utils.BeanCopyUtils; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.stereotype.Service; 19 | import org.springframework.util.StringUtils; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * 评论表(Comment)表服务实现类 25 | * 26 | * @author makejava 27 | * @since 2022-02-08 23:49:35 28 | */ 29 | @Service("commentService") 30 | public class CommentServiceImpl extends ServiceImpl implements CommentService { 31 | 32 | @Autowired 33 | private UserService userService; 34 | 35 | @Override 36 | public ResponseResult commentList(String commentType, Long articleId, Integer pageNum, Integer pageSize) { 37 | //查询对应文章的根评论 38 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 39 | //对articleId进行判断 40 | queryWrapper.eq(SystemConstants.ARTICLE_COMMENT.equals(commentType),Comment::getArticleId,articleId); 41 | //根评论 rootId为-1 42 | queryWrapper.eq(Comment::getRootId,-1); 43 | 44 | //评论类型 45 | queryWrapper.eq(Comment::getType,commentType); 46 | 47 | //分页查询 48 | Page page = new Page(pageNum,pageSize); 49 | page(page,queryWrapper); 50 | 51 | List commentVoList = toCommentVoList(page.getRecords()); 52 | 53 | //查询所有根评论对应的子评论集合,并且赋值给对应的属性 54 | for (CommentVo commentVo : commentVoList) { 55 | //查询对应的子评论 56 | List children = getChildren(commentVo.getId()); 57 | //赋值 58 | commentVo.setChildren(children); 59 | } 60 | 61 | return ResponseResult.okResult(new PageVo(commentVoList,page.getTotal())); 62 | } 63 | 64 | @Override 65 | public ResponseResult addComment(Comment comment) { 66 | //评论内容不能为空 67 | if(!StringUtils.hasText(comment.getContent())){ 68 | throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL); 69 | } 70 | save(comment); 71 | return ResponseResult.okResult(); 72 | } 73 | 74 | /** 75 | * 根据根评论的id查询所对应的子评论的集合 76 | * @param id 根评论的id 77 | * @return 78 | */ 79 | private List getChildren(Long id) { 80 | 81 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 82 | queryWrapper.eq(Comment::getRootId,id); 83 | queryWrapper.orderByAsc(Comment::getCreateTime); 84 | List comments = list(queryWrapper); 85 | 86 | List commentVos = toCommentVoList(comments); 87 | return commentVos; 88 | } 89 | 90 | private List toCommentVoList(List list){ 91 | List commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class); 92 | //遍历vo集合 93 | for (CommentVo commentVo : commentVos) { 94 | //通过creatyBy查询用户的昵称并赋值 95 | String nickName = userService.getById(commentVo.getCreateBy()).getNickName(); 96 | commentVo.setUsername(nickName); 97 | //通过toCommentUserId查询用户的昵称并赋值 98 | //如果toCommentUserId不为-1才进行查询 99 | if(commentVo.getToCommentUserId()!=-1){ 100 | String toCommentUserName = userService.getById(commentVo.getToCommentUserId()).getNickName(); 101 | commentVo.setToCommentUserName(toCommentUserName); 102 | } 103 | } 104 | return commentVos; 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/LinkServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.sangeng.constants.SystemConstants; 7 | import com.sangeng.domain.ResponseResult; 8 | import com.sangeng.domain.entity.Link; 9 | import com.sangeng.domain.vo.LinkVo; 10 | import com.sangeng.domain.vo.PageVo; 11 | import com.sangeng.mapper.LinkMapper; 12 | import com.sangeng.service.LinkService; 13 | import com.sangeng.utils.BeanCopyUtils; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.util.StringUtils; 16 | 17 | import java.util.List; 18 | import java.util.Objects; 19 | 20 | /** 21 | * 友链(Link)表服务实现类 22 | * 23 | * @author makejava 24 | * @since 2022-02-03 12:22:56 25 | */ 26 | @Service("linkService") 27 | public class LinkServiceImpl extends ServiceImpl implements LinkService { 28 | 29 | @Override 30 | public ResponseResult getAllLink() { 31 | //查询所有审核通过的 32 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 33 | queryWrapper.eq(Link::getStatus, SystemConstants.LINK_STATUS_NORMAL); 34 | List links = list(queryWrapper); 35 | //转换成vo 36 | List linkVos = BeanCopyUtils.copyBeanList(links, LinkVo.class); 37 | //封装返回 38 | return ResponseResult.okResult(linkVos); 39 | } 40 | 41 | @Override 42 | public PageVo selectLinkPage(Link link, Integer pageNum, Integer pageSize) { 43 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); 44 | 45 | queryWrapper.like(StringUtils.hasText(link.getName()),Link::getName, link.getName()); 46 | queryWrapper.eq(Objects.nonNull(link.getStatus()),Link::getStatus, link.getStatus()); 47 | 48 | Page page = new Page<>(); 49 | page.setCurrent(pageNum); 50 | page.setSize(pageSize); 51 | page(page,queryWrapper); 52 | 53 | //转换成VO 54 | List categories = page.getRecords(); 55 | 56 | PageVo pageVo = new PageVo(); 57 | pageVo.setTotal(page.getTotal()); 58 | pageVo.setRows(categories); 59 | return pageVo; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/MenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.sangeng.constants.SystemConstants; 6 | import com.sangeng.domain.entity.Menu; 7 | import com.sangeng.mapper.MenuMapper; 8 | import com.sangeng.service.MenuService; 9 | import com.sangeng.utils.SecurityUtils; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.util.StringUtils; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * 菜单权限表(Menu)表服务实现类 18 | * 19 | * @author makejava 20 | * @since 2022-08-09 22:32:10 21 | */ 22 | @Service("menuService") 23 | public class MenuServiceImpl extends ServiceImpl implements MenuService { 24 | 25 | @Override 26 | public List selectPermsByUserId(Long id) { 27 | //如果是管理员,返回所有的权限 28 | if(SecurityUtils.isAdmin()){ 29 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 30 | wrapper.in(Menu::getMenuType,SystemConstants.MENU,SystemConstants.BUTTON); 31 | wrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL); 32 | List menus = list(wrapper); 33 | List perms = menus.stream() 34 | .map(Menu::getPerms) 35 | .collect(Collectors.toList()); 36 | return perms; 37 | } 38 | //否则返回所具有的权限 39 | return getBaseMapper().selectPermsByUserId(id); 40 | } 41 | 42 | @Override 43 | public List selectRouterMenuTreeByUserId(Long userId) { 44 | MenuMapper menuMapper = getBaseMapper(); 45 | List menus = null; 46 | //判断是否是管理员 47 | if(SecurityUtils.isAdmin()){ 48 | //如果是 获取所有符合要求的Menu 49 | menus = menuMapper.selectAllRouterMenu(); 50 | }else{ 51 | //否则 获取当前用户所具有的Menu 52 | menus = menuMapper.selectRouterMenuTreeByUserId(userId); 53 | } 54 | 55 | //构建tree 56 | //先找出第一层的菜单 然后去找他们的子菜单设置到children属性中 57 | List menuTree = builderMenuTree(menus,0L); 58 | return menuTree; 59 | } 60 | 61 | @Override 62 | public List selectMenuList(Menu menu) { 63 | 64 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 65 | //menuName模糊查询 66 | queryWrapper.like(StringUtils.hasText(menu.getMenuName()),Menu::getMenuName,menu.getMenuName()); 67 | queryWrapper.eq(StringUtils.hasText(menu.getStatus()),Menu::getStatus,menu.getStatus()); 68 | //排序 parent_id和order_num 69 | queryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum); 70 | List menus = list(queryWrapper);; 71 | return menus; 72 | } 73 | 74 | @Override 75 | public boolean hasChild(Long menuId) { 76 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 77 | queryWrapper.eq(Menu::getParentId,menuId); 78 | return count(queryWrapper) != 0; 79 | } 80 | 81 | @Override 82 | public List selectMenuListByRoleId(Long roleId) { 83 | return getBaseMapper().selectMenuListByRoleId(roleId); 84 | } 85 | 86 | private List builderMenuTree(List menus, Long parentId) { 87 | List menuTree = menus.stream() 88 | .filter(menu -> menu.getParentId().equals(parentId)) 89 | .map(menu -> menu.setChildren(getChildren(menu, menus))) 90 | .collect(Collectors.toList()); 91 | return menuTree; 92 | } 93 | 94 | /** 95 | * 获取存入参数的 子Menu集合 96 | * @param menu 97 | * @param menus 98 | * @return 99 | */ 100 | private List getChildren(Menu menu, List menus) { 101 | List childrenList = menus.stream() 102 | .filter(m -> m.getParentId().equals(menu.getId())) 103 | .map(m->m.setChildren(getChildren(m,menus))) 104 | .collect(Collectors.toList()); 105 | return childrenList; 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/OssUploadService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.aliyun.oss.OSS; 4 | import com.aliyun.oss.OSSClientBuilder; 5 | import com.aliyun.oss.model.PutObjectRequest; 6 | import com.aliyun.oss.model.PutObjectResult; 7 | import com.google.gson.Gson; 8 | import com.qiniu.common.QiniuException; 9 | import com.qiniu.http.Response; 10 | import com.qiniu.storage.Configuration; 11 | import com.qiniu.storage.Region; 12 | import com.qiniu.storage.UploadManager; 13 | import com.qiniu.storage.model.DefaultPutRet; 14 | import com.qiniu.util.Auth; 15 | import com.sangeng.domain.ResponseResult; 16 | import com.sangeng.enums.AppHttpCodeEnum; 17 | import com.sangeng.exception.SystemException; 18 | import com.sangeng.service.UploadService; 19 | import com.sangeng.utils.PathUtils; 20 | import lombok.Data; 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | import org.springframework.stereotype.Service; 23 | import org.springframework.web.multipart.MultipartFile; 24 | 25 | import java.io.FileInputStream; 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | 29 | @Service 30 | @Data 31 | @ConfigurationProperties(prefix = "oss") 32 | public class OssUploadService implements UploadService { 33 | @Override 34 | public ResponseResult uploadImg(MultipartFile img) throws IOException { 35 | //判断文件类型 36 | //获取原始文件名 37 | String originalFilename = img.getOriginalFilename(); 38 | //对原始文件名进行判断 39 | if(!originalFilename.endsWith(".png")){ 40 | throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR); 41 | } 42 | 43 | //如果判断通过上传文件到OSS 44 | String filePath = PathUtils.generateFilePath(originalFilename); 45 | // String url = uploadOss(img,filePath);//七牛云 2099/2/3/wqeqeqe.png 46 | String url = uploadFile(filePath,img.getInputStream());//七牛云 2099/2/3/wqeqeqe.png 47 | 48 | 49 | return ResponseResult.okResult(url); 50 | } 51 | 52 | private String accessKey; 53 | private String secretKey; 54 | private String bucket; 55 | 56 | 57 | // private String uploadOss(MultipartFile imgFile, String filePath){ 58 | // //构造一个带指定 Region 对象的配置类 59 | // Configuration cfg = new Configuration(Region.autoRegion()); 60 | // //...其他参数参考类注释 61 | // UploadManager uploadManager = new UploadManager(cfg); 62 | // //默认不指定key的情况下,以文件内容的hash值作为文件名 63 | // String key = filePath; 64 | // try { 65 | // InputStream inputStream = imgFile.getInputStream(); 66 | // Auth auth = Auth.create(accessKey, secretKey); 67 | // String upToken = auth.uploadToken(bucket); 68 | // try { 69 | // Response response = uploadManager.put(inputStream,key,upToken,null, null); 70 | // //解析上传成功的结果 71 | // DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class); 72 | // System.out.println(putRet.key); 73 | // System.out.println(putRet.hash); 74 | // return "http://r7yxkqloa.bkt.clouddn.com/"+key; 75 | // } catch (QiniuException ex) { 76 | // Response r = ex.response; 77 | // System.err.println(r.toString()); 78 | // try { 79 | // System.err.println(r.bodyString()); 80 | // } catch (QiniuException ex2) { 81 | // //ignore 82 | // } 83 | // } 84 | // } catch (Exception ex) { 85 | // //ignore 86 | // } 87 | // return "www"; 88 | // } 89 | 90 | private String uploadFile(String filePath, InputStream inputStream) { 91 | // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 92 | String endpoint = "oss-cn-beijing.aliyuncs.com"; 93 | 94 | // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 95 | String accessKeyId = "weqeq"; 96 | String accessKeySecret = "wqeqrqrqwe"; 97 | String bucketName = "sg-blog-oss"; 98 | // 创建OSSClient实例。 99 | OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); 100 | // 创建PutObjectRequest对象。 101 | // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。 102 | PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream); 103 | 104 | // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。 105 | // ObjectMetadata metadata = new ObjectMetadata(); 106 | // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); 107 | // metadata.setObjectAcl(CannedAccessControlList.Private); 108 | // putObjectRequest.setMetadata(metadata); 109 | 110 | // 上传字符串。 111 | PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest); 112 | 113 | // 关闭OSSClient。 114 | ossClient.shutdown(); 115 | return "https://"+bucketName+"."+endpoint+"/"+filePath; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/PermissionService.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.sangeng.utils.SecurityUtils; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | @Service("ps") 9 | public class PermissionService { 10 | 11 | /** 12 | * 判断当前用户是否具有permission 13 | * @param permission 要判断的权限 14 | * @return 15 | */ 16 | public boolean hasPermission(String permission){ 17 | //如果是超级管理员 直接返回true 18 | if(SecurityUtils.isAdmin()){ 19 | return true; 20 | } 21 | //否则 获取当前登录用户所具有的权限列表 如何判断是否存在permission 22 | List permissions = SecurityUtils.getLoginUser().getPermissions(); 23 | return permissions.contains(permission); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/RoleMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.sangeng.domain.entity.RoleMenu; 6 | import com.sangeng.mapper.RoleMenuMapper; 7 | import com.sangeng.service.RoleMenuService; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @Author 三更 B站: https://space.bilibili.com/663528522 12 | */ 13 | @Service 14 | public class RoleMenuServiceImpl extends ServiceImpl implements RoleMenuService { 15 | 16 | @Override 17 | public void deleteRoleMenuByRoleId(Long id) { 18 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 19 | queryWrapper.eq(RoleMenu::getRoleId,id); 20 | remove(queryWrapper); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/RoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.sangeng.constants.SystemConstants; 8 | import com.sangeng.domain.ResponseResult; 9 | import com.sangeng.domain.entity.Role; 10 | import com.sangeng.domain.entity.RoleMenu; 11 | import com.sangeng.domain.vo.PageVo; 12 | import com.sangeng.mapper.RoleMapper; 13 | import com.sangeng.service.RoleMenuService; 14 | import com.sangeng.service.RoleService; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | import org.springframework.util.StringUtils; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * 角色信息表(Role)表服务实现类 27 | * 28 | * @author makejava 29 | * @since 2022-08-09 22:36:47 30 | */ 31 | @Service("roleService") 32 | public class RoleServiceImpl extends ServiceImpl implements RoleService { 33 | @Autowired 34 | private RoleMenuService roleMenuService; 35 | @Override 36 | public List selectRoleKeyByUserId(Long id) { 37 | //判断是否是管理员 如果是返回集合中只需要有admin 38 | if(id == 1L){ 39 | List roleKeys = new ArrayList<>(); 40 | roleKeys.add("admin"); 41 | return roleKeys; 42 | } 43 | //否则查询用户所具有的角色信息 44 | return getBaseMapper().selectRoleKeyByUserId(id); 45 | } 46 | 47 | @Override 48 | public ResponseResult selectRolePage(Role role, Integer pageNum, Integer pageSize) { 49 | LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); 50 | //目前没有根据id查询 51 | // lambdaQueryWrapper.eq(Objects.nonNull(role.getId()),Role::getId,role.getId()); 52 | lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName()); 53 | lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus()); 54 | lambdaQueryWrapper.orderByAsc(Role::getRoleSort); 55 | 56 | Page page = new Page<>(); 57 | page.setCurrent(pageNum); 58 | page.setSize(pageSize); 59 | page(page,lambdaQueryWrapper); 60 | 61 | //转换成VO 62 | List roles = page.getRecords(); 63 | 64 | PageVo pageVo = new PageVo(); 65 | pageVo.setTotal(page.getTotal()); 66 | pageVo.setRows(roles); 67 | return ResponseResult.okResult(pageVo); 68 | } 69 | 70 | @Override 71 | @Transactional 72 | public void insertRole(Role role) { 73 | save(role); 74 | System.out.println(role.getId()); 75 | if(role.getMenuIds()!=null&&role.getMenuIds().length>0){ 76 | insertRoleMenu(role); 77 | } 78 | } 79 | 80 | @Override 81 | public void updateRole(Role role) { 82 | updateById(role); 83 | roleMenuService.deleteRoleMenuByRoleId(role.getId()); 84 | insertRoleMenu(role); 85 | } 86 | 87 | @Override 88 | public List selectRoleAll() { 89 | return list(Wrappers.lambdaQuery().eq(Role::getStatus, SystemConstants.NORMAL)); 90 | } 91 | 92 | @Override 93 | public List selectRoleIdByUserId(Long userId) { 94 | return getBaseMapper().selectRoleIdByUserId(userId); 95 | } 96 | 97 | private void insertRoleMenu(Role role) { 98 | List roleMenuList = Arrays.stream(role.getMenuIds()) 99 | .map(memuId -> new RoleMenu(role.getId(), memuId)) 100 | .collect(Collectors.toList()); 101 | roleMenuService.saveBatch(roleMenuList); 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/SystemLoginServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.sangeng.domain.ResponseResult; 4 | import com.sangeng.domain.entity.LoginUser; 5 | import com.sangeng.domain.entity.User; 6 | import com.sangeng.domain.vo.BlogUserLoginVo; 7 | import com.sangeng.domain.vo.UserInfoVo; 8 | import com.sangeng.service.BlogLoginService; 9 | import com.sangeng.service.LoginService; 10 | import com.sangeng.utils.BeanCopyUtils; 11 | import com.sangeng.utils.JwtUtil; 12 | import com.sangeng.utils.RedisCache; 13 | import com.sangeng.utils.SecurityUtils; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.authentication.AuthenticationManager; 16 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 17 | import org.springframework.security.core.Authentication; 18 | import org.springframework.security.core.context.SecurityContextHolder; 19 | import org.springframework.stereotype.Service; 20 | 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | import java.util.Objects; 24 | 25 | @Service 26 | public class SystemLoginServiceImpl implements LoginService { 27 | 28 | @Autowired 29 | private AuthenticationManager authenticationManager; 30 | 31 | @Autowired 32 | private RedisCache redisCache; 33 | 34 | @Override 35 | public ResponseResult login(User user) { 36 | UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword()); 37 | Authentication authenticate = authenticationManager.authenticate(authenticationToken); 38 | //判断是否认证通过 39 | if(Objects.isNull(authenticate)){ 40 | throw new RuntimeException("用户名或密码错误"); 41 | } 42 | //获取userid 生成token 43 | LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); 44 | String userId = loginUser.getUser().getId().toString(); 45 | String jwt = JwtUtil.createJWT(userId); 46 | //把用户信息存入redis 47 | redisCache.setCacheObject("login:"+userId,loginUser); 48 | 49 | //把token封装 返回 50 | Map map = new HashMap<>(); 51 | map.put("token",jwt); 52 | return ResponseResult.okResult(map); 53 | } 54 | 55 | @Override 56 | public ResponseResult logout() { 57 | //获取当前登录的用户id 58 | Long userId = SecurityUtils.getUserId(); 59 | //删除redis中对应的值 60 | redisCache.deleteObject("login:"+userId); 61 | return ResponseResult.okResult(); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/TagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.sangeng.domain.ResponseResult; 7 | import com.sangeng.domain.dto.TagListDto; 8 | import com.sangeng.domain.entity.Tag; 9 | import com.sangeng.domain.vo.PageVo; 10 | import com.sangeng.domain.vo.TagVo; 11 | import com.sangeng.mapper.TagMapper; 12 | import com.sangeng.service.TagService; 13 | import com.sangeng.utils.BeanCopyUtils; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.util.StringUtils; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 标签(Tag)表服务实现类 21 | * 22 | * @author makejava 23 | * @since 2022-07-19 22:33:38 24 | */ 25 | @Service("tagService") 26 | public class TagServiceImpl extends ServiceImpl implements TagService { 27 | 28 | @Override 29 | public ResponseResult pageTagList(Integer pageNum, Integer pageSize, TagListDto tagListDto) { 30 | //分页查询 31 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 32 | queryWrapper.eq(StringUtils.hasText(tagListDto.getName()),Tag::getName,tagListDto.getName()); 33 | queryWrapper.eq(StringUtils.hasText(tagListDto.getRemark()),Tag::getRemark,tagListDto.getRemark()); 34 | 35 | Page page = new Page<>(); 36 | page.setCurrent(pageNum); 37 | page.setSize(pageSize); 38 | page(page, queryWrapper); 39 | //封装数据返回 40 | PageVo pageVo = new PageVo(page.getRecords(),page.getTotal()); 41 | return ResponseResult.okResult(pageVo); 42 | } 43 | 44 | @Override 45 | public List listAllTag() { 46 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 47 | wrapper.select(Tag::getId,Tag::getName); 48 | List list = list(wrapper); 49 | List tagVos = BeanCopyUtils.copyBeanList(list, TagVo.class); 50 | return tagVos; 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.sangeng.constants.SystemConstants; 5 | import com.sangeng.domain.entity.LoginUser; 6 | import com.sangeng.domain.entity.User; 7 | import com.sangeng.mapper.MenuMapper; 8 | import com.sangeng.mapper.UserMapper; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | import java.util.Objects; 17 | 18 | @Service 19 | public class UserDetailsServiceImpl implements UserDetailsService { 20 | 21 | @Autowired 22 | private UserMapper userMapper; 23 | 24 | @Autowired 25 | private MenuMapper menuMapper; 26 | 27 | @Override 28 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 29 | //根据用户名查询用户信息 30 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 31 | queryWrapper.eq(User::getUserName,username); 32 | User user = userMapper.selectOne(queryWrapper); 33 | //判断是否查到用户 如果没查到抛出异常 34 | if(Objects.isNull(user)){ 35 | throw new RuntimeException("用户不存在"); 36 | } 37 | //返回用户信息 38 | if(user.getType().equals(SystemConstants.ADMAIN)){ 39 | List list = menuMapper.selectPermsByUserId(user.getId()); 40 | return new LoginUser(user,list); 41 | } 42 | return new LoginUser(user,null); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/UserRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.sangeng.domain.entity.UserRole; 5 | import com.sangeng.mapper.UserRoleMapper; 6 | import com.sangeng.service.UserRoleService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @Author 三更 B站: https://space.bilibili.com/663528522 11 | */ 12 | @Service 13 | public class UserRoleServiceImpl extends ServiceImpl implements UserRoleService { 14 | } 15 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.sangeng.domain.ResponseResult; 8 | import com.sangeng.domain.entity.User; 9 | import com.sangeng.domain.entity.UserRole; 10 | import com.sangeng.domain.vo.PageVo; 11 | import com.sangeng.domain.vo.UserInfoVo; 12 | import com.sangeng.domain.vo.UserVo; 13 | import com.sangeng.enums.AppHttpCodeEnum; 14 | import com.sangeng.exception.SystemException; 15 | import com.sangeng.mapper.UserMapper; 16 | import com.sangeng.service.UserRoleService; 17 | import com.sangeng.service.UserService; 18 | import com.sangeng.utils.BeanCopyUtils; 19 | import com.sangeng.utils.SecurityUtils; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.security.crypto.password.PasswordEncoder; 22 | import org.springframework.stereotype.Service; 23 | import org.springframework.transaction.annotation.Transactional; 24 | import org.springframework.util.StringUtils; 25 | 26 | import java.util.Arrays; 27 | import java.util.List; 28 | import java.util.Objects; 29 | import java.util.stream.Collectors; 30 | 31 | /** 32 | * 用户表(User)表服务实现类 33 | * 34 | * @author makejava 35 | * @since 2022-02-09 00:28:30 36 | */ 37 | @Service("userService") 38 | public class UserServiceImpl extends ServiceImpl implements UserService { 39 | 40 | @Override 41 | public ResponseResult userInfo() { 42 | //获取当前用户id 43 | Long userId = SecurityUtils.getUserId(); 44 | //根据用户id查询用户信息 45 | User user = getById(userId); 46 | //封装成UserInfoVo 47 | UserInfoVo vo = BeanCopyUtils.copyBean(user,UserInfoVo.class); 48 | return ResponseResult.okResult(vo); 49 | } 50 | 51 | @Override 52 | public ResponseResult updateUserInfo(User user) { 53 | updateById(user); 54 | return ResponseResult.okResult(); 55 | } 56 | 57 | @Autowired 58 | private PasswordEncoder passwordEncoder; 59 | @Override 60 | public ResponseResult register(User user) { 61 | //对数据进行非空判断 62 | if(!StringUtils.hasText(user.getUserName())){ 63 | throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL); 64 | } 65 | if(!StringUtils.hasText(user.getPassword())){ 66 | throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL); 67 | } 68 | if(!StringUtils.hasText(user.getEmail())){ 69 | throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL); 70 | } 71 | if(!StringUtils.hasText(user.getNickName())){ 72 | throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL); 73 | } 74 | //对数据进行是否存在的判断 75 | if(userNameExist(user.getUserName())){ 76 | throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST); 77 | } 78 | if(nickNameExist(user.getNickName())){ 79 | throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST); 80 | } 81 | //... 82 | //对密码进行加密 83 | String encodePassword = passwordEncoder.encode(user.getPassword()); 84 | user.setPassword(encodePassword); 85 | //存入数据库 86 | save(user); 87 | return ResponseResult.okResult(); 88 | } 89 | 90 | @Override 91 | public ResponseResult selectUserPage(User user, Integer pageNum, Integer pageSize) { 92 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); 93 | 94 | queryWrapper.like(StringUtils.hasText(user.getUserName()),User::getUserName,user.getUserName()); 95 | queryWrapper.eq(StringUtils.hasText(user.getStatus()),User::getStatus,user.getStatus()); 96 | queryWrapper.eq(StringUtils.hasText(user.getPhonenumber()),User::getPhonenumber,user.getPhonenumber()); 97 | 98 | Page page = new Page<>(); 99 | page.setCurrent(pageNum); 100 | page.setSize(pageSize); 101 | page(page,queryWrapper); 102 | 103 | //转换成VO 104 | List users = page.getRecords(); 105 | List userVoList = users.stream() 106 | .map(u -> BeanCopyUtils.copyBean(u, UserVo.class)) 107 | .collect(Collectors.toList()); 108 | PageVo pageVo = new PageVo(); 109 | pageVo.setTotal(page.getTotal()); 110 | pageVo.setRows(userVoList); 111 | return ResponseResult.okResult(pageVo); 112 | } 113 | 114 | @Override 115 | public boolean checkUserNameUnique(String userName) { 116 | return count(Wrappers.lambdaQuery().eq(User::getUserName,userName))==0; 117 | } 118 | 119 | @Override 120 | public boolean checkPhoneUnique(User user) { 121 | return count(Wrappers.lambdaQuery().eq(User::getPhonenumber,user.getPhonenumber()))==0; 122 | } 123 | 124 | @Override 125 | public boolean checkEmailUnique(User user) { 126 | return count(Wrappers.lambdaQuery().eq(User::getEmail,user.getEmail()))==0; 127 | } 128 | 129 | @Override 130 | @Transactional 131 | public ResponseResult addUser(User user) { 132 | //密码加密处理 133 | user.setPassword(passwordEncoder.encode(user.getPassword())); 134 | save(user); 135 | 136 | if(user.getRoleIds()!=null&&user.getRoleIds().length>0){ 137 | insertUserRole(user); 138 | } 139 | return ResponseResult.okResult(); 140 | } 141 | 142 | @Override 143 | @Transactional 144 | public void updateUser(User user) { 145 | // 删除用户与角色关联 146 | LambdaQueryWrapper userRoleUpdateWrapper = new LambdaQueryWrapper<>(); 147 | userRoleUpdateWrapper.eq(UserRole::getUserId,user.getId()); 148 | userRoleService.remove(userRoleUpdateWrapper); 149 | 150 | // 新增用户与角色管理 151 | insertUserRole(user); 152 | // 更新用户信息 153 | updateById(user); 154 | } 155 | 156 | @Autowired 157 | private UserRoleService userRoleService; 158 | 159 | private void insertUserRole(User user) { 160 | List sysUserRoles = Arrays.stream(user.getRoleIds()) 161 | .map(roleId -> new UserRole(user.getId(), roleId)).collect(Collectors.toList()); 162 | userRoleService.saveBatch(sysUserRoles); 163 | } 164 | 165 | private boolean nickNameExist(String nickName) { 166 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 167 | queryWrapper.eq(User::getNickName,nickName); 168 | return count(queryWrapper)>0; 169 | } 170 | 171 | private boolean userNameExist(String userName) { 172 | LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); 173 | queryWrapper.eq(User::getUserName,userName); 174 | return count(queryWrapper)>0; 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/BeanCopyUtils.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import com.sangeng.domain.entity.Article; 4 | import com.sangeng.domain.vo.HotArticleVo; 5 | import org.springframework.beans.BeanUtils; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | public class BeanCopyUtils { 11 | 12 | private BeanCopyUtils() { 13 | } 14 | 15 | public static V copyBean(Object source,Class clazz) { 16 | //创建目标对象 17 | V result = null; 18 | try { 19 | result = clazz.newInstance(); 20 | //实现属性copy 21 | BeanUtils.copyProperties(source, result); 22 | } catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | //返回结果 26 | return result; 27 | } 28 | public static List copyBeanList(List list,Class clazz){ 29 | return list.stream() 30 | .map(o -> copyBean(o, clazz)) 31 | .collect(Collectors.toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.JwtBuilder; 5 | import io.jsonwebtoken.Jwts; 6 | import io.jsonwebtoken.SignatureAlgorithm; 7 | 8 | import javax.crypto.SecretKey; 9 | import javax.crypto.spec.SecretKeySpec; 10 | import java.util.Base64; 11 | import java.util.Date; 12 | import java.util.UUID; 13 | 14 | /** 15 | * JWT工具类 16 | */ 17 | public class JwtUtil { 18 | 19 | //有效期为 20 | public static final Long JWT_TTL = 24*60 * 60 *1000L;// 60 * 60 *1000 一个小时 21 | //设置秘钥明文 22 | public static final String JWT_KEY = "sangeng"; 23 | 24 | public static String getUUID(){ 25 | String token = UUID.randomUUID().toString().replaceAll("-", ""); 26 | return token; 27 | } 28 | 29 | /** 30 | * 生成jtw 31 | * @param subject token中要存放的数据(json格式) 32 | * @return 33 | */ 34 | public static String createJWT(String subject) { 35 | JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间 36 | return builder.compact(); 37 | } 38 | 39 | /** 40 | * 生成jtw 41 | * @param subject token中要存放的数据(json格式) 42 | * @param ttlMillis token超时时间 43 | * @return 44 | */ 45 | public static String createJWT(String subject, Long ttlMillis) { 46 | JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间 47 | return builder.compact(); 48 | } 49 | 50 | private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { 51 | SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; 52 | SecretKey secretKey = generalKey(); 53 | long nowMillis = System.currentTimeMillis(); 54 | Date now = new Date(nowMillis); 55 | if(ttlMillis==null){ 56 | ttlMillis=JwtUtil.JWT_TTL; 57 | } 58 | long expMillis = nowMillis + ttlMillis; 59 | Date expDate = new Date(expMillis); 60 | return Jwts.builder() 61 | .setId(uuid) //唯一的ID 62 | .setSubject(subject) // 主题 可以是JSON数据 63 | .setIssuer("sg") // 签发者 64 | .setIssuedAt(now) // 签发时间 65 | .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥 66 | .setExpiration(expDate); 67 | } 68 | 69 | /** 70 | * 创建token 71 | * @param id 72 | * @param subject 73 | * @param ttlMillis 74 | * @return 75 | */ 76 | public static String createJWT(String id, String subject, Long ttlMillis) { 77 | JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间 78 | return builder.compact(); 79 | } 80 | 81 | public static void main(String[] args) throws Exception { 82 | String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg"; 83 | Claims claims = parseJWT(token); 84 | System.out.println(claims); 85 | } 86 | 87 | /** 88 | * 生成加密后的秘钥 secretKey 89 | * @return 90 | */ 91 | public static SecretKey generalKey() { 92 | byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); 93 | SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); 94 | return key; 95 | } 96 | 97 | /** 98 | * 解析 99 | * 100 | * @param jwt 101 | * @return 102 | * @throws Exception 103 | */ 104 | public static Claims parseJWT(String jwt) throws Exception { 105 | SecretKey secretKey = generalKey(); 106 | return Jwts.parser() 107 | .setSigningKey(secretKey) 108 | .parseClaimsJws(jwt) 109 | .getBody(); 110 | } 111 | 112 | 113 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/PathUtils.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.UUID; 6 | 7 | /** 8 | * @Author 三更 B站: https://space.bilibili.com/663528522 9 | */ 10 | public class PathUtils { 11 | 12 | public static String generateFilePath(String fileName){ 13 | //根据日期生成路径 2022/1/15/ 14 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/"); 15 | String datePath = sdf.format(new Date()); 16 | //uuid作为文件名 17 | String uuid = UUID.randomUUID().toString().replaceAll("-", ""); 18 | //后缀和文件后缀一致 19 | int index = fileName.lastIndexOf("."); 20 | // test.jpg -> .jpg 21 | String fileType = fileName.substring(index); 22 | return new StringBuilder().append(datePath).append(uuid).append(fileType).toString(); 23 | } 24 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/RedisCache.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.BoundSetOperations; 5 | import org.springframework.data.redis.core.HashOperations; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.core.ValueOperations; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.*; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @SuppressWarnings(value = { "unchecked", "rawtypes" }) 14 | @Component 15 | public class RedisCache 16 | { 17 | @Autowired 18 | public RedisTemplate redisTemplate; 19 | 20 | /** 21 | * 缓存基本的对象,Integer、String、实体类等 22 | * 23 | * @param key 缓存的键值 24 | * @param value 缓存的值 25 | */ 26 | public void setCacheObject(final String key, final T value) 27 | { 28 | redisTemplate.opsForValue().set(key, value); 29 | } 30 | 31 | /** 32 | * 缓存基本的对象,Integer、String、实体类等 33 | * 34 | * @param key 缓存的键值 35 | * @param value 缓存的值 36 | * @param timeout 时间 37 | * @param timeUnit 时间颗粒度 38 | */ 39 | public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) 40 | { 41 | redisTemplate.opsForValue().set(key, value, timeout, timeUnit); 42 | } 43 | 44 | /** 45 | * 设置有效时间 46 | * 47 | * @param key Redis键 48 | * @param timeout 超时时间 49 | * @return true=设置成功;false=设置失败 50 | */ 51 | public boolean expire(final String key, final long timeout) 52 | { 53 | return expire(key, timeout, TimeUnit.SECONDS); 54 | } 55 | 56 | /** 57 | * 设置有效时间 58 | * 59 | * @param key Redis键 60 | * @param timeout 超时时间 61 | * @param unit 时间单位 62 | * @return true=设置成功;false=设置失败 63 | */ 64 | public boolean expire(final String key, final long timeout, final TimeUnit unit) 65 | { 66 | return redisTemplate.expire(key, timeout, unit); 67 | } 68 | 69 | /** 70 | * 获得缓存的基本对象。 71 | * 72 | * @param key 缓存键值 73 | * @return 缓存键值对应的数据 74 | */ 75 | public T getCacheObject(final String key) 76 | { 77 | ValueOperations operation = redisTemplate.opsForValue(); 78 | return operation.get(key); 79 | } 80 | 81 | /** 82 | * 删除单个对象 83 | * 84 | * @param key 85 | */ 86 | public boolean deleteObject(final String key) 87 | { 88 | return redisTemplate.delete(key); 89 | } 90 | 91 | /** 92 | * 删除集合对象 93 | * 94 | * @param collection 多个对象 95 | * @return 96 | */ 97 | public long deleteObject(final Collection collection) 98 | { 99 | return redisTemplate.delete(collection); 100 | } 101 | 102 | /** 103 | * 缓存List数据 104 | * 105 | * @param key 缓存的键值 106 | * @param dataList 待缓存的List数据 107 | * @return 缓存的对象 108 | */ 109 | public long setCacheList(final String key, final List dataList) 110 | { 111 | Long count = redisTemplate.opsForList().rightPushAll(key, dataList); 112 | return count == null ? 0 : count; 113 | } 114 | 115 | /** 116 | * 获得缓存的list对象 117 | * 118 | * @param key 缓存的键值 119 | * @return 缓存键值对应的数据 120 | */ 121 | public List getCacheList(final String key) 122 | { 123 | return redisTemplate.opsForList().range(key, 0, -1); 124 | } 125 | 126 | /** 127 | * 缓存Set 128 | * 129 | * @param key 缓存键值 130 | * @param dataSet 缓存的数据 131 | * @return 缓存数据的对象 132 | */ 133 | public BoundSetOperations setCacheSet(final String key, final Set dataSet) 134 | { 135 | BoundSetOperations setOperation = redisTemplate.boundSetOps(key); 136 | Iterator it = dataSet.iterator(); 137 | while (it.hasNext()) 138 | { 139 | setOperation.add(it.next()); 140 | } 141 | return setOperation; 142 | } 143 | 144 | /** 145 | * 获得缓存的set 146 | * 147 | * @param key 148 | * @return 149 | */ 150 | public Set getCacheSet(final String key) 151 | { 152 | return redisTemplate.opsForSet().members(key); 153 | } 154 | 155 | /** 156 | * 缓存Map 157 | * 158 | * @param key 159 | * @param dataMap 160 | */ 161 | public void setCacheMap(final String key, final Map dataMap) 162 | { 163 | if (dataMap != null) { 164 | redisTemplate.opsForHash().putAll(key, dataMap); 165 | } 166 | } 167 | 168 | /** 169 | * 获得缓存的Map 170 | * 171 | * @param key 172 | * @return 173 | */ 174 | public Map getCacheMap(final String key) 175 | { 176 | return redisTemplate.opsForHash().entries(key); 177 | } 178 | 179 | /** 180 | * 往Hash中存入数据 181 | * 182 | * @param key Redis键 183 | * @param hKey Hash键 184 | * @param value 值 185 | */ 186 | public void setCacheMapValue(final String key, final String hKey, final T value) 187 | { 188 | redisTemplate.opsForHash().put(key, hKey, value); 189 | } 190 | 191 | /** 192 | * 获取Hash中的数据 193 | * 194 | * @param key Redis键 195 | * @param hKey Hash键 196 | * @return Hash中的对象 197 | */ 198 | public T getCacheMapValue(final String key, final String hKey) 199 | { 200 | HashOperations opsForHash = redisTemplate.opsForHash(); 201 | return opsForHash.get(key, hKey); 202 | } 203 | 204 | 205 | public void incrementCacheMapValue(String key,String hKey,int v){ 206 | redisTemplate.opsForHash().increment(key,hKey,v); 207 | } 208 | 209 | /** 210 | * 删除Hash中的数据 211 | * 212 | * @param key 213 | * @param hkey 214 | */ 215 | public void delCacheMapValue(final String key, final String hkey) 216 | { 217 | HashOperations hashOperations = redisTemplate.opsForHash(); 218 | hashOperations.delete(key, hkey); 219 | } 220 | 221 | /** 222 | * 获取多个Hash中的数据 223 | * 224 | * @param key Redis键 225 | * @param hKeys Hash键集合 226 | * @return Hash对象集合 227 | */ 228 | public List getMultiCacheMapValue(final String key, final Collection hKeys) 229 | { 230 | return redisTemplate.opsForHash().multiGet(key, hKeys); 231 | } 232 | 233 | /** 234 | * 获得缓存的基本对象列表 235 | * 236 | * @param pattern 字符串前缀 237 | * @return 对象列表 238 | */ 239 | public Collection keys(final String pattern) 240 | { 241 | return redisTemplate.keys(pattern); 242 | } 243 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import com.sangeng.domain.entity.LoginUser; 4 | import org.springframework.security.core.Authentication; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | 7 | /** 8 | * @Author 三更 B站: https://space.bilibili.com/663528522 9 | */ 10 | public class SecurityUtils 11 | { 12 | 13 | /** 14 | * 获取用户 15 | **/ 16 | public static LoginUser getLoginUser() 17 | { 18 | return (LoginUser) getAuthentication().getPrincipal(); 19 | } 20 | 21 | /** 22 | * 获取Authentication 23 | */ 24 | public static Authentication getAuthentication() { 25 | return SecurityContextHolder.getContext().getAuthentication(); 26 | } 27 | 28 | public static Boolean isAdmin(){ 29 | Long id = getLoginUser().getUser().getId(); 30 | return id != null && id.equals(1L); 31 | } 32 | 33 | public static Long getUserId() { 34 | return getLoginUser().getUser().getId(); 35 | } 36 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/SystemConverter.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | 4 | import com.sangeng.domain.entity.Menu; 5 | import com.sangeng.domain.vo.MenuTreeVo; 6 | import org.springframework.util.StringUtils; 7 | 8 | import java.util.ArrayList; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | import java.util.Objects; 12 | import java.util.stream.Collectors; 13 | 14 | /** 15 | * @Author 三更 B站: https://space.bilibili.com/663528522 16 | */ 17 | public class SystemConverter { 18 | 19 | private SystemConverter() { 20 | } 21 | 22 | 23 | public static List buildMenuSelectTree(List menus) { 24 | List MenuTreeVos = menus.stream() 25 | .map(m -> new MenuTreeVo(m.getId(), m.getMenuName(), m.getParentId(), null)) 26 | .collect(Collectors.toList()); 27 | List options = MenuTreeVos.stream() 28 | .filter(o -> o.getParentId().equals(0L)) 29 | .map(o -> o.setChildren(getChildList(MenuTreeVos, o))) 30 | .collect(Collectors.toList()); 31 | 32 | 33 | return options; 34 | } 35 | 36 | 37 | /** 38 | * 得到子节点列表 39 | */ 40 | private static List getChildList(List list, MenuTreeVo option) { 41 | List options = list.stream() 42 | .filter(o -> Objects.equals(o.getParentId(), option.getId())) 43 | .map(o -> o.setChildren(getChildList(list, o))) 44 | .collect(Collectors.toList()); 45 | return options; 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/java/com/sangeng/utils/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.sangeng.utils; 2 | 3 | import org.springframework.web.context.request.RequestContextHolder; 4 | 5 | import javax.servlet.ServletContext; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.URLEncoder; 10 | 11 | public class WebUtils 12 | { 13 | /** 14 | * 将字符串渲染到客户端 15 | * 16 | * @param response 渲染对象 17 | * @param string 待渲染的字符串 18 | * @return null 19 | */ 20 | public static void renderString(HttpServletResponse response, String string) { 21 | try 22 | { 23 | response.setStatus(200); 24 | response.setContentType("application/json"); 25 | response.setCharacterEncoding("utf-8"); 26 | response.getWriter().print(string); 27 | } 28 | catch (IOException e) 29 | { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | public static void setDownLoadHeader(String filename, HttpServletResponse response) throws UnsupportedEncodingException { 35 | response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 36 | response.setCharacterEncoding("utf-8"); 37 | String fname= URLEncoder.encode(filename,"UTF-8").replaceAll("\\+", "%20"); 38 | response.setHeader("Content-disposition","attachment; filename="+fname); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /sangeng-framework/src/main/resources/mapper/MenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 30 | 45 | 54 | 55 | -------------------------------------------------------------------------------- /sangeng-framework/src/main/resources/mapper/RoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 21 | --------------------------------------------------------------------------------