├── vueadmin-vue
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── assets
│ │ ├── logo.png
│ │ └── MarkerHub.jpg
│ ├── views
│ │ ├── Index.vue
│ │ ├── inc
│ │ │ ├── SideMenu.vue
│ │ │ └── Tabs.vue
│ │ ├── Home.vue
│ │ ├── UserCenter.vue
│ │ ├── Login.vue
│ │ └── sys
│ │ │ ├── Menu.vue
│ │ │ ├── Role.vue
│ │ │ └── User.vue
│ ├── globalFun.js
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ └── menus.js
│ ├── main.js
│ ├── App.vue
│ ├── axios.js
│ ├── router
│ │ └── index.js
│ └── mock.js
├── babel.config.js
├── README.md
└── package.json
├── vueadmin-java
├── Dockerfile
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── mapper
│ │ │ │ ├── SysMenuMapper.xml
│ │ │ │ ├── SysRoleMapper.xml
│ │ │ │ ├── SysRoleMenuMapper.xml
│ │ │ │ ├── SysUserRoleMapper.xml
│ │ │ │ └── SysUserMapper.xml
│ │ │ └── application.yml
│ │ └── java
│ │ │ └── com
│ │ │ └── markerhub
│ │ │ ├── common
│ │ │ ├── exception
│ │ │ │ ├── CaptchaException.java
│ │ │ │ └── GlobalExceptionHandler.java
│ │ │ ├── dto
│ │ │ │ ├── PassDto.java
│ │ │ │ └── SysMenuDto.java
│ │ │ └── lang
│ │ │ │ ├── Const.java
│ │ │ │ └── Result.java
│ │ │ ├── mapper
│ │ │ ├── SysMenuMapper.java
│ │ │ ├── SysRoleMapper.java
│ │ │ ├── SysRoleMenuMapper.java
│ │ │ ├── SysUserRoleMapper.java
│ │ │ └── SysUserMapper.java
│ │ │ ├── service
│ │ │ ├── SysRoleMenuService.java
│ │ │ ├── SysUserRoleService.java
│ │ │ ├── SysRoleService.java
│ │ │ ├── SysMenuService.java
│ │ │ ├── impl
│ │ │ │ ├── SysRoleMenuServiceImpl.java
│ │ │ │ ├── SysUserRoleServiceImpl.java
│ │ │ │ ├── SysRoleServiceImpl.java
│ │ │ │ ├── SysMenuServiceImpl.java
│ │ │ │ └── SysUserServiceImpl.java
│ │ │ └── SysUserService.java
│ │ │ ├── VueadminJavaApplication.java
│ │ │ ├── entity
│ │ │ ├── BaseEntity.java
│ │ │ ├── SysUserRole.java
│ │ │ ├── SysRoleMenu.java
│ │ │ ├── SysRole.java
│ │ │ ├── SysUser.java
│ │ │ └── SysMenu.java
│ │ │ ├── config
│ │ │ ├── KaptchaConfig.java
│ │ │ ├── MybatisPlusConfig.java
│ │ │ ├── RedisConfig.java
│ │ │ ├── CorsConfig.java
│ │ │ └── SecurityConfig.java
│ │ │ ├── controller
│ │ │ ├── BaseController.java
│ │ │ ├── TestController.java
│ │ │ ├── AuthController.java
│ │ │ ├── SysMenuController.java
│ │ │ ├── SysRoleController.java
│ │ │ └── SysUserController.java
│ │ │ ├── security
│ │ │ ├── LoginFailureHandler.java
│ │ │ ├── JwtAuthenticationEntryPoint.java
│ │ │ ├── JwtAccessDeniedHandler.java
│ │ │ ├── LoginSuccessHandler.java
│ │ │ ├── JwtLogoutSuccessHandler.java
│ │ │ ├── UserDetailServiceImpl.java
│ │ │ ├── CaptchaFilter.java
│ │ │ ├── JwtAuthenticationFilter.java
│ │ │ └── AccountUser.java
│ │ │ ├── utils
│ │ │ ├── JwtUtils.java
│ │ │ └── RedisUtil.java
│ │ │ └── CodeGenerator.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── markerhub
│ │ └── VueadminJavaApplicationTests.java
├── docker-compose.yml
├── pom.xml
└── 数据库脚本 - vueadmin.sql
├── .gitignore
└── README.md
/vueadmin-vue/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkerHub/VueAdmin/HEAD/vueadmin-vue/public/favicon.ico
--------------------------------------------------------------------------------
/vueadmin-vue/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkerHub/VueAdmin/HEAD/vueadmin-vue/src/assets/logo.png
--------------------------------------------------------------------------------
/vueadmin-vue/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/assets/MarkerHub.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkerHub/VueAdmin/HEAD/vueadmin-vue/src/assets/MarkerHub.jpg
--------------------------------------------------------------------------------
/vueadmin-java/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:8
2 |
3 | EXPOSE 8085
4 |
5 | ADD vueadmin-java-0.0.1-SNAPSHOT.jar app.jar
6 | RUN bash -c 'touch /app.jar'
7 |
8 | ENTRYPOINT ["java", "-jar", "/app.jar", "--spring.profiles.active=link"]
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/Index.vue:
--------------------------------------------------------------------------------
1 |
2 | main
3 |
4 |
5 |
10 |
11 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/globalFun.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue"
2 |
3 | Vue.mixin({
4 | methods: {
5 | hasAuth(perm) {
6 | var authority = this.$store.state.menus.permList
7 |
8 | return authority.indexOf(perm) > -1
9 | }
10 | }
11 | })
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/mapper/SysMenuMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/mapper/SysRoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/mapper/SysRoleMenuMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/mapper/SysUserRoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/vueadmin-java/src/test/java/com/markerhub/VueadminJavaApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.markerhub;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class VueadminJavaApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/exception/CaptchaException.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.exception;
2 |
3 | import org.springframework.security.core.AuthenticationException;
4 |
5 | public class CaptchaException extends AuthenticationException {
6 |
7 | public CaptchaException(String msg) {
8 | super(msg);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/vueadmin-vue/README.md:
--------------------------------------------------------------------------------
1 | # vueadmin-vue
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Customize configuration
19 | See [Configuration Reference](https://cli.vuejs.org/config/).
20 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/mapper/SysMenuMapper.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.mapper;
2 |
3 | import com.markerhub.entity.SysMenu;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysMenuMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/mapper/SysRoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.mapper;
2 |
3 | import com.markerhub.entity.SysRole;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysRoleMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/mapper/SysRoleMenuMapper.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.mapper;
2 |
3 | import com.markerhub.entity.SysRoleMenu;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysRoleMenuMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/mapper/SysUserRoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.mapper;
2 |
3 | import com.markerhub.entity.SysUserRole;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysUserRoleMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/SysRoleMenuService.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service;
2 |
3 | import com.markerhub.entity.SysRoleMenu;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysRoleMenuService extends IService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/SysUserRoleService.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service;
2 |
3 | import com.markerhub.entity.SysUserRole;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysUserRoleService extends IService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-java/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | mysql:
4 | image: mysql:5.7.27
5 | ports:
6 | - 3306:3306
7 | environment: # 指定用户root的密码
8 | - MYSQL_ROOT_PASSWORD=admin
9 | redis:
10 | image: redis:latest
11 | vueadmin:
12 | image: vueadmin:latest
13 | build: . # 表示以当前目录下的Dockerfile开始构建镜像
14 | ports:
15 | - 8085:8081
16 | depends_on:
17 | - mysql
18 | - redis
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/VueadminJavaApplication.java:
--------------------------------------------------------------------------------
1 | package com.markerhub;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class VueadminJavaApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(VueadminJavaApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/dto/PassDto.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.dto;
2 |
3 | import lombok.Data;
4 |
5 | import javax.validation.constraints.NotBlank;
6 | import java.io.Serializable;
7 |
8 | @Data
9 | public class PassDto implements Serializable {
10 |
11 | @NotBlank(message = "新密码不能为空")
12 | private String password;
13 |
14 | @NotBlank(message = "旧密码不能为空")
15 | private String currentPass;
16 | }
17 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import menus from "./modules/menus";
4 |
5 | Vue.use(Vuex)
6 |
7 | export default new Vuex.Store({
8 | state: {
9 | token: ''
10 |
11 | },
12 | mutations: {
13 |
14 | SET_TOKEN: (state, token) => {
15 | state.token = token
16 | localStorage.setItem("token", token)
17 | },
18 |
19 |
20 | },
21 | actions: {},
22 | modules: {
23 | menus
24 | }
25 | })
26 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/SysRoleService.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service;
2 |
3 | import com.markerhub.entity.SysRole;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | *
10 | * 服务类
11 | *
12 | *
13 | * @author 我的公众号:MarkerHub
14 | * @since 2021-04-05
15 | */
16 | public interface SysRoleService extends IService {
17 |
18 | List listRolesByUserId(Long userId);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/lang/Const.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.lang;
2 |
3 | public class Const {
4 |
5 | public final static String CAPTCHA_KEY = "captcha";
6 |
7 | public final static Integer STATUS_ON = 0;
8 | public final static Integer STATUS_OFF = 1;
9 |
10 | public static final String DEFULT_PASSWORD = "888888";
11 | public static final String DEFULT_AVATAR = "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg";
12 | }
13 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import store from './store'
5 |
6 | import Element from "element-ui"
7 | import "element-ui/lib/theme-chalk/index.css"
8 |
9 | import axios from './axios'
10 | import global from './globalFun'
11 |
12 | Vue.prototype.$axios = axios //
13 | Vue.config.productionTip = false
14 |
15 | // require("./mock.js")
16 |
17 | Vue.use(Element)
18 |
19 | new Vue({
20 | router,
21 | store,
22 | render: h => h(App)
23 | }).$mount('#app')
24 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/BaseEntity.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 |
7 | import java.io.Serializable;
8 | import java.time.LocalDateTime;
9 |
10 | @Data
11 | public class BaseEntity implements Serializable {
12 |
13 | @TableId(value = "id", type = IdType.AUTO)
14 | private Long id;
15 |
16 | private LocalDateTime created;
17 | private LocalDateTime updated;
18 |
19 | private Integer statu;
20 | }
21 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/SysMenuService.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service;
2 |
3 | import com.markerhub.common.dto.SysMenuDto;
4 | import com.markerhub.entity.SysMenu;
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 服务类
12 | *
13 | *
14 | * @author 我的公众号:MarkerHub
15 | * @since 2021-04-05
16 | */
17 | public interface SysMenuService extends IService {
18 |
19 | List getCurrentUserNav();
20 |
21 | List tree();
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | # DataSource Config
4 | spring:
5 | datasource:
6 | driver-class-name: com.mysql.cj.jdbc.Driver
7 | url: jdbc:mysql://localhost:3306/vueadmin?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
8 | username: root
9 | password: admin
10 | # security:
11 | # user:
12 | # name: user
13 | # password: 111111
14 | mybatis-plus:
15 | mapper-locations: classpath*:/mapper/**Mapper.xml
16 | markerhub:
17 | jwt:
18 | header: Authorization
19 | expire: 604800 #7天,秒单位
20 | secret: ji8n3439n439n43ld9ne9343fdfer49h
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/mapper/SysUserMapper.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.mapper;
2 |
3 | import com.markerhub.entity.SysUser;
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 | import org.apache.ibatis.annotations.Mapper;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | *
12 | * Mapper 接口
13 | *
14 | *
15 | * @author 我的公众号:MarkerHub
16 | * @since 2021-04-05
17 | */
18 | @Repository
19 | public interface SysUserMapper extends BaseMapper {
20 |
21 | List getNavMenuIds(Long userId);
22 |
23 | List listByMenuId(Long menuId);
24 | }
25 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/SysUserRole.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import lombok.Data;
6 | import lombok.EqualsAndHashCode;
7 |
8 | /**
9 | *
10 | *
11 | *
12 | *
13 | * @author 我的公众号:MarkerHub
14 | * @since 2021-04-05
15 | */
16 | @Data
17 | public class SysUserRole {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Long id;
23 |
24 | private Long userId;
25 |
26 | private Long roleId;
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/impl/SysRoleMenuServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service.impl;
2 |
3 | import com.markerhub.entity.SysRoleMenu;
4 | import com.markerhub.mapper.SysRoleMenuMapper;
5 | import com.markerhub.service.SysRoleMenuService;
6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | * @author 我的公众号:MarkerHub
15 | * @since 2021-04-05
16 | */
17 | @Service
18 | public class SysRoleMenuServiceImpl extends ServiceImpl implements SysRoleMenuService {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/impl/SysUserRoleServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service.impl;
2 |
3 | import com.markerhub.entity.SysUserRole;
4 | import com.markerhub.mapper.SysUserRoleMapper;
5 | import com.markerhub.service.SysUserRoleService;
6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | * @author 我的公众号:MarkerHub
15 | * @since 2021-04-05
16 | */
17 | @Service
18 | public class SysUserRoleServiceImpl extends ServiceImpl implements SysUserRoleService {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/SysRoleMenu.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 |
4 | import com.baomidou.mybatisplus.annotation.IdType;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 |
9 | /**
10 | *
11 | *
12 | *
13 | *
14 | * @author 我的公众号:MarkerHub
15 | * @since 2021-04-05
16 | */
17 | @Data
18 | public class SysRoleMenu {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Long id;
24 |
25 | private Long roleId;
26 |
27 | private Long menuId;
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/SysUserService.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service;
2 |
3 | import com.markerhub.entity.SysUser;
4 | import com.baomidou.mybatisplus.extension.service.IService;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author 我的公众号:MarkerHub
12 | * @since 2021-04-05
13 | */
14 | public interface SysUserService extends IService {
15 |
16 | SysUser getByUsername(String username);
17 |
18 | String getUserAuthorityInfo(Long userId);
19 |
20 | void clearUserAuthorityInfo(String username);
21 |
22 | void clearUserAuthorityInfoByRoleId(Long roleId);
23 |
24 | void clearUserAuthorityInfoByMenuId(Long menuId);
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/vueadmin-vue/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
30 |
31 |
40 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/dto/SysMenuDto.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.dto;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * {
11 | * name: 'SysUser',
12 | * title: '用户管理',
13 | * icon: 'el-icon-s-custom',
14 | * path: '/sys/users',
15 | * component: 'sys/User',
16 | * children: []
17 | * },
18 | */
19 | @Data
20 | public class SysMenuDto implements Serializable {
21 |
22 | private Long id;
23 | private String name;
24 | private String title;
25 | private String icon;
26 | private String path;
27 | private String component;
28 | private List children = new ArrayList<>();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/vueadmin-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vueadmin-vue",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build"
8 | },
9 | "dependencies": {
10 | "axios": "^0.21.1",
11 | "core-js": "^3.6.5",
12 | "element-ui": "^2.15.0",
13 | "mockjs": "^1.1.0",
14 | "qs": "^6.10.1",
15 | "vue": "^2.6.11",
16 | "vue-router": "^3.2.0",
17 | "vuex": "^3.4.0"
18 | },
19 | "devDependencies": {
20 | "@vue/cli-plugin-babel": "~4.5.0",
21 | "@vue/cli-plugin-router": "~4.5.0",
22 | "@vue/cli-plugin-vuex": "~4.5.0",
23 | "@vue/cli-service": "~4.5.0",
24 | "mockjs": "^1.1.0",
25 | "vue-template-compiler": "^2.6.11"
26 | },
27 | "browserslist": [
28 | "> 1%",
29 | "last 2 versions",
30 | "not dead"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/lang/Result.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.lang;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | @Data
8 | public class Result implements Serializable {
9 |
10 | private int code;
11 | private String msg;
12 | private Object data;
13 |
14 | public static Result succ(Object data) {
15 | return succ(200, "操作成功", data);
16 | }
17 |
18 | public static Result succ(int code, String msg, Object data) {
19 | Result r = new Result();
20 | r.setCode(code);
21 | r.setMsg(msg);
22 | r.setData(data);
23 | return r;
24 | }
25 |
26 | public static Result fail(String msg) {
27 | return fail(400, msg, null);
28 | }
29 |
30 | public static Result fail(int code, String msg, Object data) {
31 | Result r = new Result();
32 | r.setCode(code);
33 | r.setMsg(msg);
34 | r.setData(data);
35 | return r;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/SysRole.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableField;
4 | import lombok.Data;
5 | import lombok.EqualsAndHashCode;
6 |
7 | import javax.validation.constraints.NotBlank;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | *
13 | *
14 | *
15 | *
16 | * @author 我的公众号:MarkerHub
17 | * @since 2021-04-05
18 | */
19 | @Data
20 | @EqualsAndHashCode(callSuper = true)
21 | public class SysRole extends BaseEntity {
22 |
23 | private static final long serialVersionUID = 1L;
24 |
25 | @NotBlank(message = "角色名称不能为空")
26 | private String name;
27 |
28 | @NotBlank(message = "角色编码不能为空")
29 | private String code;
30 |
31 | /**
32 | * 备注
33 | */
34 | private String remark;
35 |
36 | @TableField(exist = false)
37 | private List menuIds = new ArrayList<>();
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/resources/mapper/SysUserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
27 |
28 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/impl/SysRoleServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 | import com.markerhub.entity.SysRole;
5 | import com.markerhub.mapper.SysRoleMapper;
6 | import com.markerhub.service.SysRoleService;
7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | *
14 | * 服务实现类
15 | *
16 | *
17 | * @author 我的公众号:MarkerHub
18 | * @since 2021-04-05
19 | */
20 | @Service
21 | public class SysRoleServiceImpl extends ServiceImpl implements SysRoleService {
22 |
23 | @Override
24 | public List listRolesByUserId(Long userId) {
25 |
26 | List sysRoles = this.list(new QueryWrapper()
27 | .inSql("id", "select role_id from sys_user_role where user_id = " + userId));
28 |
29 | return sysRoles;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### VueAdmin - 基于SpringBoot+Jwt+Vue的前后端分离后台管理系统
2 |
3 | 完整教学!从0到1开发,手把手教你学会开发一个spring security + jwt + vue的前后端分离项目!
4 |
5 | 线上体验:[https://www.markerhub.com/vueadmin/](https://www.markerhub.com/vueadmin/)
6 |
7 | ### 说明:
8 |
9 | 首发公众号:MarkerHub
10 |
11 | 
12 |
13 | 项目视频:[https://www.bilibili.com/video/BV1af4y1s7Wh/](https://www.bilibili.com/video/BV1af4y1s7Wh/)
14 |
15 | 项目文档:
16 | * 前端笔记:https://shimo.im/docs/pxwyJHgqcWjWkTKX/
17 | * 后端笔记:https://shimo.im/docs/OnZDwoxFFL8bnP1c/
18 |
19 | 更多项目:[https://www.markerhub.com/](https://www.markerhub.com/)
20 |
21 | ### 技术栈:
22 | springboot、spring security、myabtis plus、jwt、vue、element-ui
23 |
24 | ### 项目截图
25 | 
26 |
27 | 
28 |
29 | ### 进群学习
30 |
31 | 加我微信 java-mindman3,记得备注【 VueAdmin 】,我会拉群!
32 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/config/KaptchaConfig.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.config;
2 |
3 | import com.google.code.kaptcha.impl.DefaultKaptcha;
4 | import com.google.code.kaptcha.util.Config;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.security.core.parameters.P;
8 |
9 | import java.util.Properties;
10 |
11 | @Configuration
12 | public class KaptchaConfig {
13 |
14 | @Bean
15 | DefaultKaptcha producer() {
16 | Properties properties = new Properties();
17 | properties.put("kaptcha.border", "no");
18 | properties.put("kaptcha.textproducer.font.color", "black");
19 | properties.put("kaptcha.textproducer.char.space", "4");
20 | properties.put("kaptcha.image.height", "40");
21 | properties.put("kaptcha.image.width", "120");
22 | properties.put("kaptcha.textproducer.font.size", "30");
23 |
24 | Config config = new Config(properties);
25 | DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
26 | defaultKaptcha.setConfig(config);
27 |
28 | return defaultKaptcha;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/SysUser.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 | import java.time.LocalDateTime;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import com.baomidou.mybatisplus.annotation.TableField;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 |
11 | import javax.validation.constraints.Email;
12 | import javax.validation.constraints.NotBlank;
13 |
14 | /**
15 | *
16 | *
17 | *
18 | *
19 | * @author 我的公众号:MarkerHub
20 | * @since 2021-04-05
21 | */
22 | @Data
23 | @EqualsAndHashCode(callSuper = true)
24 | public class SysUser extends BaseEntity {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | @NotBlank(message = "用户名不能为空")
29 | private String username;
30 |
31 | private String password;
32 |
33 | private String avatar;
34 |
35 | @NotBlank(message = "邮箱不能为空")
36 | @Email(message = "邮箱格式不正确")
37 | private String email;
38 |
39 | private String city;
40 |
41 | private LocalDateTime lastLogin;
42 |
43 | @TableField(exist = false)
44 | private List sysRoles = new ArrayList<>();
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/BaseController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
4 | import com.markerhub.service.*;
5 | import com.markerhub.utils.RedisUtil;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.web.bind.ServletRequestUtils;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 |
11 | public class BaseController {
12 |
13 | @Autowired
14 | HttpServletRequest req;
15 |
16 | @Autowired
17 | RedisUtil redisUtil;
18 |
19 | @Autowired
20 | SysUserService sysUserService;
21 |
22 | @Autowired
23 | SysRoleService sysRoleService;
24 |
25 | @Autowired
26 | SysMenuService sysMenuService;
27 |
28 | @Autowired
29 | SysUserRoleService sysUserRoleService;
30 |
31 | @Autowired
32 | SysRoleMenuService sysRoleMenuService;
33 |
34 | /**
35 | * 获取页面
36 | * @return
37 | */
38 | public Page getPage() {
39 | int current = ServletRequestUtils.getIntParameter(req, "cuurent", 1);
40 | int size = ServletRequestUtils.getIntParameter(req, "size", 10);
41 |
42 | return new Page(current, size);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/axios.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import router from "./router";
3 | import Element from "element-ui"
4 |
5 | axios.defaults.baseURL = "http://localhost:8081"
6 |
7 | const request = axios.create({
8 | timeout: 5000,
9 | headers: {
10 | 'Content-Type': "application/json; charset=utf-8"
11 | }
12 | })
13 |
14 | request.interceptors.request.use(config => {
15 | config.headers['Authorization'] = localStorage.getItem("token")
16 | return config
17 | })
18 |
19 | request.interceptors.response.use(
20 | response => {
21 |
22 | console.log("response ->" + response)
23 |
24 | let res = response.data
25 |
26 | if (res.code === 200) {
27 | return response
28 | } else {
29 | Element.Message.error(!res.msg ? '系统异常' : res.msg)
30 | return Promise.reject(response.data.msg)
31 | }
32 | },
33 | error => {
34 |
35 | console.log(error)
36 |
37 | if (error.response.data) {
38 | error.massage = error.response.data.msg
39 | }
40 |
41 | if (error.response.status === 401) {
42 | router.push("/login")
43 | }
44 |
45 | Element.Message.error(error.massage, {duration: 3000})
46 | return Promise.reject(error)
47 | }
48 | )
49 |
50 | export default request
--------------------------------------------------------------------------------
/vueadmin-vue/src/store/modules/menus.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | export default {
7 | state: {
8 |
9 | menuList: [],
10 | permList: [],
11 |
12 | hasRoutes: false,
13 |
14 | editableTabsValue: 'Index',
15 | editableTabs: [{
16 | title: '首页',
17 | name: 'Index',
18 | }]
19 | },
20 | mutations: {
21 | setMenuList(state, menus) {
22 | state.menuList = menus
23 | },
24 | setPermList(state, perms) {
25 | state.permList = perms
26 | },
27 | changeRouteStatus(state, hasRoutes) {
28 | state.hasRoutes = hasRoutes
29 | },
30 |
31 | addTab(state, tab) {
32 |
33 | let index = state.editableTabs.findIndex(e => e.name === tab.name)
34 |
35 | if (index === -1) {
36 | state.editableTabs.push({
37 | title: tab.title,
38 | name: tab.name,
39 | });
40 | }
41 |
42 | state.editableTabsValue = tab.name;
43 | },
44 |
45 | resetState: (state) => {
46 | state.menuList = []
47 | state.permList = []
48 |
49 | state.hasRoutes = false
50 | state.editableTabsValue = 'Index'
51 | state.editableTabs = [{
52 | title: '首页',
53 | name: 'Index',
54 | }]
55 | }
56 |
57 | },
58 | actions: {
59 | },
60 |
61 | }
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/config/MybatisPlusConfig.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.config;
2 |
3 | import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
5 | import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
6 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
7 | import org.mybatis.spring.annotation.MapperScan;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | @Configuration
12 | @MapperScan("com.markerhub.mapper")
13 | public class MybatisPlusConfig {
14 |
15 | @Bean
16 | public MybatisPlusInterceptor mybatisPlusInterceptor() {
17 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
18 | // 分页插件
19 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
20 | // 防止全表更新插件
21 | interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
22 |
23 | return interceptor;
24 | }
25 |
26 | @Bean
27 | public ConfigurationCustomizer configurationCustomizer() {
28 | return configuration -> configuration.setUseDeprecatedExecutor(false);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/LoginFailureHandler.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.markerhub.common.lang.Result;
5 | import org.springframework.security.core.AuthenticationException;
6 | import org.springframework.security.web.authentication.AuthenticationFailureHandler;
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.ServletOutputStream;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 |
15 | @Component
16 | public class LoginFailureHandler implements AuthenticationFailureHandler {
17 |
18 | @Override
19 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
20 |
21 | response.setContentType("application/json;charset=UTF-8");
22 | ServletOutputStream outputStream = response.getOutputStream();
23 |
24 | Result result = Result.fail("用户名或密码错误");
25 |
26 | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
27 |
28 | outputStream.flush();
29 | outputStream.close();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 | import com.markerhub.common.lang.Result;
4 | import com.markerhub.service.SysUserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.access.prepost.PreAuthorize;
7 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | public class TestController {
13 |
14 | @Autowired
15 | SysUserService sysUserService;
16 |
17 | @Autowired
18 | BCryptPasswordEncoder bCryptPasswordEncoder;
19 |
20 | @PreAuthorize("hasRole('admin')")
21 | @GetMapping("/test")
22 | public Result test() {
23 | return Result.succ(sysUserService.list());
24 | }
25 |
26 | // 普通用户、超级管理员
27 | @PreAuthorize("hasAuthority('sys:user:list')")
28 | @GetMapping("/test/pass")
29 | public Result pass() {
30 |
31 | // 加密后密码
32 | String password = bCryptPasswordEncoder.encode("111111");
33 |
34 | boolean matches = bCryptPasswordEncoder.matches("111111", password);
35 |
36 | System.out.println("匹配结果:" + matches);
37 |
38 | return Result.succ(password);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/JwtAuthenticationEntryPoint.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.markerhub.common.lang.Result;
5 | import org.springframework.security.core.AuthenticationException;
6 | import org.springframework.security.web.AuthenticationEntryPoint;
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.ServletOutputStream;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 |
15 | @Component
16 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
17 |
18 | @Override
19 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
20 |
21 | response.setContentType("application/json;charset=UTF-8");
22 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
23 | ServletOutputStream outputStream = response.getOutputStream();
24 |
25 | Result result = Result.fail("请先登录");
26 |
27 | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
28 |
29 | outputStream.flush();
30 | outputStream.close();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/JwtAccessDeniedHandler.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.markerhub.common.lang.Result;
5 | import org.springframework.security.access.AccessDeniedException;
6 | import org.springframework.security.web.access.AccessDeniedHandler;
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.ServletOutputStream;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 |
15 | @Component
16 | public class JwtAccessDeniedHandler implements AccessDeniedHandler {
17 |
18 | @Override
19 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
20 |
21 | response.setContentType("application/json;charset=UTF-8");
22 | response.setStatus(HttpServletResponse.SC_FORBIDDEN);
23 |
24 | ServletOutputStream outputStream = response.getOutputStream();
25 |
26 | Result result = Result.fail(accessDeniedException.getMessage());
27 |
28 | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
29 |
30 | outputStream.flush();
31 | outputStream.close();
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/utils/JwtUtils.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.utils;
2 |
3 | import io.jsonwebtoken.*;
4 | import lombok.Data;
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.util.Date;
9 |
10 | @Data
11 | @Component
12 | @ConfigurationProperties(prefix = "markerhub.jwt")
13 | public class JwtUtils {
14 |
15 | private long expire;
16 | private String secret;
17 | private String header;
18 |
19 | // 生成jwt
20 | public String generateToken(String username) {
21 |
22 | Date nowDate = new Date();
23 | Date expireDate = new Date(nowDate.getTime() + 1000 * expire);
24 |
25 | return Jwts.builder()
26 | .setHeaderParam("typ", "JWT")
27 | .setSubject(username)
28 | .setIssuedAt(nowDate)
29 | .setExpiration(expireDate)// 7天過期
30 | .signWith(SignatureAlgorithm.HS512, secret)
31 | .compact();
32 | }
33 |
34 | // 解析jwt
35 | public Claims getClaimByToken(String jwt) {
36 | try {
37 | return Jwts.parser()
38 | .setSigningKey(secret)
39 | .parseClaimsJws(jwt)
40 | .getBody();
41 | } catch (Exception e) {
42 | return null;
43 | }
44 | }
45 |
46 | // jwt是否过期
47 | public boolean isTokenExpired(Claims claims) {
48 | return claims.getExpiration().before(new Date());
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/config/RedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.config;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.connection.RedisConnectionFactory;
7 | import org.springframework.data.redis.core.RedisTemplate;
8 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
9 | import org.springframework.data.redis.serializer.StringRedisSerializer;
10 |
11 | @Configuration
12 | public class RedisConfig {
13 |
14 | @Bean
15 | RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
16 |
17 | RedisTemplate redisTemplate = new RedisTemplate();
18 | redisTemplate.setConnectionFactory(redisConnectionFactory);
19 |
20 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
21 | jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());
22 |
23 | redisTemplate.setKeySerializer(new StringRedisSerializer());
24 | redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
25 |
26 | redisTemplate.setHashKeySerializer(new StringRedisSerializer());
27 | redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
28 |
29 | return redisTemplate;
30 |
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/config/CorsConfig.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.cors.CorsConfiguration;
6 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
7 | import org.springframework.web.filter.CorsFilter;
8 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
10 |
11 | @Configuration
12 | public class CorsConfig implements WebMvcConfigurer {
13 |
14 | private CorsConfiguration buildConfig() {
15 | CorsConfiguration corsConfiguration = new CorsConfiguration();
16 | corsConfiguration.addAllowedOrigin("*");
17 | corsConfiguration.addAllowedHeader("*");
18 | corsConfiguration.addAllowedMethod("*");
19 | corsConfiguration.addExposedHeader("Authorization");
20 | return corsConfiguration;
21 | }
22 |
23 | @Bean
24 | public CorsFilter corsFilter() {
25 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
26 | source.registerCorsConfiguration("/**", buildConfig());
27 | return new CorsFilter(source);
28 | }
29 |
30 | @Override
31 | public void addCorsMappings(CorsRegistry registry) {
32 | registry.addMapping("/**")
33 | .allowedOrigins("*")
34 | // .allowCredentials(true)
35 | .allowedMethods("GET", "POST", "DELETE", "PUT")
36 | .maxAge(3600);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/LoginSuccessHandler.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.markerhub.common.lang.Result;
5 | import com.markerhub.utils.JwtUtils;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.security.core.Authentication;
8 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
9 | import org.springframework.stereotype.Component;
10 |
11 | import javax.servlet.ServletException;
12 | import javax.servlet.ServletOutputStream;
13 | import javax.servlet.http.HttpServletRequest;
14 | import javax.servlet.http.HttpServletResponse;
15 | import java.io.IOException;
16 |
17 | @Component
18 | public class LoginSuccessHandler implements AuthenticationSuccessHandler {
19 |
20 | @Autowired
21 | JwtUtils jwtUtils;
22 |
23 | @Override
24 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
25 | response.setContentType("application/json;charset=UTF-8");
26 | ServletOutputStream outputStream = response.getOutputStream();
27 |
28 | // 生成jwt,并放置到请求头中
29 | String jwt = jwtUtils.generateToken(authentication.getName());
30 | response.setHeader(jwtUtils.getHeader(), jwt);
31 |
32 | Result result = Result.succ("");
33 |
34 | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
35 |
36 | outputStream.flush();
37 | outputStream.close();
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/entity/SysMenu.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableField;
4 | import lombok.Data;
5 | import lombok.EqualsAndHashCode;
6 |
7 | import javax.validation.constraints.NotBlank;
8 | import javax.validation.constraints.NotNull;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | /**
13 | *
14 | *
15 | *
16 | *
17 | * @author 我的公众号:MarkerHub
18 | * @since 2021-04-05
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = true)
22 | public class SysMenu extends BaseEntity {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | /**
27 | * 父菜单ID,一级菜单为0
28 | */
29 | @NotNull(message = "上级菜单不能为空")
30 | private Long parentId;
31 |
32 | @NotBlank(message = "菜单名称不能为空")
33 | private String name;
34 |
35 | /**
36 | * 菜单URL
37 | */
38 | private String path;
39 |
40 | /**
41 | * 授权(多个用逗号分隔,如:user:list,user:create)
42 | */
43 | @NotBlank(message = "菜单授权码不能为空")
44 | private String perms;
45 |
46 | private String component;
47 |
48 | /**
49 | * 类型 0:目录 1:菜单 2:按钮
50 | */
51 | @NotNull(message = "菜单类型不能为空")
52 | private Integer type;
53 |
54 | /**
55 | * 菜单图标
56 | */
57 | private String icon;
58 |
59 | /**
60 | * 排序
61 | */
62 | @TableField("orderNum")
63 | private Integer orderNum;
64 |
65 | @TableField(exist = false)
66 | private List children = new ArrayList<>();
67 | }
68 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/inc/SideMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
36 |
37 |
38 |
60 |
61 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/JwtLogoutSuccessHandler.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.markerhub.common.lang.Result;
5 | import com.markerhub.utils.JwtUtils;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.security.core.Authentication;
8 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
9 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
10 | import org.springframework.stereotype.Component;
11 |
12 | import javax.servlet.ServletException;
13 | import javax.servlet.ServletOutputStream;
14 | import javax.servlet.http.HttpServletRequest;
15 | import javax.servlet.http.HttpServletResponse;
16 | import java.io.IOException;
17 |
18 | @Component
19 | public class JwtLogoutSuccessHandler implements LogoutSuccessHandler {
20 |
21 | @Autowired
22 | JwtUtils jwtUtils;
23 |
24 | @Override
25 | public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
26 |
27 | if (authentication != null) {
28 | new SecurityContextLogoutHandler().logout(request, response, authentication);
29 | }
30 |
31 | response.setContentType("application/json;charset=UTF-8");
32 | ServletOutputStream outputStream = response.getOutputStream();
33 |
34 | response.setHeader(jwtUtils.getHeader(), "");
35 |
36 | Result result = Result.succ("");
37 |
38 | outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
39 |
40 | outputStream.flush();
41 | outputStream.close();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/UserDetailServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import com.markerhub.entity.SysUser;
4 | import com.markerhub.service.SysUserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.GrantedAuthority;
7 | import org.springframework.security.core.authority.AuthorityUtils;
8 | import org.springframework.security.core.userdetails.UserDetails;
9 | import org.springframework.security.core.userdetails.UserDetailsService;
10 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
11 | import org.springframework.stereotype.Service;
12 |
13 | import java.util.List;
14 |
15 | @Service
16 | public class UserDetailServiceImpl implements UserDetailsService {
17 |
18 | @Autowired
19 | SysUserService sysUserService;
20 |
21 | @Override
22 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
23 |
24 | SysUser sysUser = sysUserService.getByUsername(username);
25 | if (sysUser == null) {
26 | throw new UsernameNotFoundException("用户名或密码不正确");
27 | }
28 | return new AccountUser(sysUser.getId(), sysUser.getUsername(), sysUser.getPassword(), getUserAuthority(sysUser.getId()));
29 | }
30 |
31 | /**
32 | * 获取用户权限信息(角色、菜单权限)
33 | * @param userId
34 | * @return
35 | */
36 | public List getUserAuthority(Long userId){
37 |
38 | // 角色(ROLE_admin)、菜单操作权限 sys:user:list
39 | String authority = sysUserService.getUserAuthorityInfo(userId); // ROLE_admin,ROLE_normal,sys:user:list,....
40 |
41 | return AuthorityUtils.commaSeparatedStringToAuthorityList(authority);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/common/exception/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.common.exception;
2 |
3 | import com.markerhub.common.lang.Result;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.validation.BindingResult;
7 | import org.springframework.validation.ObjectError;
8 | import org.springframework.web.bind.MethodArgumentNotValidException;
9 | import org.springframework.web.bind.annotation.ExceptionHandler;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestControllerAdvice;
12 |
13 | @Slf4j
14 | @RestControllerAdvice
15 | public class GlobalExceptionHandler {
16 |
17 | //
18 |
19 | // 实体校验异常捕获
20 | @ResponseStatus(HttpStatus.BAD_REQUEST)
21 | @ExceptionHandler(value = MethodArgumentNotValidException.class)
22 | public Result handler(MethodArgumentNotValidException e) {
23 |
24 | BindingResult result = e.getBindingResult();
25 | ObjectError objectError = result.getAllErrors().stream().findFirst().get();
26 |
27 | log.error("实体校验异常:----------------{}", objectError.getDefaultMessage());
28 | return Result.fail(objectError.getDefaultMessage());
29 | }
30 |
31 | @ResponseStatus(HttpStatus.BAD_REQUEST)
32 | @ExceptionHandler(value = IllegalArgumentException.class)
33 | public Result handler(IllegalArgumentException e) {
34 | log.error("Assert异常:----------------{}", e.getMessage());
35 | return Result.fail(e.getMessage());
36 | }
37 |
38 | @ResponseStatus(HttpStatus.BAD_REQUEST)
39 | @ExceptionHandler(value = RuntimeException.class)
40 | public Result handler(RuntimeException e) {
41 | log.error("运行时异常:----------------{}", e.getMessage());
42 | return Result.fail(e.getMessage());
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/inc/Tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
74 |
75 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/CaptchaFilter.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import com.baomidou.mybatisplus.core.toolkit.StringUtils;
4 | import com.markerhub.common.exception.CaptchaException;
5 | import com.markerhub.common.lang.Const;
6 | import com.markerhub.utils.RedisUtil;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Component;
9 | import org.springframework.web.filter.OncePerRequestFilter;
10 |
11 | import javax.servlet.FilterChain;
12 | import javax.servlet.ServletException;
13 | import javax.servlet.http.HttpServletRequest;
14 | import javax.servlet.http.HttpServletResponse;
15 | import java.io.IOException;
16 |
17 | @Component
18 | public class CaptchaFilter extends OncePerRequestFilter {
19 |
20 | @Autowired
21 | RedisUtil redisUtil;
22 |
23 | @Autowired
24 | LoginFailureHandler loginFailureHandler;
25 |
26 | @Override
27 | protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
28 |
29 | String url = httpServletRequest.getRequestURI();
30 |
31 | if ("/login".equals(url) && httpServletRequest.getMethod().equals("POST")) {
32 |
33 | try{
34 | // 校验验证码
35 | validate(httpServletRequest);
36 | } catch (CaptchaException e) {
37 |
38 | // 交给认证失败处理器
39 | loginFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, e);
40 | }
41 | }
42 |
43 | filterChain.doFilter(httpServletRequest, httpServletResponse);
44 | }
45 |
46 | // 校验验证码逻辑
47 | private void validate(HttpServletRequest httpServletRequest) {
48 |
49 | String code = httpServletRequest.getParameter("code");
50 | String key = httpServletRequest.getParameter("token");
51 |
52 | if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
53 | throw new CaptchaException("验证码错误");
54 | }
55 |
56 | if (!code.equals(redisUtil.hget(Const.CAPTCHA_KEY, key))) {
57 | throw new CaptchaException("验证码错误");
58 | }
59 |
60 | // 一次性使用
61 | redisUtil.hdel(Const.CAPTCHA_KEY, key);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/AuthController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 | import cn.hutool.core.lang.UUID;
4 | import cn.hutool.core.map.MapUtil;
5 | import com.google.code.kaptcha.Producer;
6 | import com.markerhub.common.lang.Const;
7 | import com.markerhub.common.lang.Result;
8 | import com.markerhub.entity.SysUser;
9 | import com.markerhub.service.SysUserService;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.web.bind.annotation.GetMapping;
12 | import org.springframework.web.bind.annotation.RestController;
13 | import sun.misc.BASE64Encoder;
14 |
15 | import javax.imageio.ImageIO;
16 | import java.awt.image.BufferedImage;
17 | import java.io.ByteArrayOutputStream;
18 | import java.io.IOException;
19 | import java.security.Principal;
20 |
21 | @RestController
22 | public class AuthController extends BaseController{
23 |
24 | @Autowired
25 | Producer producer;
26 |
27 | @GetMapping("/captcha")
28 | public Result captcha() throws IOException {
29 |
30 | String key = UUID.randomUUID().toString();
31 | String code = producer.createText();
32 |
33 | // 为了测试
34 | key = "aaaaa";
35 | code = "11111";
36 |
37 | BufferedImage image = producer.createImage(code);
38 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
39 | ImageIO.write(image, "jpg", outputStream);
40 |
41 | BASE64Encoder encoder = new BASE64Encoder();
42 | String str = "data:image/jpeg;base64,";
43 |
44 | String base64Img = str + encoder.encode(outputStream.toByteArray());
45 |
46 | redisUtil.hset(Const.CAPTCHA_KEY, key, code, 120);
47 |
48 | return Result.succ(
49 | MapUtil.builder()
50 | .put("token", key)
51 | .put("captchaImg", base64Img)
52 | .build()
53 |
54 | );
55 | }
56 |
57 | /**
58 | * 获取用户信息接口
59 | * @param principal
60 | * @return
61 | */
62 | @GetMapping("/sys/userInfo")
63 | public Result userInfo(Principal principal) {
64 |
65 | SysUser sysUser = sysUserService.getByUsername(principal.getName());
66 |
67 | return Result.succ(MapUtil.builder()
68 | .put("id", sysUser.getId())
69 | .put("username", sysUser.getUsername())
70 | .put("avatar", sysUser.getAvatar())
71 | .put("created", sysUser.getCreated())
72 | .map()
73 | );
74 | }
75 |
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/JwtAuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import cn.hutool.core.util.StrUtil;
4 | import com.markerhub.entity.SysUser;
5 | import com.markerhub.service.SysUserService;
6 | import com.markerhub.utils.JwtUtils;
7 | import io.jsonwebtoken.Claims;
8 | import io.jsonwebtoken.JwtException;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.security.authentication.AuthenticationManager;
11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
12 | import org.springframework.security.core.context.SecurityContextHolder;
13 | import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
14 |
15 | import javax.servlet.FilterChain;
16 | import javax.servlet.ServletException;
17 | import javax.servlet.http.HttpServletRequest;
18 | import javax.servlet.http.HttpServletResponse;
19 | import java.io.IOException;
20 |
21 | public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
22 |
23 | @Autowired
24 | JwtUtils jwtUtils;
25 |
26 | @Autowired
27 | UserDetailServiceImpl userDetailService;
28 |
29 | @Autowired
30 | SysUserService sysUserService;
31 |
32 | public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
33 | super(authenticationManager);
34 | }
35 |
36 | @Override
37 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
38 |
39 | String jwt = request.getHeader(jwtUtils.getHeader());
40 | if (StrUtil.isBlankOrUndefined(jwt)) {
41 | chain.doFilter(request, response);
42 | return;
43 | }
44 |
45 | Claims claim = jwtUtils.getClaimByToken(jwt);
46 | if (claim == null) {
47 | throw new JwtException("token 异常");
48 | }
49 | if (jwtUtils.isTokenExpired(claim)) {
50 | throw new JwtException("token已过期");
51 | }
52 |
53 | String username = claim.getSubject();
54 | // 获取用户的权限等信息
55 |
56 | SysUser sysUser = sysUserService.getByUsername(username);
57 | UsernamePasswordAuthenticationToken token
58 | = new UsernamePasswordAuthenticationToken(username, null, userDetailService.getUserAuthority(sysUser.getId()));
59 |
60 | SecurityContextHolder.getContext().setAuthentication(token);
61 |
62 | chain.doFilter(request, response);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/security/AccountUser.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.security;
2 |
3 | import org.springframework.security.core.GrantedAuthority;
4 | import org.springframework.security.core.userdetails.UserDetails;
5 | import org.springframework.util.Assert;
6 |
7 | import java.util.Collection;
8 | import java.util.Collections;
9 | import java.util.Set;
10 |
11 | public class AccountUser implements UserDetails {
12 |
13 | private Long userId;
14 |
15 | private String password;
16 |
17 | private final String username;
18 |
19 | private final Collection extends GrantedAuthority> authorities;
20 |
21 | private final boolean accountNonExpired;
22 |
23 | private final boolean accountNonLocked;
24 |
25 | private final boolean credentialsNonExpired;
26 |
27 | private final boolean enabled;
28 |
29 | public AccountUser(Long userId, String username, String password, Collection extends GrantedAuthority> authorities) {
30 | this(userId, username, password, true, true, true, true, authorities);
31 | }
32 |
33 |
34 | public AccountUser(Long userId, String username, String password, boolean enabled, boolean accountNonExpired,
35 | boolean credentialsNonExpired, boolean accountNonLocked,
36 | Collection extends GrantedAuthority> authorities) {
37 | Assert.isTrue(username != null && !"".equals(username) && password != null,
38 | "Cannot pass null or empty values to constructor");
39 | this.userId = userId;
40 | this.username = username;
41 | this.password = password;
42 | this.enabled = enabled;
43 | this.accountNonExpired = accountNonExpired;
44 | this.credentialsNonExpired = credentialsNonExpired;
45 | this.accountNonLocked = accountNonLocked;
46 | this.authorities = authorities;
47 | }
48 |
49 |
50 | @Override
51 | public Collection extends GrantedAuthority> getAuthorities() {
52 | return this.authorities;
53 | }
54 |
55 | @Override
56 | public String getPassword() {
57 | return this.password;
58 | }
59 |
60 | @Override
61 | public String getUsername() {
62 | return this.username;
63 | }
64 |
65 | @Override
66 | public boolean isAccountNonExpired() {
67 | return this.accountNonExpired;
68 | }
69 |
70 | @Override
71 | public boolean isAccountNonLocked() {
72 | return this.accountNonLocked;
73 | }
74 |
75 | @Override
76 | public boolean isCredentialsNonExpired() {
77 | return this.credentialsNonExpired;
78 | }
79 |
80 | @Override
81 | public boolean isEnabled() {
82 | return this.enabled;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | VueAdmin后台管理系统
11 |
12 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
83 |
84 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/UserCenter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
你好!{{ userInfo.username }} 同学
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 提交
17 | 重置
18 |
19 |
20 |
21 |
22 |
23 |
97 |
98 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/impl/SysMenuServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service.impl;
2 |
3 | import cn.hutool.json.JSONUtil;
4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 | import com.markerhub.common.dto.SysMenuDto;
6 | import com.markerhub.entity.SysMenu;
7 | import com.markerhub.entity.SysUser;
8 | import com.markerhub.mapper.SysMenuMapper;
9 | import com.markerhub.mapper.SysUserMapper;
10 | import com.markerhub.service.SysMenuService;
11 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
12 | import com.markerhub.service.SysUserService;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.security.core.context.SecurityContextHolder;
15 | import org.springframework.stereotype.Service;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | /**
21 | *
22 | * 服务实现类
23 | *
24 | *
25 | * @author 我的公众号:MarkerHub
26 | * @since 2021-04-05
27 | */
28 | @Service
29 | public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService {
30 |
31 | @Autowired
32 | SysUserService sysUserService;
33 |
34 | @Autowired
35 | SysUserMapper sysUserMapper;
36 |
37 | @Override
38 | public List getCurrentUserNav() {
39 | String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
40 | SysUser sysUser = sysUserService.getByUsername(username);
41 |
42 | List menuIds = sysUserMapper.getNavMenuIds(sysUser.getId());
43 | List menus = this.listByIds(menuIds);
44 |
45 | // 转树状结构
46 | List menuTree = buildTreeMenu(menus);
47 |
48 | // 实体转DTO
49 | return convert(menuTree);
50 | }
51 |
52 | @Override
53 | public List tree() {
54 | // 获取所有菜单信息
55 | List sysMenus = this.list(new QueryWrapper().orderByAsc("orderNum"));
56 |
57 | // 转成树状结构
58 | return buildTreeMenu(sysMenus);
59 | }
60 |
61 | private List convert(List menuTree) {
62 | List menuDtos = new ArrayList<>();
63 |
64 | menuTree.forEach(m -> {
65 | SysMenuDto dto = new SysMenuDto();
66 |
67 | dto.setId(m.getId());
68 | dto.setName(m.getPerms());
69 | dto.setTitle(m.getName());
70 | dto.setComponent(m.getComponent());
71 | dto.setPath(m.getPath());
72 |
73 | if (m.getChildren().size() > 0) {
74 |
75 | // 子节点调用当前方法进行再次转换
76 | dto.setChildren(convert(m.getChildren()));
77 | }
78 |
79 | menuDtos.add(dto);
80 | });
81 |
82 | return menuDtos;
83 | }
84 |
85 | private List buildTreeMenu(List menus) {
86 |
87 | List finalMenus = new ArrayList<>();
88 |
89 | // 先各自寻找到各自的孩子
90 | for (SysMenu menu : menus) {
91 |
92 | for (SysMenu e : menus) {
93 | if (menu.getId() == e.getParentId()) {
94 | menu.getChildren().add(e);
95 | }
96 | }
97 |
98 | // 提取出父节点
99 | if (menu.getParentId() == 0L) {
100 | finalMenus.add(menu);
101 | }
102 | }
103 |
104 | System.out.println(JSONUtil.toJsonStr(finalMenus));
105 | return finalMenus;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import Home from '../views/Home.vue'
4 | import Index from '../views/Index.vue'
5 | import User from '../views/sys/User.vue'
6 | import Role from '../views/sys/Role.vue'
7 | import Menu from '../views/sys/Menu.vue'
8 |
9 | import axios from "../axios";
10 | import store from "../store"
11 | import el from "element-ui/src/locale/lang/el";
12 |
13 | Vue.use(VueRouter)
14 |
15 | const routes = [
16 | {
17 | path: '/',
18 | name: 'Home',
19 | component: Home,
20 | children: [
21 | {
22 | path: '/index',
23 | name: 'Index',
24 | meta: {
25 | title: "首页"
26 | },
27 | component: Index
28 | },
29 | {
30 | path: '/userCenter',
31 | name: 'UserCenter',
32 | meta: {
33 | title: "个人中心"
34 | },
35 | component: () => import('@/views/UserCenter.vue')
36 | },
37 | // {
38 | // path: '/sys/users',
39 | // name: 'SysUser',
40 | // component: User
41 | // },
42 | // {
43 | // path: '/sys/roles',
44 | // name: 'SysRole',
45 | // component: Role
46 | // },
47 | // {
48 | // path: '/sys/menus',
49 | // name: 'SysMenu',
50 | // component: Menu
51 | // },
52 | ]
53 | },
54 |
55 | {
56 | path: '/login',
57 | name: 'Login',
58 | component: () => import('@/views/Login.vue')
59 | }
60 | ]
61 |
62 | const router = new VueRouter({
63 | mode: 'history',
64 | base: process.env.BASE_URL,
65 | routes
66 | })
67 |
68 | router.beforeEach((to, from, next) => {
69 |
70 | let hasRoute = store.state.menus.hasRoutes
71 |
72 | let token = localStorage.getItem("token")
73 |
74 | if (to.path == '/login') {
75 | next()
76 |
77 | } else if (!token) {
78 | next({path: '/login'})
79 |
80 |
81 | } else if(token && !hasRoute) {
82 | axios.get("/sys/menu/nav", {
83 | headers: {
84 | Authorization: localStorage.getItem("token")
85 | }
86 | }).then(res => {
87 |
88 | console.log(res.data.data)
89 |
90 | // 拿到menuList
91 | store.commit("setMenuList", res.data.data.nav)
92 |
93 | // 拿到用户权限
94 | store.commit("setPermList", res.data.data.authoritys)
95 |
96 | console.log(store.state.menus.menuList)
97 |
98 | // 动态绑定路由
99 | let newRoutes = router.options.routes
100 |
101 | res.data.data.nav.forEach(menu => {
102 | if (menu.children) {
103 | menu.children.forEach(e => {
104 |
105 | // 转成路由
106 | let route = menuToRoute(e)
107 |
108 | // 吧路由添加到路由管理中
109 | if (route) {
110 | newRoutes[0].children.push(route)
111 | }
112 |
113 | })
114 | }
115 | })
116 |
117 | console.log("newRoutes")
118 | console.log(newRoutes)
119 | router.addRoutes(newRoutes)
120 |
121 | hasRoute = true
122 | store.commit("changeRouteStatus", hasRoute)
123 | })
124 | }
125 |
126 |
127 |
128 | next()
129 | })
130 |
131 |
132 | // 导航转成路由
133 | const menuToRoute = (menu) => {
134 |
135 | if (!menu.component) {
136 | return null
137 | }
138 |
139 | let route = {
140 | name: menu.name,
141 | path: menu.path,
142 | meta: {
143 | icon: menu.icon,
144 | title: menu.title
145 | }
146 | }
147 | route.component = () => import('@/views/' + menu.component +'.vue')
148 |
149 | return route
150 | }
151 |
152 | export default router
153 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.config;
2 |
3 | import com.markerhub.security.*;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.EnableWebSecurity;
11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
12 | import org.springframework.security.config.http.SessionCreationPolicy;
13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
14 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
15 |
16 | @Configuration
17 | @EnableWebSecurity
18 | @EnableGlobalMethodSecurity(prePostEnabled = true)
19 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
20 |
21 | @Autowired
22 | LoginFailureHandler loginFailureHandler;
23 |
24 | @Autowired
25 | LoginSuccessHandler loginSuccessHandler;
26 |
27 | @Autowired
28 | CaptchaFilter captchaFilter;
29 |
30 | @Autowired
31 | JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
32 |
33 | @Autowired
34 | JwtAccessDeniedHandler jwtAccessDeniedHandler;
35 |
36 | @Autowired
37 | UserDetailServiceImpl userDetailService;
38 |
39 | @Autowired
40 | JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
41 |
42 | @Bean
43 | JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
44 | JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
45 | return jwtAuthenticationFilter;
46 | }
47 |
48 | @Bean
49 | BCryptPasswordEncoder bCryptPasswordEncoder() {
50 | return new BCryptPasswordEncoder();
51 | }
52 |
53 | private static final String[] URL_WHITELIST = {
54 |
55 | "/login",
56 | "/logout",
57 | "/captcha",
58 | "/favicon.ico",
59 |
60 | };
61 |
62 |
63 | protected void configure(HttpSecurity http) throws Exception {
64 |
65 | http.cors().and().csrf().disable()
66 |
67 | // 登录配置
68 | .formLogin()
69 | .successHandler(loginSuccessHandler)
70 | .failureHandler(loginFailureHandler)
71 |
72 | .and()
73 | .logout()
74 | .logoutSuccessHandler(jwtLogoutSuccessHandler)
75 |
76 | // 禁用session
77 | .and()
78 | .sessionManagement()
79 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
80 |
81 | // 配置拦截规则
82 | .and()
83 | .authorizeRequests()
84 | .antMatchers(URL_WHITELIST).permitAll()
85 | .anyRequest().authenticated()
86 |
87 | // 异常处理器
88 | .and()
89 | .exceptionHandling()
90 | .authenticationEntryPoint(jwtAuthenticationEntryPoint)
91 | .accessDeniedHandler(jwtAccessDeniedHandler)
92 |
93 | // 配置自定义的过滤器
94 | .and()
95 | .addFilter(jwtAuthenticationFilter())
96 | .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
97 |
98 | ;
99 |
100 | }
101 |
102 | @Override
103 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
104 | auth.userDetailsService(userDetailService);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/service/impl/SysUserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
5 | import com.markerhub.entity.SysMenu;
6 | import com.markerhub.entity.SysRole;
7 | import com.markerhub.entity.SysUser;
8 | import com.markerhub.mapper.SysUserMapper;
9 | import com.markerhub.service.SysMenuService;
10 | import com.markerhub.service.SysRoleService;
11 | import com.markerhub.service.SysUserService;
12 | import com.markerhub.utils.RedisUtil;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Service;
15 |
16 | import java.util.List;
17 | import java.util.stream.Collectors;
18 |
19 | /**
20 | *
21 | * 服务实现类
22 | *
23 | *
24 | * @author 我的公众号:MarkerHub
25 | * @since 2021-04-05
26 | */
27 | @Service
28 | public class SysUserServiceImpl extends ServiceImpl implements SysUserService {
29 |
30 | @Autowired
31 | SysRoleService sysRoleService;
32 |
33 | @Autowired
34 | SysUserMapper sysUserMapper;
35 |
36 | @Autowired
37 | SysMenuService sysMenuService;
38 |
39 | @Autowired
40 | RedisUtil redisUtil;
41 |
42 | @Override
43 | public SysUser getByUsername(String username) {
44 | return getOne(new QueryWrapper().eq("username", username));
45 | }
46 |
47 | @Override
48 | public String getUserAuthorityInfo(Long userId) {
49 |
50 | SysUser sysUser = sysUserMapper.selectById(userId);
51 |
52 | // ROLE_admin,ROLE_normal,sys:user:list,....
53 | String authority = "";
54 |
55 | if (redisUtil.hasKey("GrantedAuthority:" + sysUser.getUsername())) {
56 | authority = (String) redisUtil.get("GrantedAuthority:" + sysUser.getUsername());
57 |
58 | } else {
59 | // 获取角色编码
60 | List roles = sysRoleService.list(new QueryWrapper()
61 | .inSql("id", "select role_id from sys_user_role where user_id = " + userId));
62 |
63 | if (roles.size() > 0) {
64 | String roleCodes = roles.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
65 | authority = roleCodes.concat(",");
66 | }
67 |
68 | // 获取菜单操作编码
69 | List menuIds = sysUserMapper.getNavMenuIds(userId);
70 | if (menuIds.size() > 0) {
71 |
72 | List menus = sysMenuService.listByIds(menuIds);
73 | String menuPerms = menus.stream().map(m -> m.getPerms()).collect(Collectors.joining(","));
74 |
75 | authority = authority.concat(menuPerms);
76 | }
77 |
78 | redisUtil.set("GrantedAuthority:" + sysUser.getUsername(), authority, 60 * 60);
79 | }
80 |
81 | return authority;
82 | }
83 |
84 | @Override
85 | public void clearUserAuthorityInfo(String username) {
86 | redisUtil.del("GrantedAuthority:" + username);
87 | }
88 |
89 | @Override
90 | public void clearUserAuthorityInfoByRoleId(Long roleId) {
91 |
92 | List sysUsers = this.list(new QueryWrapper()
93 | .inSql("id", "select user_id from sys_user_role where role_id = " + roleId));
94 |
95 | sysUsers.forEach(u -> {
96 | this.clearUserAuthorityInfo(u.getUsername());
97 | });
98 |
99 | }
100 |
101 | @Override
102 | public void clearUserAuthorityInfoByMenuId(Long menuId) {
103 | List sysUsers = sysUserMapper.listByMenuId(menuId);
104 |
105 | sysUsers.forEach(u -> {
106 | this.clearUserAuthorityInfo(u.getUsername());
107 | });
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/SysMenuController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 |
4 | import cn.hutool.core.map.MapUtil;
5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 | import com.markerhub.common.dto.SysMenuDto;
7 | import com.markerhub.common.lang.Const;
8 | import com.markerhub.common.lang.Result;
9 | import com.markerhub.entity.SysMenu;
10 | import com.markerhub.entity.SysRoleMenu;
11 | import com.markerhub.entity.SysUser;
12 | import org.apache.ibatis.executor.ResultExtractor;
13 | import org.springframework.security.access.prepost.PreAuthorize;
14 | import org.springframework.util.StringUtils;
15 | import org.springframework.validation.annotation.Validated;
16 | import org.springframework.web.bind.annotation.*;
17 |
18 | import java.security.Principal;
19 | import java.time.LocalDateTime;
20 | import java.util.List;
21 |
22 | /**
23 | *
24 | * 前端控制器
25 | *
26 | *
27 | * @author 我的公众号:MarkerHub
28 | * @since 2021-04-05
29 | */
30 | @RestController
31 | @RequestMapping("/sys/menu")
32 | public class SysMenuController extends BaseController {
33 |
34 | /**
35 | * 用户当前用户的菜单和权限信息
36 | * @param principal
37 | * @return
38 | */
39 | @GetMapping("/nav")
40 | public Result nav(Principal principal) {
41 | SysUser sysUser = sysUserService.getByUsername(principal.getName());
42 |
43 | // 获取权限信息
44 | String authorityInfo = sysUserService.getUserAuthorityInfo(sysUser.getId());// ROLE_admin,ROLE_normal,sys:user:list,....
45 | String[] authorityInfoArray = StringUtils.tokenizeToStringArray(authorityInfo, ",");
46 |
47 | // 获取导航栏信息
48 | List navs = sysMenuService.getCurrentUserNav();
49 |
50 | return Result.succ(MapUtil.builder()
51 | .put("authoritys", authorityInfoArray)
52 | .put("nav", navs)
53 | .map()
54 | );
55 | }
56 |
57 | @GetMapping("/info/{id}")
58 | @PreAuthorize("hasAuthority('sys:menu:list')")
59 | public Result info(@PathVariable(name = "id") Long id) {
60 | return Result.succ(sysMenuService.getById(id));
61 | }
62 |
63 | @GetMapping("/list")
64 | @PreAuthorize("hasAuthority('sys:menu:list')")
65 | public Result list() {
66 |
67 | List menus = sysMenuService.tree();
68 | return Result.succ(menus);
69 | }
70 |
71 | @PostMapping("/save")
72 | @PreAuthorize("hasAuthority('sys:menu:save')")
73 | public Result save(@Validated @RequestBody SysMenu sysMenu) {
74 |
75 | sysMenu.setCreated(LocalDateTime.now());
76 |
77 | sysMenuService.save(sysMenu);
78 | return Result.succ(sysMenu);
79 | }
80 |
81 | @PostMapping("/update")
82 | @PreAuthorize("hasAuthority('sys:menu:update')")
83 | public Result update(@Validated @RequestBody SysMenu sysMenu) {
84 |
85 | sysMenu.setUpdated(LocalDateTime.now());
86 |
87 | sysMenuService.updateById(sysMenu);
88 |
89 | // 清除所有与该菜单相关的权限缓存
90 | sysUserService.clearUserAuthorityInfoByMenuId(sysMenu.getId());
91 | return Result.succ(sysMenu);
92 | }
93 |
94 | @PostMapping("/delete/{id}")
95 | @PreAuthorize("hasAuthority('sys:menu:delete')")
96 | public Result delete(@PathVariable("id") Long id) {
97 |
98 | int count = sysMenuService.count(new QueryWrapper().eq("parent_id", id));
99 | if (count > 0) {
100 | return Result.fail("请先删除子菜单");
101 | }
102 |
103 | // 清除所有与该菜单相关的权限缓存
104 | sysUserService.clearUserAuthorityInfoByMenuId(id);
105 |
106 | sysMenuService.removeById(id);
107 |
108 | // 同步删除中间关联表
109 | sysRoleMenuService.remove(new QueryWrapper().eq("menu_id", id));
110 | return Result.succ("");
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 欢迎来到VueAdmin管理系统
5 |
6 |
7 | 公众号 MarkerHub
8 | 扫码二维码,回复【 VueAdmin 】获取登录密码
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 立即创建
30 | 重置
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
107 |
108 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/SysRoleController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 |
4 | import cn.hutool.core.util.StrUtil;
5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
7 | import com.markerhub.common.lang.Const;
8 | import com.markerhub.common.lang.Result;
9 | import com.markerhub.entity.SysRole;
10 | import com.markerhub.entity.SysRoleMenu;
11 | import com.markerhub.entity.SysUserRole;
12 | import org.springframework.security.access.prepost.PreAuthorize;
13 | import org.springframework.transaction.annotation.Transactional;
14 | import org.springframework.validation.annotation.Validated;
15 | import org.springframework.web.bind.annotation.*;
16 |
17 | import java.time.LocalDateTime;
18 | import java.util.ArrayList;
19 | import java.util.Arrays;
20 | import java.util.List;
21 | import java.util.stream.Collectors;
22 |
23 | /**
24 | *
25 | * 前端控制器
26 | * swagger2
27 | *
28 | *
29 | * @author 我的公众号:MarkerHub
30 | * @since 2021-04-05
31 | */
32 | @RestController
33 | @RequestMapping("/sys/role")
34 | public class SysRoleController extends BaseController {
35 |
36 | @PreAuthorize("hasAuthority('sys:role:list')")
37 | @GetMapping("/info/{id}")
38 | public Result info(@PathVariable("id") Long id) {
39 |
40 | SysRole sysRole = sysRoleService.getById(id);
41 |
42 | // 获取角色相关联的菜单id
43 | List roleMenus = sysRoleMenuService.list(new QueryWrapper().eq("role_id", id));
44 | List menuIds = roleMenus.stream().map(p -> p.getMenuId()).collect(Collectors.toList());
45 |
46 | sysRole.setMenuIds(menuIds);
47 | return Result.succ(sysRole);
48 | }
49 |
50 | @PreAuthorize("hasAuthority('sys:role:list')")
51 | @GetMapping("/list")
52 | public Result list(String name) {
53 |
54 | Page pageData = sysRoleService.page(getPage(),
55 | new QueryWrapper()
56 | .like(StrUtil.isNotBlank(name), "name", name)
57 | );
58 |
59 | return Result.succ(pageData);
60 | }
61 |
62 | @PostMapping("/save")
63 | @PreAuthorize("hasAuthority('sys:role:save')")
64 | public Result save(@Validated @RequestBody SysRole sysRole) {
65 |
66 | sysRole.setCreated(LocalDateTime.now());
67 | sysRole.setStatu(Const.STATUS_ON);
68 |
69 | sysRoleService.save(sysRole);
70 | return Result.succ(sysRole);
71 | }
72 |
73 | @PostMapping("/update")
74 | @PreAuthorize("hasAuthority('sys:role:update')")
75 | public Result update(@Validated @RequestBody SysRole sysRole) {
76 |
77 | sysRole.setUpdated(LocalDateTime.now());
78 |
79 | sysRoleService.updateById(sysRole);
80 |
81 | // 更新缓存
82 | sysUserService.clearUserAuthorityInfoByRoleId(sysRole.getId());
83 |
84 | return Result.succ(sysRole);
85 | }
86 |
87 | @PostMapping("/delete")
88 | @PreAuthorize("hasAuthority('sys:role:delete')")
89 | @Transactional
90 | public Result info(@RequestBody Long[] ids) {
91 |
92 | sysRoleService.removeByIds(Arrays.asList(ids));
93 |
94 | // 删除中间表
95 | sysUserRoleService.remove(new QueryWrapper().in("role_id", ids));
96 | sysRoleMenuService.remove(new QueryWrapper().in("role_id", ids));
97 |
98 | // 缓存同步删除
99 | Arrays.stream(ids).forEach(id -> {
100 | // 更新缓存
101 | sysUserService.clearUserAuthorityInfoByRoleId(id);
102 | });
103 |
104 | return Result.succ("");
105 | }
106 |
107 | @Transactional
108 | @PostMapping("/perm/{roleId}")
109 | @PreAuthorize("hasAuthority('sys:role:perm')")
110 | public Result info(@PathVariable("roleId") Long roleId, @RequestBody Long[] menuIds) {
111 |
112 | List sysRoleMenus = new ArrayList<>();
113 |
114 | Arrays.stream(menuIds).forEach(menuId -> {
115 | SysRoleMenu roleMenu = new SysRoleMenu();
116 | roleMenu.setMenuId(menuId);
117 | roleMenu.setRoleId(roleId);
118 |
119 | sysRoleMenus.add(roleMenu);
120 | });
121 |
122 | // 先删除原来的记录,再保存新的
123 | sysRoleMenuService.remove(new QueryWrapper().eq("role_id", roleId));
124 | sysRoleMenuService.saveBatch(sysRoleMenus);
125 |
126 | // 删除缓存
127 | sysUserService.clearUserAuthorityInfoByRoleId(roleId);
128 |
129 | return Result.succ(menuIds);
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/vueadmin-java/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.0
9 |
10 |
11 | com.markerhub
12 | vueadmin-java
13 | 0.0.1-SNAPSHOT
14 | vueadmin-java
15 | Demo project for Spring Boot
16 |
17 | 1.8
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-devtools
28 | runtime
29 | true
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-test
39 | test
40 |
41 |
42 |
43 |
44 | com.baomidou
45 | mybatis-plus-boot-starter
46 | 3.4.1
47 |
48 |
49 |
50 | com.baomidou
51 | mybatis-plus-generator
52 | 3.4.1
53 |
54 |
55 | org.freemarker
56 | freemarker
57 | 2.3.30
58 |
59 |
60 | mysql
61 | mysql-connector-java
62 | runtime
63 |
64 |
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-starter-security
69 |
70 |
71 | org.springframework.boot
72 | spring-boot-starter-data-redis
73 |
74 |
75 |
76 | io.jsonwebtoken
77 | jjwt
78 | 0.9.1
79 |
80 |
81 | com.github.axet
82 | kaptcha
83 | 0.0.9
84 |
85 |
86 |
87 | cn.hutool
88 | hutool-all
89 | 5.3.3
90 |
91 |
92 | org.apache.commons
93 | commons-lang3
94 | 3.11
95 |
96 |
97 |
98 | org.springframework.boot
99 | spring-boot-starter-validation
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | org.springframework.boot
108 | spring-boot-maven-plugin
109 |
110 |
111 |
112 | org.projectlombok
113 | lombok
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/controller/SysUserController.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.controller;
2 |
3 |
4 | import cn.hutool.core.util.StrUtil;
5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
7 | import com.markerhub.common.dto.PassDto;
8 | import com.markerhub.common.lang.Const;
9 | import com.markerhub.common.lang.Result;
10 | import com.markerhub.entity.SysRole;
11 | import com.markerhub.entity.SysUser;
12 | import com.markerhub.entity.SysUserRole;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.security.access.prepost.PreAuthorize;
15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
16 | import org.springframework.transaction.annotation.Transactional;
17 | import org.springframework.util.Assert;
18 | import org.springframework.validation.annotation.Validated;
19 | import org.springframework.web.bind.annotation.*;
20 |
21 | import java.security.Principal;
22 | import java.time.LocalDateTime;
23 | import java.util.ArrayList;
24 | import java.util.Arrays;
25 | import java.util.List;
26 |
27 | /**
28 | *
29 | * 前端控制器
30 | *
31 | *
32 | * @author 我的公众号:MarkerHub
33 | * @since 2021-04-05
34 | */
35 | @RestController
36 | @RequestMapping("/sys/user")
37 | public class SysUserController extends BaseController {
38 |
39 | @Autowired
40 | BCryptPasswordEncoder passwordEncoder;
41 |
42 | @GetMapping("/info/{id}")
43 | @PreAuthorize("hasAuthority('sys:user:list')")
44 | public Result info(@PathVariable("id") Long id) {
45 |
46 | SysUser sysUser = sysUserService.getById(id);
47 | Assert.notNull(sysUser, "找不到该管理员");
48 |
49 | List roles = sysRoleService.listRolesByUserId(id);
50 |
51 | sysUser.setSysRoles(roles);
52 | return Result.succ(sysUser);
53 | }
54 |
55 | @GetMapping("/list")
56 | @PreAuthorize("hasAuthority('sys:user:list')")
57 | public Result list(String username) {
58 |
59 | Page pageData = sysUserService.page(getPage(), new QueryWrapper()
60 | .like(StrUtil.isNotBlank(username), "username", username));
61 |
62 | pageData.getRecords().forEach(u -> {
63 |
64 | u.setSysRoles(sysRoleService.listRolesByUserId(u.getId()));
65 | });
66 |
67 | return Result.succ(pageData);
68 | }
69 |
70 | @PostMapping("/save")
71 | @PreAuthorize("hasAuthority('sys:user:save')")
72 | public Result save(@Validated @RequestBody SysUser sysUser) {
73 |
74 | sysUser.setCreated(LocalDateTime.now());
75 | sysUser.setStatu(Const.STATUS_ON);
76 |
77 | // 默认密码
78 | String password = passwordEncoder.encode(Const.DEFULT_PASSWORD);
79 | sysUser.setPassword(password);
80 |
81 | // 默认头像
82 | sysUser.setAvatar(Const.DEFULT_AVATAR);
83 |
84 | sysUserService.save(sysUser);
85 | return Result.succ(sysUser);
86 | }
87 |
88 | @PostMapping("/update")
89 | @PreAuthorize("hasAuthority('sys:user:update')")
90 | public Result update(@Validated @RequestBody SysUser sysUser) {
91 |
92 | sysUser.setUpdated(LocalDateTime.now());
93 |
94 | sysUserService.updateById(sysUser);
95 | return Result.succ(sysUser);
96 | }
97 |
98 | @Transactional
99 | @PostMapping("/delete")
100 | @PreAuthorize("hasAuthority('sys:user:delete')")
101 | public Result delete(@RequestBody Long[] ids) {
102 |
103 | sysUserService.removeByIds(Arrays.asList(ids));
104 | sysUserRoleService.remove(new QueryWrapper().in("user_id", ids));
105 |
106 | return Result.succ("");
107 | }
108 |
109 | @Transactional
110 | @PostMapping("/role/{userId}")
111 | @PreAuthorize("hasAuthority('sys:user:role')")
112 | public Result rolePerm(@PathVariable("userId") Long userId, @RequestBody Long[] roleIds) {
113 |
114 | List userRoles = new ArrayList<>();
115 |
116 | Arrays.stream(roleIds).forEach(r -> {
117 | SysUserRole sysUserRole = new SysUserRole();
118 | sysUserRole.setRoleId(r);
119 | sysUserRole.setUserId(userId);
120 |
121 | userRoles.add(sysUserRole);
122 | });
123 |
124 | sysUserRoleService.remove(new QueryWrapper().eq("user_id", userId));
125 | sysUserRoleService.saveBatch(userRoles);
126 |
127 | // 删除缓存
128 | SysUser sysUser = sysUserService.getById(userId);
129 | sysUserService.clearUserAuthorityInfo(sysUser.getUsername());
130 |
131 | return Result.succ("");
132 | }
133 |
134 | @PostMapping("/repass")
135 | @PreAuthorize("hasAuthority('sys:user:repass')")
136 | public Result repass(@RequestBody Long userId) {
137 |
138 | SysUser sysUser = sysUserService.getById(userId);
139 |
140 | sysUser.setPassword(passwordEncoder.encode(Const.DEFULT_PASSWORD));
141 | sysUser.setUpdated(LocalDateTime.now());
142 |
143 | sysUserService.updateById(sysUser);
144 | return Result.succ("");
145 | }
146 |
147 | @PostMapping("/updatePass")
148 | public Result updatePass(@Validated @RequestBody PassDto passDto, Principal principal) {
149 |
150 | SysUser sysUser = sysUserService.getByUsername(principal.getName());
151 |
152 | boolean matches = passwordEncoder.matches(passDto.getCurrentPass(), sysUser.getPassword());
153 | if (!matches) {
154 | return Result.fail("旧密码不正确");
155 | }
156 |
157 | sysUser.setPassword(passwordEncoder.encode(passDto.getPassword()));
158 | sysUser.setUpdated(LocalDateTime.now());
159 |
160 | sysUserService.updateById(sysUser);
161 | return Result.succ("");
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/CodeGenerator.java:
--------------------------------------------------------------------------------
1 | package com.markerhub;
2 |
3 | import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
4 | import com.baomidou.mybatisplus.core.toolkit.StringPool;
5 | import com.baomidou.mybatisplus.core.toolkit.StringUtils;
6 | import com.baomidou.mybatisplus.generator.AutoGenerator;
7 | import com.baomidou.mybatisplus.generator.InjectionConfig;
8 | import com.baomidou.mybatisplus.generator.config.*;
9 | import com.baomidou.mybatisplus.generator.config.po.TableInfo;
10 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
11 | import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 | import java.util.Scanner;
16 |
17 | // 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
18 | public class CodeGenerator {
19 |
20 | /**
21 | *
22 | * 读取控制台内容
23 | *
24 | */
25 | public static String scanner(String tip) {
26 | Scanner scanner = new Scanner(System.in);
27 | StringBuilder help = new StringBuilder();
28 | help.append("请输入" + tip + ":");
29 | System.out.println(help.toString());
30 | if (scanner.hasNext()) {
31 | String ipt = scanner.next();
32 | if (StringUtils.isNotBlank(ipt)) {
33 | return ipt;
34 | }
35 | }
36 | throw new MybatisPlusException("请输入正确的" + tip + "!");
37 | }
38 |
39 | public static void main(String[] args) {
40 | // 代码生成器
41 | AutoGenerator mpg = new AutoGenerator();
42 |
43 | // 全局配置
44 | GlobalConfig gc = new GlobalConfig();
45 | String projectPath = System.getProperty("user.dir");
46 | gc.setOutputDir(projectPath + "/src/main/java");
47 | gc.setAuthor("我的公众号:MarkerHub");
48 | gc.setOpen(false);
49 | // gc.setSwagger2(true); 实体属性 Swagger2 注解
50 | gc.setServiceName("%sService");
51 | mpg.setGlobalConfig(gc);
52 |
53 | // 数据源配置
54 | DataSourceConfig dsc = new DataSourceConfig();
55 | dsc.setUrl("jdbc:mysql://localhost:3306/vueadmin?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
56 | // dsc.setSchemaName("public");
57 | dsc.setDriverName("com.mysql.cj.jdbc.Driver");
58 | dsc.setUsername("root");
59 | dsc.setPassword("admin");
60 | mpg.setDataSource(dsc);
61 |
62 | // 包配置
63 | PackageConfig pc = new PackageConfig();
64 | // pc.setModuleName(scanner("模块名"));
65 | pc.setParent("com.markerhub");
66 | mpg.setPackageInfo(pc);
67 |
68 | // 自定义配置
69 | InjectionConfig cfg = new InjectionConfig() {
70 | @Override
71 | public void initMap() {
72 | // to do nothing
73 | }
74 | };
75 |
76 | // 如果模板引擎是 freemarker
77 | String templatePath = "/templates/mapper.xml.ftl";
78 | // 如果模板引擎是 velocity
79 | // String templatePath = "/templates/mapper.xml.vm";
80 |
81 | // 自定义输出配置
82 | List focList = new ArrayList<>();
83 | // 自定义配置会被优先输出
84 | focList.add(new FileOutConfig(templatePath) {
85 | @Override
86 | public String outputFile(TableInfo tableInfo) {
87 | // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
88 | return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
89 | + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
90 | }
91 | });
92 | /*
93 | cfg.setFileCreate(new IFileCreate() {
94 | @Override
95 | public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
96 | // 判断自定义文件夹是否需要创建
97 | checkDir("调用默认方法创建的目录,自定义目录用");
98 | if (fileType == FileType.MAPPER) {
99 | // 已经生成 mapper 文件判断存在,不想重新生成返回 false
100 | return !new File(filePath).exists();
101 | }
102 | // 允许生成模板文件
103 | return true;
104 | }
105 | });
106 | */
107 | cfg.setFileOutConfigList(focList);
108 | mpg.setCfg(cfg);
109 |
110 | // 配置模板
111 | TemplateConfig templateConfig = new TemplateConfig();
112 |
113 | // 配置自定义输出模板
114 | //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
115 | // templateConfig.setEntity("templates/entity2.java");
116 | // templateConfig.setService();
117 | // templateConfig.setController();
118 |
119 | templateConfig.setXml(null);
120 | mpg.setTemplate(templateConfig);
121 |
122 | // 策略配置
123 | StrategyConfig strategy = new StrategyConfig();
124 | strategy.setNaming(NamingStrategy.underline_to_camel);
125 | strategy.setColumnNaming(NamingStrategy.underline_to_camel);
126 | strategy.setSuperEntityClass("BaseEntity");
127 | strategy.setEntityLombokModel(true);
128 | strategy.setRestControllerStyle(true);
129 | // 公共父类
130 | strategy.setSuperControllerClass("BaseController");
131 | // 写于父类中的公共字段
132 | strategy.setSuperEntityColumns("id", "created", "updated", "statu");
133 | strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
134 | strategy.setControllerMappingHyphenStyle(true);
135 | // strategy.setTablePrefix("sys_");//动态调整
136 | mpg.setStrategy(strategy);
137 | mpg.setTemplateEngine(new FreemarkerTemplateEngine());
138 | mpg.execute();
139 | }
140 |
141 | }
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/sys/Menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 新增
7 |
8 |
9 |
10 |
18 |
19 |
24 |
25 |
30 |
31 |
32 |
35 |
36 |
37 |
40 |
41 | 目录
42 | 菜单
43 | 按钮
44 |
45 |
46 |
47 |
48 |
51 |
52 |
55 |
56 |
59 |
60 |
63 |
64 | 正常
65 | 禁用
66 |
67 |
68 |
69 |
72 |
73 |
74 | 编辑
75 |
76 |
77 |
78 |
79 | 删除
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | {{ "- " + child.name }}
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | 目录
133 | 菜单
134 | 按钮
135 |
136 |
137 |
138 |
139 |
140 | 禁用
141 | 正常
142 |
143 |
144 |
145 |
146 | 1
147 |
148 |
149 |
150 |
151 | 立即创建
152 | 重置
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
258 |
259 |
--------------------------------------------------------------------------------
/vueadmin-java/数据库脚本 - vueadmin.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : pro-markerhub
5 | Source Server Version : 50727
6 | Source Host : 129.204.23.53:3306
7 | Source Database : vueadmin
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50727
11 | File Encoding : 65001
12 |
13 | Date: 2021-01-30 21:02:31
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for sys_menu
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `sys_menu`;
22 | CREATE TABLE `sys_menu` (
23 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
24 | `parent_id` bigint(20) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0',
25 | `name` varchar(64) NOT NULL,
26 | `path` varchar(255) DEFAULT NULL COMMENT '菜单URL',
27 | `perms` varchar(255) DEFAULT NULL COMMENT '授权(多个用逗号分隔,如:user:list,user:create)',
28 | `component` varchar(255) DEFAULT NULL,
29 | `type` int(5) NOT NULL COMMENT '类型 0:目录 1:菜单 2:按钮',
30 | `icon` varchar(32) DEFAULT NULL COMMENT '菜单图标',
31 | `orderNum` int(11) DEFAULT NULL COMMENT '排序',
32 | `created` datetime NOT NULL,
33 | `updated` datetime DEFAULT NULL,
34 | `statu` int(5) NOT NULL,
35 | PRIMARY KEY (`id`),
36 | UNIQUE KEY `name` (`name`) USING BTREE
37 | ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
38 |
39 | -- ----------------------------
40 | -- Records of sys_menu
41 | -- ----------------------------
42 | INSERT INTO `sys_menu` VALUES ('1', '0', '系统管理', '', 'sys:manage', '', '0', 'el-icon-s-operation', '1', '2021-01-15 18:58:18', '2021-01-15 18:58:20', '1');
43 | INSERT INTO `sys_menu` VALUES ('2', '1', '用户管理', '/sys/users', 'sys:user:list', 'sys/User', '1', 'el-icon-s-custom', '1', '2021-01-15 19:03:45', '2021-01-15 19:03:48', '1');
44 | INSERT INTO `sys_menu` VALUES ('3', '1', '角色管理', '/sys/roles', 'sys:role:list', 'sys/Role', '1', 'el-icon-rank', '2', '2021-01-15 19:03:45', '2021-01-15 19:03:48', '1');
45 | INSERT INTO `sys_menu` VALUES ('4', '1', '菜单管理', '/sys/menus', 'sys:menu:list', 'sys/Menu', '1', 'el-icon-menu', '3', '2021-01-15 19:03:45', '2021-01-15 19:03:48', '1');
46 | INSERT INTO `sys_menu` VALUES ('5', '0', '系统工具', '', 'sys:tools', null, '0', 'el-icon-s-tools', '2', '2021-01-15 19:06:11', null, '1');
47 | INSERT INTO `sys_menu` VALUES ('6', '5', '数字字典', '/sys/dicts', 'sys:dict:list', 'sys/Dict', '1', 'el-icon-s-order', '1', '2021-01-15 19:07:18', '2021-01-18 16:32:13', '1');
48 | INSERT INTO `sys_menu` VALUES ('7', '3', '添加角色', '', 'sys:role:save', '', '2', '', '1', '2021-01-15 23:02:25', '2021-01-17 21:53:14', '0');
49 | INSERT INTO `sys_menu` VALUES ('9', '2', '添加用户', null, 'sys:user:save', null, '2', null, '1', '2021-01-17 21:48:32', null, '1');
50 | INSERT INTO `sys_menu` VALUES ('10', '2', '修改用户', null, 'sys:user:update', null, '2', null, '2', '2021-01-17 21:49:03', '2021-01-17 21:53:04', '1');
51 | INSERT INTO `sys_menu` VALUES ('11', '2', '删除用户', null, 'sys:user:delete', null, '2', null, '3', '2021-01-17 21:49:21', null, '1');
52 | INSERT INTO `sys_menu` VALUES ('12', '2', '分配角色', null, 'sys:user:role', null, '2', null, '4', '2021-01-17 21:49:58', null, '1');
53 | INSERT INTO `sys_menu` VALUES ('13', '2', '重置密码', null, 'sys:user:repass', null, '2', null, '5', '2021-01-17 21:50:36', null, '1');
54 | INSERT INTO `sys_menu` VALUES ('14', '3', '修改角色', null, 'sys:role:update', null, '2', null, '2', '2021-01-17 21:51:14', null, '1');
55 | INSERT INTO `sys_menu` VALUES ('15', '3', '删除角色', null, 'sys:role:delete', null, '2', null, '3', '2021-01-17 21:51:39', null, '1');
56 | INSERT INTO `sys_menu` VALUES ('16', '3', '分配权限', null, 'sys:role:perm', null, '2', null, '5', '2021-01-17 21:52:02', null, '1');
57 | INSERT INTO `sys_menu` VALUES ('17', '4', '添加菜单', null, 'sys:menu:save', null, '2', null, '1', '2021-01-17 21:53:53', '2021-01-17 21:55:28', '1');
58 | INSERT INTO `sys_menu` VALUES ('18', '4', '修改菜单', null, 'sys:menu:update', null, '2', null, '2', '2021-01-17 21:56:12', null, '1');
59 | INSERT INTO `sys_menu` VALUES ('19', '4', '删除菜单', null, 'sys:menu:delete', null, '2', null, '3', '2021-01-17 21:56:36', null, '1');
60 |
61 | -- ----------------------------
62 | -- Table structure for sys_role
63 | -- ----------------------------
64 | DROP TABLE IF EXISTS `sys_role`;
65 | CREATE TABLE `sys_role` (
66 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
67 | `name` varchar(64) NOT NULL,
68 | `code` varchar(64) NOT NULL,
69 | `remark` varchar(64) DEFAULT NULL COMMENT '备注',
70 | `created` datetime DEFAULT NULL,
71 | `updated` datetime DEFAULT NULL,
72 | `statu` int(5) NOT NULL,
73 | PRIMARY KEY (`id`),
74 | UNIQUE KEY `name` (`name`) USING BTREE,
75 | UNIQUE KEY `code` (`code`) USING BTREE
76 | ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
77 |
78 | -- ----------------------------
79 | -- Records of sys_role
80 | -- ----------------------------
81 | INSERT INTO `sys_role` VALUES ('3', '普通用户', 'normal', '只有基本查看功能', '2021-01-04 10:09:14', '2021-01-30 08:19:52', '1');
82 | INSERT INTO `sys_role` VALUES ('6', '超级管理员', 'admin', '系统默认最高权限,不可以编辑和任意修改', '2021-01-16 13:29:03', '2021-01-17 15:50:45', '1');
83 |
84 | -- ----------------------------
85 | -- Table structure for sys_role_menu
86 | -- ----------------------------
87 | DROP TABLE IF EXISTS `sys_role_menu`;
88 | CREATE TABLE `sys_role_menu` (
89 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
90 | `role_id` bigint(20) NOT NULL,
91 | `menu_id` bigint(20) NOT NULL,
92 | PRIMARY KEY (`id`)
93 | ) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8mb4;
94 |
95 | -- ----------------------------
96 | -- Records of sys_role_menu
97 | -- ----------------------------
98 | INSERT INTO `sys_role_menu` VALUES ('60', '6', '1');
99 | INSERT INTO `sys_role_menu` VALUES ('61', '6', '2');
100 | INSERT INTO `sys_role_menu` VALUES ('62', '6', '9');
101 | INSERT INTO `sys_role_menu` VALUES ('63', '6', '10');
102 | INSERT INTO `sys_role_menu` VALUES ('64', '6', '11');
103 | INSERT INTO `sys_role_menu` VALUES ('65', '6', '12');
104 | INSERT INTO `sys_role_menu` VALUES ('66', '6', '13');
105 | INSERT INTO `sys_role_menu` VALUES ('67', '6', '3');
106 | INSERT INTO `sys_role_menu` VALUES ('68', '6', '7');
107 | INSERT INTO `sys_role_menu` VALUES ('69', '6', '14');
108 | INSERT INTO `sys_role_menu` VALUES ('70', '6', '15');
109 | INSERT INTO `sys_role_menu` VALUES ('71', '6', '16');
110 | INSERT INTO `sys_role_menu` VALUES ('72', '6', '4');
111 | INSERT INTO `sys_role_menu` VALUES ('73', '6', '17');
112 | INSERT INTO `sys_role_menu` VALUES ('74', '6', '18');
113 | INSERT INTO `sys_role_menu` VALUES ('75', '6', '19');
114 | INSERT INTO `sys_role_menu` VALUES ('76', '6', '5');
115 | INSERT INTO `sys_role_menu` VALUES ('77', '6', '6');
116 | INSERT INTO `sys_role_menu` VALUES ('96', '3', '1');
117 | INSERT INTO `sys_role_menu` VALUES ('97', '3', '2');
118 | INSERT INTO `sys_role_menu` VALUES ('98', '3', '3');
119 | INSERT INTO `sys_role_menu` VALUES ('99', '3', '4');
120 | INSERT INTO `sys_role_menu` VALUES ('100', '3', '5');
121 | INSERT INTO `sys_role_menu` VALUES ('101', '3', '6');
122 |
123 | -- ----------------------------
124 | -- Table structure for sys_user
125 | -- ----------------------------
126 | DROP TABLE IF EXISTS `sys_user`;
127 | CREATE TABLE `sys_user` (
128 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
129 | `username` varchar(64) DEFAULT NULL,
130 | `password` varchar(64) DEFAULT NULL,
131 | `avatar` varchar(255) DEFAULT NULL,
132 | `email` varchar(64) DEFAULT NULL,
133 | `city` varchar(64) DEFAULT NULL,
134 | `created` datetime DEFAULT NULL,
135 | `updated` datetime DEFAULT NULL,
136 | `last_login` datetime DEFAULT NULL,
137 | `statu` int(5) NOT NULL,
138 | PRIMARY KEY (`id`),
139 | UNIQUE KEY `UK_USERNAME` (`username`) USING BTREE
140 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
141 |
142 | -- ----------------------------
143 | -- Records of sys_user
144 | -- ----------------------------
145 | INSERT INTO `sys_user` VALUES ('1', 'admin', '$2a$10$R7zegeWzOXPw871CmNuJ6upC0v8D373GuLuTw8jn6NET4BkPRZfgK', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', '123@qq.com', '广州', '2021-01-12 22:13:53', '2021-01-16 16:57:32', '2020-12-30 08:38:37', '1');
146 | INSERT INTO `sys_user` VALUES ('2', 'test', '$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', 'test@qq.com', null, '2021-01-30 08:20:22', '2021-01-30 08:55:57', null, '1');
147 |
148 | -- ----------------------------
149 | -- Table structure for sys_user_role
150 | -- ----------------------------
151 | DROP TABLE IF EXISTS `sys_user_role`;
152 | CREATE TABLE `sys_user_role` (
153 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
154 | `user_id` bigint(20) NOT NULL,
155 | `role_id` bigint(20) NOT NULL,
156 | PRIMARY KEY (`id`)
157 | ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4;
158 |
159 | -- ----------------------------
160 | -- Records of sys_user_role
161 | -- ----------------------------
162 | INSERT INTO `sys_user_role` VALUES ('4', '1', '6');
163 | INSERT INTO `sys_user_role` VALUES ('7', '1', '3');
164 | INSERT INTO `sys_user_role` VALUES ('13', '2', '3');
165 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/sys/Role.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 | 搜索
15 |
16 |
17 |
18 | 新增
19 |
20 |
21 |
22 | 批量删除
23 |
24 |
25 |
26 |
27 |
35 |
36 |
39 |
40 |
41 |
45 |
46 |
50 |
51 |
55 |
56 |
57 |
60 |
61 | 正常
62 | 禁用
63 |
64 |
65 |
66 |
69 |
70 |
71 | 分配权限
72 |
73 |
74 | 编辑
75 |
76 |
77 |
78 |
79 | 删除
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
97 |
98 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | 禁用
125 | 正常
126 |
127 |
128 |
129 |
130 | 立即创建
131 | 重置
132 |
133 |
134 |
135 |
136 |
137 |
141 |
142 |
143 |
144 |
152 |
153 |
154 |
155 |
156 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
355 |
356 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/views/sys/User.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 | 搜索
15 |
16 |
17 |
18 | 新增
19 |
20 |
21 |
22 | 批量删除
23 |
24 |
25 |
26 |
27 |
35 |
36 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
57 |
58 | {{item.name}}
59 |
60 |
61 |
62 |
65 |
66 |
69 |
70 |
71 |
74 |
75 | 正常
76 | 禁用
77 |
78 |
79 |
80 |
85 |
86 |
90 |
91 |
92 | 分配角色
93 |
94 |
95 | 重置密码
96 |
97 |
98 | 编辑
99 |
100 |
101 |
102 |
103 | 删除
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
120 |
121 |
122 |
123 |
124 |
129 |
130 |
131 |
132 |
133 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | 禁用
151 | 正常
152 |
153 |
154 |
155 |
156 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
174 |
175 |
176 |
177 |
181 |
182 |
183 |
184 |
185 |
186 |
400 |
401 |
--------------------------------------------------------------------------------
/vueadmin-vue/src/mock.js:
--------------------------------------------------------------------------------
1 | const Mock = require('mockjs')
2 |
3 | const Random = Mock.Random
4 |
5 | let Result = {
6 | code: 200,
7 | msg: '操作成功',
8 | data: null
9 | }
10 |
11 | Mock.mock('/captcha', 'get', () => {
12 |
13 | Result.data = {
14 | token: Random.string(32),
15 | captchaImg: Random.dataImage('120x40', 'p7n5w')
16 | }
17 | return Result
18 | })
19 |
20 | Mock.mock('/login', 'post', () => {
21 |
22 | // 无法在header中传入数jwt
23 |
24 | // Result.code = 400
25 | // Result.msg = "验证码错误"
26 |
27 | return Result
28 | })
29 | Mock.mock('/sys/userInfo', 'get', () => {
30 |
31 | Result.data = {
32 | id: "1",
33 | username: "test",
34 | avatar: "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg"
35 | }
36 |
37 | return Result
38 | })
39 |
40 | Mock.mock('/logout', 'post', () => {
41 |
42 | return Result
43 | })
44 |
45 | // 获取用户菜单以及权限接口
46 | Mock.mock('/sys/menu/nav', 'get', () => {
47 |
48 | let nav = [
49 | {
50 | name: 'SysManga',
51 | title: '系统管理',
52 | icon: 'el-icon-s-operation',
53 | component: '',
54 | path: '',
55 | children: [
56 | {
57 | name: 'SysUser',
58 | title: '用户管理',
59 | icon: 'el-icon-s-custom',
60 | path: '/sys/users',
61 | component: 'sys/User',
62 | children: []
63 | },
64 | {
65 | name: 'SysRole',
66 | title: '角色管理',
67 | icon: 'el-icon-rank',
68 | path: '/sys/roles',
69 | component: 'sys/Role',
70 | children: []
71 | },
72 | {
73 | name: 'SysMenu',
74 | title: '菜单管理',
75 | icon: 'el-icon-menu',
76 | path: '/sys/menus',
77 | component: 'sys/Menu',
78 | children: []
79 | }
80 | ]
81 | },
82 | {
83 | name: 'SysTools',
84 | title: '系统工具',
85 | icon: 'el-icon-s-tools',
86 | path: '',
87 | component: '',
88 | children: [
89 | {
90 | name: 'SysDict',
91 | title: '数字字典',
92 | icon: 'el-icon-s-order',
93 | path: '/sys/dicts',
94 | component: '',
95 | children: []
96 | },
97 | ]
98 | }
99 | ]
100 |
101 | let authoritys = ['sys:user:list', "sys:user:save", "sys:user:delete"]
102 |
103 | Result.data = {
104 | nav: nav,
105 | authoritys: authoritys
106 | }
107 |
108 | return Result
109 | })
110 |
111 | //////////////// 菜单管理 ////////////////
112 |
113 | Mock.mock('/sys/menu/list', 'get', () => {
114 | let menus = [
115 | {
116 | "id": 1,
117 | "created": "2021-01-15T18:58:18",
118 | "updated": "2021-01-15T18:58:20",
119 | "statu": 1,
120 | "parentId": 0,
121 | "name": "系统管理",
122 | "path": "",
123 | "perms": "sys:manage",
124 | "component": "",
125 | "type": 0,
126 | "icon": "el-icon-s-operation",
127 | "ordernum": 1,
128 | "children": [
129 | {
130 | "id": 2,
131 | "created": "2021-01-15T19:03:45",
132 | "updated": "2021-01-15T19:03:48",
133 | "statu": 1,
134 | "parentId": 1,
135 | "name": "用户管理",
136 | "path": "/sys/users",
137 | "perms": "sys:user:list",
138 | "component": "sys/User",
139 | "type": 1,
140 | "icon": "el-icon-s-custom",
141 | "ordernum": 1,
142 | "children": [
143 | {
144 | "id": 9,
145 | "created": "2021-01-17T21:48:32",
146 | "updated": null,
147 | "statu": 1,
148 | "parentId": 2,
149 | "name": "添加用户",
150 | "path": null,
151 | "perms": "sys:user:save",
152 | "component": null,
153 | "type": 2,
154 | "icon": null,
155 | "ordernum": 1,
156 | "children": []
157 | },
158 | {
159 | "id": 10,
160 | "created": "2021-01-17T21:49:03",
161 | "updated": "2021-01-17T21:53:04",
162 | "statu": 1,
163 | "parentId": 2,
164 | "name": "修改用户",
165 | "path": null,
166 | "perms": "sys:user:update",
167 | "component": null,
168 | "type": 2,
169 | "icon": null,
170 | "ordernum": 2,
171 | "children": []
172 | },
173 | {
174 | "id": 11,
175 | "created": "2021-01-17T21:49:21",
176 | "updated": null,
177 | "statu": 1,
178 | "parentId": 2,
179 | "name": "删除用户",
180 | "path": null,
181 | "perms": "sys:user:delete",
182 | "component": null,
183 | "type": 2,
184 | "icon": null,
185 | "ordernum": 3,
186 | "children": []
187 | },
188 | {
189 | "id": 12,
190 | "created": "2021-01-17T21:49:58",
191 | "updated": null,
192 | "statu": 1,
193 | "parentId": 2,
194 | "name": "分配角色",
195 | "path": null,
196 | "perms": "sys:user:role",
197 | "component": null,
198 | "type": 2,
199 | "icon": null,
200 | "ordernum": 4,
201 | "children": []
202 | },
203 | {
204 | "id": 13,
205 | "created": "2021-01-17T21:50:36",
206 | "updated": null,
207 | "statu": 1,
208 | "parentId": 2,
209 | "name": "重置密码",
210 | "path": null,
211 | "perms": "sys:user:repass",
212 | "component": null,
213 | "type": 2,
214 | "icon": null,
215 | "ordernum": 5,
216 | "children": []
217 | }
218 | ]
219 | },
220 | {
221 | "id": 3,
222 | "created": "2021-01-15T19:03:45",
223 | "updated": "2021-01-15T19:03:48",
224 | "statu": 1,
225 | "parentId": 1,
226 | "name": "角色管理",
227 | "path": "/sys/roles",
228 | "perms": "sys:role:list",
229 | "component": "sys/Role",
230 | "type": 1,
231 | "icon": "el-icon-rank",
232 | "ordernum": 2,
233 | "children": []
234 | },
235 |
236 | ]
237 | },
238 | {
239 | "id": 5,
240 | "created": "2021-01-15T19:06:11",
241 | "updated": null,
242 | "statu": 1,
243 | "parentId": 0,
244 | "name": "系统工具",
245 | "path": "",
246 | "perms": "sys:tools",
247 | "component": null,
248 | "type": 0,
249 | "icon": "el-icon-s-tools",
250 | "ordernum": 2,
251 | "children": [
252 | {
253 | "id": 6,
254 | "created": "2021-01-15T19:07:18",
255 | "updated": "2021-01-18T16:32:13",
256 | "statu": 1,
257 | "parentId": 5,
258 | "name": "数字字典",
259 | "path": "/sys/dicts",
260 | "perms": "sys:dict:list",
261 | "component": "sys/Dict",
262 | "type": 1,
263 | "icon": "el-icon-s-order",
264 | "ordernum": 1,
265 | "children": []
266 | }
267 | ]
268 | }
269 | ]
270 |
271 | Result.data = menus
272 |
273 | return Result
274 | })
275 |
276 | Mock.mock(RegExp('/sys/menu/info/*'), 'get', () => {
277 |
278 | Result.data = {
279 | "id": 3,
280 | "statu": 1,
281 | "parentId": 1,
282 | "name": "角色管理",
283 | "path": "/sys/roles",
284 | "perms": "sys:role:list",
285 | "component": "sys/Role",
286 | "type": 1,
287 | "icon": "el-icon-rank",
288 | "orderNum": 2,
289 | "children": []
290 | }
291 |
292 | return Result
293 | })
294 |
295 |
296 | Mock.mock(RegExp('/sys/menu/*'), 'post', () => {
297 |
298 | return Result
299 | })
300 |
301 | //////////////// 角色管理 ////////////////
302 |
303 | Mock.mock(RegExp('/sys/role/list*'), 'get', () => {
304 |
305 | Result.data = {
306 | "records": [
307 | {
308 | "id": 3,
309 | "created": "2021-01-04T10:09:14",
310 | "updated": "2021-01-30T08:19:52",
311 | "statu": 1,
312 | "name": "普通用户",
313 | "code": "normal",
314 | "remark": "只有基本查看功能",
315 | "menuIds": []
316 | },
317 | {
318 | "id": 6,
319 | "created": "2021-01-16T13:29:03",
320 | "updated": "2021-01-17T15:50:45",
321 | "statu": 1,
322 | "name": "超级管理员",
323 | "code": "admin",
324 | "remark": "系统默认最高权限,不可以编辑和任意修改",
325 | "menuIds": []
326 | }
327 | ],
328 | "total": 2,
329 | "size": 10,
330 | "current": 1,
331 | "orders": [],
332 | "optimizeCountSql": true,
333 | "hitCount": false,
334 | "countId": null,
335 | "maxLimit": null,
336 | "searchCount": true,
337 | "pages": 1
338 | }
339 |
340 | return Result
341 |
342 | })
343 |
344 | Mock.mock(RegExp('/sys/role/info/*'), 'get', () => {
345 |
346 | Result.data = {
347 | "id": 6,
348 | "created": "2021-01-16T13:29:03",
349 | "updated": "2021-01-17T15:50:45",
350 | "statu": 1,
351 | "name": "超级管理员",
352 | "code": "admin",
353 | "remark": "系统默认最高权限,不可以编辑和任意修改",
354 | "menuIds": [3]
355 | }
356 |
357 | return Result
358 | })
359 |
360 | Mock.mock(RegExp('/sys/role/*'), 'post', () => {
361 |
362 | return Result
363 | })
364 |
365 | //////////////// 用户管理 ////////////////
366 |
367 | Mock.mock(RegExp('/sys/user/list*'), 'get', () => {
368 | Result.data = {
369 | "records": [
370 | {
371 | "id": 1,
372 | "created": "2021-01-12T22:13:53",
373 | "updated": "2021-01-16T16:57:32",
374 | "statu": 1,
375 | "username": "admin",
376 | "password": "$2a$10$R7zegeWzOXPw871CmNuJ6upC0v8D373GuLuTw8jn6NET4BkPRZfgK",
377 | "avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
378 | "email": "123@qq.com",
379 | "city": "广州",
380 | "lastLogin": "2020-12-30T08:38:37",
381 | "roles": [
382 | {
383 | "id": 6,
384 | "created": "2021-01-16T13:29:03",
385 | "updated": "2021-01-17T15:50:45",
386 | "statu": 1,
387 | "name": "超级管理员",
388 | "code": "admin",
389 | "remark": "系统默认最高权限,不可以编辑和任意修改",
390 | "menuIds": []
391 | },
392 | {
393 | "id": 3,
394 | "created": "2021-01-04T10:09:14",
395 | "updated": "2021-01-30T08:19:52",
396 | "statu": 1,
397 | "name": "普通用户",
398 | "code": "normal",
399 | "remark": "只有基本查看功能",
400 | "menuIds": []
401 | }
402 | ]
403 | },
404 | {
405 | "id": 2,
406 | "created": "2021-01-30T08:20:22",
407 | "updated": "2021-01-30T08:55:57",
408 | "statu": 1,
409 | "username": "test",
410 | "password": "$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO",
411 | "avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
412 | "email": "test@qq.com",
413 | "city": null,
414 | "lastLogin": null,
415 | "roles": [
416 | {
417 | "id": 3,
418 | "created": "2021-01-04T10:09:14",
419 | "updated": "2021-01-30T08:19:52",
420 | "statu": 1,
421 | "name": "普通用户",
422 | "code": "normal",
423 | "remark": "只有基本查看功能",
424 | "menuIds": []
425 | }
426 | ]
427 | }
428 | ],
429 | "total": 2,
430 | "size": 10,
431 | "current": 1,
432 | "orders": [],
433 | "optimizeCountSql": true,
434 | "hitCount": false,
435 | "countId": null,
436 | "maxLimit": null,
437 | "searchCount": true,
438 | "pages": 1
439 | }
440 |
441 | return Result
442 | })
443 |
444 |
445 | Mock.mock(RegExp('/sys/user/*'), 'post', () => {
446 | return Result
447 | })
448 |
449 | Mock.mock(RegExp('/sys/user/info/*'), 'get', () => {
450 |
451 | Result.data = {
452 | "id": 2,
453 | "created": "2021-01-30T08:20:22",
454 | "updated": "2021-01-30T08:55:57",
455 | "statu": 1,
456 | "username": "test",
457 | "password": "$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO",
458 | "avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
459 | "email": "test@qq.com",
460 | "city": null,
461 | "lastLogin": null,
462 | "roles": []
463 | }
464 | return Result
465 | })
--------------------------------------------------------------------------------
/vueadmin-java/src/main/java/com/markerhub/utils/RedisUtil.java:
--------------------------------------------------------------------------------
1 | package com.markerhub.utils;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.data.redis.core.RedisTemplate;
5 | import org.springframework.data.redis.core.ZSetOperations;
6 | import org.springframework.stereotype.Component;
7 | import org.springframework.util.CollectionUtils;
8 |
9 | import java.util.Collection;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Set;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | @Component
16 | public class RedisUtil {
17 |
18 | @Autowired
19 | private RedisTemplate redisTemplate;
20 |
21 | /**
22 | * 指定缓存失效时间
23 | *
24 | * @param key 键
25 | * @param time 时间(秒)
26 | * @return
27 | */
28 | public boolean expire(String key, long time) {
29 | try {
30 | if (time > 0) {
31 | redisTemplate.expire(key, time, TimeUnit.SECONDS);
32 | }
33 | return true;
34 | } catch (Exception e) {
35 | e.printStackTrace();
36 | return false;
37 | }
38 | }
39 |
40 | /**
41 | * 根据key 获取过期时间
42 | *
43 | * @param key 键 不能为null
44 | * @return 时间(秒) 返回0代表为永久有效
45 | */
46 | public long getExpire(String key) {
47 | return redisTemplate.getExpire(key, TimeUnit.SECONDS);
48 | }
49 |
50 | /**
51 | * 判断key是否存在
52 | *
53 | * @param key 键
54 | * @return true 存在 false不存在
55 | */
56 | public boolean hasKey(String key) {
57 | try {
58 | return redisTemplate.hasKey(key);
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | return false;
62 | }
63 | }
64 |
65 | /**
66 | * 删除缓存
67 | *
68 | * @param key 可以传一个值 或多个
69 | */
70 | @SuppressWarnings("unchecked")
71 | public void del(String... key) {
72 | if (key != null && key.length > 0) {
73 | if (key.length == 1) {
74 | redisTemplate.delete(key[0]);
75 | } else {
76 | redisTemplate.delete(CollectionUtils.arrayToList(key));
77 | }
78 | }
79 | }
80 |
81 | //============================String=============================
82 |
83 | /**
84 | * 普通缓存获取
85 | *
86 | * @param key 键
87 | * @return 值
88 | */
89 | public Object get(String key) {
90 | return key == null ? null : redisTemplate.opsForValue().get(key);
91 | }
92 |
93 | /**
94 | * 普通缓存放入
95 | *
96 | * @param key 键
97 | * @param value 值
98 | * @return true成功 false失败
99 | */
100 | public boolean set(String key, Object value) {
101 | try {
102 | redisTemplate.opsForValue().set(key, value);
103 | return true;
104 | } catch (Exception e) {
105 | e.printStackTrace();
106 | return false;
107 | }
108 |
109 | }
110 |
111 | /**
112 | * 普通缓存放入并设置时间
113 | *
114 | * @param key 键
115 | * @param value 值
116 | * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
117 | * @return true成功 false 失败
118 | */
119 | public boolean set(String key, Object value, long time) {
120 | try {
121 | if (time > 0) {
122 | redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
123 | } else {
124 | set(key, value);
125 | }
126 | return true;
127 | } catch (Exception e) {
128 | e.printStackTrace();
129 | return false;
130 | }
131 | }
132 |
133 | /**
134 | * 递增
135 | *
136 | * @param key 键
137 | * @param delta 要增加几(大于0)
138 | * @return
139 | */
140 | public long incr(String key, long delta) {
141 | if (delta < 0) {
142 | throw new RuntimeException("递增因子必须大于0");
143 | }
144 | return redisTemplate.opsForValue().increment(key, delta);
145 | }
146 |
147 | /**
148 | * 递减
149 | *
150 | * @param key 键
151 | * @param delta 要减少几(小于0)
152 | * @return
153 | */
154 | public long decr(String key, long delta) {
155 | if (delta < 0) {
156 | throw new RuntimeException("递减因子必须大于0");
157 | }
158 | return redisTemplate.opsForValue().increment(key, -delta);
159 | }
160 |
161 | //================================Map=================================
162 |
163 | /**
164 | * HashGet
165 | *
166 | * @param key 键 不能为null
167 | * @param item 项 不能为null
168 | * @return 值
169 | */
170 | public Object hget(String key, String item) {
171 | return redisTemplate.opsForHash().get(key, item);
172 | }
173 |
174 | /**
175 | * 获取hashKey对应的所有键值
176 | *
177 | * @param key 键
178 | * @return 对应的多个键值
179 | */
180 | public Map