SpringBoot + Vue 动态加载菜单栏解析

熊孩纸 阅读:218 2021-03-31 13:19:24 评论:0

 

第一步:SpirngBoot 项目

1.1 建库脚本

/* 
 Navicat MySQL Data Transfer 
 
 Source Server         : 192.168.1.73 
 Source Server Type    : MySQL 
 Source Server Version : 80015 
 Source Host           : 192.168.1.73:3306 
 Source Schema         : auth_shrio 
 
 Target Server Type    : MySQL 
 Target Server Version : 80015 
 File Encoding         : 65001 
 
 Date: 02/12/2020 18:45:00 
*/ 
 
SET NAMES utf8mb4; 
SET FOREIGN_KEY_CHECKS = 0; 
 
-- ---------------------------- 
-- Table structure for cost 
-- ---------------------------- 
DROP TABLE IF EXISTS `cost`; 
CREATE TABLE `cost`  ( 
  `cost_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  `house_id` int(11) NOT NULL COMMENT '房屋ID', 
  `create_date` date NOT NULL COMMENT '创建日期', 
  `money` int(11) NOT NULL DEFAULT 0 COMMENT '金额', 
  `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态:1 未支付,2:已支付', 
  PRIMARY KEY (`cost_id`) USING BTREE, 
  INDEX `FK_cost_house`(`house_id`) USING BTREE, 
  CONSTRAINT `FK_cost_house` FOREIGN KEY (`house_id`) REFERENCES `house` (`house_id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '费用信息表' ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of cost 
-- ---------------------------- 
INSERT INTO `cost` VALUES (1, 2, '2020-12-02', 3360, 1); 
 
-- ---------------------------- 
-- Table structure for house 
-- ---------------------------- 
DROP TABLE IF EXISTS `house`; 
CREATE TABLE `house`  ( 
  `house_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  `house_number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '房屋编号', 
  `area` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '区域', 
  `house_address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '房屋地址', 
  `house_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '房屋类型', 
  `acreage` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '房屋面积', 
  `peroples` int(10) NULL DEFAULT NULL COMMENT '可容纳人数', 
  `rent` int(10) NULL DEFAULT NULL COMMENT '房屋租金', 
  `status` tinyint(4) NULL DEFAULT NULL COMMENT '房屋状态:1:已租、2:待租', 
  `user_id` int(11) NOT NULL COMMENT '用户ID', 
  PRIMARY KEY (`house_id`) USING BTREE, 
  INDEX `FK_house_user`(`user_id`) USING BTREE, 
  CONSTRAINT `FK_house_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '房屋信息表' ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of house 
-- ---------------------------- 
INSERT INTO `house` VALUES (1, '0001', '广东省宝安区麻布新村', '105号13-1101', '1', '28.35平方', 3, 1800, 1, 3); 
INSERT INTO `house` VALUES (2, '0002', '广东省宝安区麻布新村', '105号13-1102', '1', '44.2平方', 5, 3400, 1, 1); 
INSERT INTO `house` VALUES (4, '0003', '广东省宝安区麻布新村', '105号13-1103', '1', '38.35平方', 3, 2800, 1, 1); 
 
-- ---------------------------- 
-- Table structure for house_lease 
-- ---------------------------- 
DROP TABLE IF EXISTS `house_lease`; 
CREATE TABLE `house_lease`  ( 
  `house_id` int(11) NOT NULL COMMENT '房屋ID', 
  `lease_id` int(11) NOT NULL COMMENT '租赁者ID', 
  PRIMARY KEY (`house_id`, `lease_id`) USING BTREE, 
  INDEX `FK_house_lease_lease`(`lease_id`) USING BTREE, 
  CONSTRAINT `FK_house_lease_house` FOREIGN KEY (`house_id`) REFERENCES `house` (`house_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, 
  CONSTRAINT `FK_house_lease_lease` FOREIGN KEY (`lease_id`) REFERENCES `lease` (`lease_id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '房屋租赁信息表' ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of house_lease 
-- ---------------------------- 
INSERT INTO `house_lease` VALUES (1, 1); 
INSERT INTO `house_lease` VALUES (2, 1); 
 
-- ---------------------------- 
-- Table structure for lease 
-- ---------------------------- 
DROP TABLE IF EXISTS `lease`; 
CREATE TABLE `lease`  ( 
  `lease_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  `real_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '租赁者姓名', 
  `id_card` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '租赁者身份证号码', 
  `sex` tinyint(4) NOT NULL COMMENT '性别:1 男 2 女', 
  `telphone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '电话', 
  `hometown` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '租赁者籍贯', 
  `status` tinyint(4) NOT NULL COMMENT '状态:1:租房中  2:未租房', 
  `start_date` date NOT NULL COMMENT '租赁开始时间', 
  `end_date` date NOT NULL COMMENT '租赁结束时间', 
  `sign_date` date NOT NULL COMMENT '租赁签订时间', 
  PRIMARY KEY (`lease_id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '租赁者信息表' ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of lease 
-- ---------------------------- 
INSERT INTO `lease` VALUES (1, '周志刚', '430921199112205454', 1, '13265740591', '湖南', 1, '2015-10-01', '2025-01-01', '2020-12-02'); 
 
-- ---------------------------- 
-- Table structure for permission 
-- ---------------------------- 
DROP TABLE IF EXISTS `permission`; 
CREATE TABLE `permission`  ( 
  `permission_id` int(11) NOT NULL, 
  `permision_component` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, 
  `permision_icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, 
  `permision_parent_id` int(11) NULL DEFAULT NULL, 
  `permission_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, 
  `permission_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, 
  `permission_zh` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, 
  PRIMARY KEY (`permission_id`) USING BTREE 
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of permission 
-- ---------------------------- 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (1, '首页', 'Admin', '/admin', 'el-icon-s-home', 'AdminIndex', 0); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (2, '运行情况', 'DashBoard', '/admin/dashboard', NULL, 'dashboard/Index', 1); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (3, '用户管理', 'User', '/admin', 'el-icon-user', 'AdminIndex', 0); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (4, '用户信息', 'Profile', '/admin/user/Profile', NULL, 'user/Profile', 3); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (5, '角色配置', 'Role', '/admin/user/Role', NULL, 'user/Role', 3); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (6, '测试菜单', 'ArticleManage', '/admin', 'el-icon-edit', 'AdminIndex', 0); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (7, '菜单列表1', 'ArticleList', '/admin/test/Test1', NULL, 'test/Test1', 6); 
INSERT INTO `permission`(permission_id,permission_zh,permission_name,permission_path,permision_icon,permision_component,permision_parent_id) VALUES (8, '菜单列表2', 'ArticleEdit', '/admin/test/Test2', NULL, 'test/Test2', 6); 
 
-- ---------------------------- 
-- Table structure for role 
-- ---------------------------- 
DROP TABLE IF EXISTS `role`; 
CREATE TABLE `role`  ( 
  `role_id` int(11) NOT NULL, 
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 
  PRIMARY KEY (`role_id`) USING BTREE 
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of role 
-- ---------------------------- 
INSERT INTO `role` VALUES (1, 'svip'); 
INSERT INTO `role` VALUES (2, 'vip'); 
INSERT INTO `role` VALUES (3, 'p'); 
INSERT INTO `role` VALUES (4, 'admin'); 
 
-- ---------------------------- 
-- Table structure for role_permission 
-- ---------------------------- 
DROP TABLE IF EXISTS `role_permission`; 
CREATE TABLE `role_permission`  ( 
  `role_id` int(11) NOT NULL, 
  `permission_id` int(11) NOT NULL, 
  PRIMARY KEY (`role_id`, `permission_id`) USING BTREE, 
  INDEX `FKf8yllw1ecvwqy3ehyxawqa1qp`(`permission_id`) USING BTREE, 
  CONSTRAINT `FKa6jx8n8xkesmjmv6jqug6bg68` FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, 
  CONSTRAINT `FKf8yllw1ecvwqy3ehyxawqa1qp` FOREIGN KEY (`permission_id`) REFERENCES `permission` (`permission_id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of role_permission 
-- ---------------------------- 
INSERT INTO `role_permission` VALUES (1, 1); 
INSERT INTO `role_permission` VALUES (1, 2); 
INSERT INTO `role_permission` VALUES (1, 3); 
INSERT INTO `role_permission` VALUES (1, 4); 
INSERT INTO `role_permission` VALUES (1, 5); 
INSERT INTO `role_permission` VALUES (1, 6); 
INSERT INTO `role_permission` VALUES (1, 7); 
INSERT INTO `role_permission` VALUES (1, 8); 
INSERT INTO `role_permission` VALUES (2, 1); 
INSERT INTO `role_permission` VALUES (2, 2); 
 
-- ---------------------------- 
-- Table structure for token_relation 
-- ---------------------------- 
DROP TABLE IF EXISTS `token_relation`; 
CREATE TABLE `token_relation`  ( 
  `relation_sid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名', 
  `token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'token凭证', 
  PRIMARY KEY (`relation_sid`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of token_relation 
-- ---------------------------- 
INSERT INTO `token_relation` VALUES (3, 'Jack', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDY5NTkzNzAsInVzZXJuYW1lIjoiSmFjayJ9.m3OZ1w2YQLmI0cE9oK79_pZbXnON_-e5YMbZLPtdyrU'); 
 
-- ---------------------------- 
-- Table structure for user 
-- ---------------------------- 
DROP TABLE IF EXISTS `user`; 
CREATE TABLE `user`  ( 
  `user_id` int(11) NOT NULL COMMENT '主键', 
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码', 
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '账户', 
  `telephone` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号码', 
  `email` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱地址', 
  `guid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '唯一码', 
  `real_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '真实姓名', 
  `address` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址', 
  PRIMARY KEY (`user_id`) USING BTREE 
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of user 
-- ---------------------------- 
INSERT INTO `user` VALUES (1, '123', 'Jack', '123', [email protected]', NULL, NULL, NULL); 
INSERT INTO `user` VALUES (2, '123', 'Rose', '1234', [email protected]', NULL, NULL, NULL); 
INSERT INTO `user` VALUES (3, '123', 'Paul', '12345', [email protected]', NULL, NULL, NULL); 
INSERT INTO `user` VALUES (4, '123', 'Jane', '123456', [email protected]', NULL, '简', '中国广东省深圳市盐田区'); 
 
-- ---------------------------- 
-- Table structure for user_role 
-- ---------------------------- 
DROP TABLE IF EXISTS `user_role`; 
CREATE TABLE `user_role`  ( 
  `user_id` int(11) NOT NULL, 
  `role_id` int(11) NOT NULL, 
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE, 
  INDEX `FKa68196081fvovjhkek5m97n3y`(`role_id`) USING BTREE, 
  CONSTRAINT `FK859n2jvi8ivhui0rl0esws6o` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT, 
  CONSTRAINT `FKa68196081fvovjhkek5m97n3y` FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of user_role 
-- ---------------------------- 
INSERT INTO `user_role` VALUES (3, 3); 
INSERT INTO `user_role` VALUES (4, 4); 
 
-- ---------------------------- 
-- Table structure for verification 
-- ---------------------------- 
DROP TABLE IF EXISTS `verification`; 
CREATE TABLE `verification`  ( 
  `verification_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  `verification_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '验证码', 
  `status` tinyint(255) NULL DEFAULT NULL COMMENT '状态:1:未使用,2:已使用', 
  `create_date` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', 
  `fail_date` datetime(0) NULL DEFAULT NULL COMMENT '失效日期', 
  PRIMARY KEY (`verification_id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
SET FOREIGN_KEY_CHECKS = 1; 

1.2 SpringBoot项目源码

1.2.1 实体层定义:

package com.zzg.entity; 
 
import java.util.Date; 
 
import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
@Entity 
public class Cost { 
	 
	@Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略 
    private Integer costId; 
	 
	 @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示house不能为空。删除房屋,不影响用户 
	 @JoinColumn(name="house_id")//设置在house表中的关联字段(外键) 
	 private House house;//所属房屋 
	  
	 private Date createDate; 
	  
	 private Integer money; 
	  
	 private Integer status; 
 
} 
package com.zzg.entity; 
 
import java.util.Set; 
 
import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.JoinTable; 
import javax.persistence.ManyToMany; 
import javax.persistence.ManyToOne; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
@Entity 
public class House { 
	@Id 
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略 
	private Integer houseId; 
 
	private String houseNumber; 
 
	private String area; 
 
	private String houseAddress; 
 
	private String houseType; 
 
	private String acreage; 
 
	private Integer peroples; 
 
	private Integer rent; 
 
	private Integer status; 
 
	@ManyToOne(cascade = {CascadeType.MERGE,CascadeType.REFRESH}, optional = false) // 可选属性optional=false,表示house不能为空。删除房屋,不影响用户 
	@JoinColumn(name = "user_id") // 设置在house表中的关联字段(外键) 
	private User user;// 所属房屋 
 
 
	@ManyToMany(fetch = FetchType.EAGER) 
	@JoinTable(name = "house_lease", joinColumns = { 
			@JoinColumn(name = "house_id", referencedColumnName = "houseId") }, inverseJoinColumns = { 
					@JoinColumn(name = "lease_id", referencedColumnName = "leaseId") }) 
	private Set<Lease> leases; 
 
} 
package com.zzg.entity; 
 
import java.util.Date; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
@Entity 
public class Lease { 
	@Id 
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略 
	private Integer leaseId; 
 
	private String realName; 
 
	private String idCard; 
 
	private Integer sex; 
 
	private String telphone; 
 
	private String hometown; 
 
	private Integer status; 
 
	private Date startDate; 
 
	private Date endDate; 
 
	private Date signDate; 
 
//	@ManyToMany(fetch = FetchType.EAGER) 
//	@JoinTable(name = "house_lease", joinColumns = { 
//			@JoinColumn(name = "lease_id", referencedColumnName = "leaseId") }, inverseJoinColumns = { 
//					@JoinColumn(name = "house_id", referencedColumnName = "houseId") }) 
//	private Set<House> houses; 
} 
package com.zzg.entity; 
 
import javax.persistence.Entity; 
import javax.persistence.Id; 
 
import lombok.Getter; 
import lombok.Setter; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Getter 
@Setter 
@Entity 
public class Permission { 
 
    @Id 
    private Integer permissionId; 
    private String permissionName; 
    private String permissionZh; 
    private String permissionPath; 
    private String permisionIcon; 
    private String permisionComponent; 
    private Integer permisionParentId; 
     
//    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)    
//    @JoinColumn(name="permision_parent_id")   
//    private Permission parent; 
//    // 子菜单项 
//    @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.EAGER)   
//    private Set<Permission> child  = new HashSet<Permission>() ; 
} 
package com.zzg.entity; 
 
import lombok.Getter; 
import lombok.Setter; 
 
import javax.persistence.*; 
import java.util.Set; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
 
@Getter 
@Setter 
@Entity 
public class Role { 
 
    @Id 
    private Integer roleId; 
    private String roleName; 
 
    @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(name = "role_permission", 
            joinColumns = [email protected](name = "ROLE_ID", referencedColumnName = "roleId")}, 
            inverseJoinColumns = [email protected](name = "PERMISSION_ID", referencedColumnName = "permissionId")}) 
    private Set<Permission> permissions; 
}
package com.zzg.entity; 
 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
@Entity(name="token_relation") 
public class TokenRelation { 
	@Id 
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略 
	private Integer relationSid; 
	 
	private String username; 
	 
	private String token; 
	 
} 
package com.zzg.entity; 
 
import java.util.List; 
import java.util.Set; 
 
import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.JoinTable; 
import javax.persistence.ManyToMany; 
import javax.persistence.OneToMany; 
 
import lombok.Getter; 
import lombok.Setter; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Getter 
@Setter 
@Entity 
public class User { 
    @Id 
    private Integer userId; 
 
    private String username; 
    private String password; 
 
    @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(name = "user_role", 
            joinColumns = [email protected](name = "USER_ID", referencedColumnName = "userId")}, 
            inverseJoinColumns = [email protected](name = "ROLE_ID", referencedColumnName = "roleId")}) 
    private Set<Role> roles; 
     
    private String telephone; 
     
    private String email; 
     
    private String guid; 
     
    private String realName; 
     
    private String address; 
} 
package com.zzg.entity; 
 
import java.util.Date; 
 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
@Entity(name="verification") 
public class Verification { 
	@Id 
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略 
	private Integer verificationId; 
	 
	private String verificationCode; 
	 
	private Integer status; 
	 
	private Date createDate; 
	 
	private Date failDate; 
	 
 
} 

1.2.2 dao层定义:

package com.zzg.dao; 
 
import javax.transaction.Transactional; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.data.jpa.repository.Modifying; 
import org.springframework.data.jpa.repository.Query; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.Cost; 
 
@Repository 
public interface CostRepository extends JpaRepository<Cost, Integer>, JpaSpecificationExecutor<Cost> { 
 
	/** 
	 * 原生SQL 
	 * @param houseId 
	 * @param costId 
	 * @return 
	 */ 
	@Transactional 
	@Modifying 
	@Query(nativeQuery = true,value="update cost u set u.house_id = ?1 where u.cost_id = ?2") 
	int modifyHouseId(Integer houseId, Integer costId); 
 
} 
package com.zzg.dao; 
 
import javax.transaction.Transactional; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.data.jpa.repository.Modifying; 
import org.springframework.data.jpa.repository.Query; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.House; 
 
@Repository 
public interface HouseRepository extends JpaRepository<House, Integer>, JpaSpecificationExecutor<House> { 
	/** 
	 * 原生SQL 
	 * @param houseId 
	 * @param costId 
	 * @return 
	 */ 
	@Transactional 
	@Modifying 
	@Query(nativeQuery = true,value="update house u set u.user_id = ?1 where u.house_id = ?2") 
	int modifyUserId(Integer userId, Integer houseId); 
} 
package com.zzg.dao; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.Lease; 
 
@Repository 
public interface LeaseRepository extends JpaRepository<Lease, Integer>, JpaSpecificationExecutor<Lease> { 
	 
} 
package com.zzg.dao; 
 
import java.util.List; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.Permission; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Repository 
public interface PermissionRepository extends JpaRepository<Permission, Integer>, JpaSpecificationExecutor<Permission> { 
} 
package com.zzg.dao; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.Role; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Repository 
public interface RoleRepository extends JpaRepository<Role, Integer>, JpaSpecificationExecutor<Role> { 
	Role findByRoleId(Integer userId); 
} 
package com.zzg.dao; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.stereotype.Repository; 
 
import com.zzg.entity.TokenRelation; 
 
@Repository("tokenRelationRepository") 
public interface TokenRelationRepository extends JpaRepository<TokenRelation, Integer> { 
	TokenRelation findByUsername(String username); 
	 
	TokenRelation findByToken(String token); 
} 
package com.zzg.dao; 
 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.stereotype.Repository; 
 
import com.zzg.entity.User; 
 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Repository 
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> { 
    User findByUsername(String username); 
 
    User findByUserId(Integer userId); 
     
    User findByEmail(String email); 
     
    User findByTelephone(String telephone); 
} 
package com.zzg.dao; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.stereotype.Repository; 
import com.zzg.entity.Verification; 
 
@Repository 
public interface VerificationRepository extends JpaRepository<Verification, Integer> { 
	Verification findByVerificationCode(String verificationCode); 
} 

1.2.3 controller层定义:

package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.zzg.common.AbstractController; 
import com.zzg.dao.CostRepository; 
import com.zzg.entity.Cost; 
 
@RestController 
public class CostController extends AbstractController { 
	@Autowired 
	CostRepository costRepository; 
	 
	@RequestMapping(value = "/cost/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody Cost cost) { 
		costRepository.save(cost); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段和多对多表关系,产生原因:[email protected] 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/cost/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody Cost cost) { 
		Optional<Cost> old = costRepository.findById(cost.getCostId()); 
		if(old.isPresent()){ 
			Cost oldCost = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(cost, oldCost); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            costRepository.save(oldCost); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	/** 
	 * 基于原生SQL 功能实现 
	 * @param houseId 
	 * @param costId 
	 * @return 
	 */ 
	@RequestMapping(value = "/cost/houseId", method = RequestMethod.GET) 
	@ResponseBody 
	public Map updateHouseId(Integer houseId,Integer costId) { 
		costRepository.modifyHouseId(houseId, costId); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	 
	 
	@RequestMapping(value = "/cost/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
		 
		Page<Cost> stus = costRepository.findAll(new Specification<Cost>(){ 
			@Override 
			public Predicate toPredicate(Root<Cost> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	@RequestMapping(value = "/cost/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		costRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
 
} 
package com.zzg.controller; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import org.apache.shiro.authz.annotation.RequiresPermissions; 
import org.apache.shiro.authz.annotation.RequiresRoles; 
import org.springframework.web.bind.annotation.DeleteMapping; 
import org.springframework.web.bind.annotation.GetMapping; 
import org.springframework.web.bind.annotation.PostMapping; 
import org.springframework.web.bind.annotation.PutMapping; 
import org.springframework.web.bind.annotation.RequestHeader; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
 
@RestController 
public class DataController { 
	@RequiresPermissions({"save"}) //没有的话 AuthorizationException 
    @PostMapping("/data/save") 
 	@ResponseBody 
    public Map<String, Object> save(@RequestHeader("token")String token) { 
        System.out.println("save"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有save的权力"); 
        return map; 
    }//f603cd4348b8f1d41226e3f555d392bd 
 
    @RequiresPermissions({"delete"}) //没有的话 AuthorizationException 
    @DeleteMapping("/data/delete") 
    @ResponseBody 
    public Map<String, Object> delete(@RequestHeader("token")String token) { 
        System.out.println("delete"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有delete的权力"); 
        return map; 
    } 
 
    @RequiresPermissions({"update"}) //没有的话 AuthorizationException 
    @PutMapping("/data/update") 
    @ResponseBody 
    public Map<String, Object> update(@RequestHeader("token")String token) { 
        System.out.println("update"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有update的权力"); 
        return map; 
    } 
 
    @RequiresPermissions({"select"}) //没有的话 AuthorizationException 
    @GetMapping("/data/select") 
    @ResponseBody 
    public Map<String, Object> select(@RequestHeader("token")String token) { 
        System.out.println("select"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有select的权力"); 
        return map; 
    } 
 
    @RequiresRoles({"vip"}) //没有的话 AuthorizationException 
    @GetMapping("/data/vip") 
    @ResponseBody 
    public Map<String, Object> vip(@RequestHeader("token")String token) { 
        System.out.println("vip"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有VIP角色"); 
        return map; 
    } 
    @RequiresRoles({"svip"}) //没有的话 AuthorizationException 
    @GetMapping("/data/svip") 
    @ResponseBody 
    public Map<String, Object> svip(@RequestHeader("token")String token) { 
        System.out.println("svip"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有SVIP角色"); 
        return map; 
    } 
    @RequiresRoles({"p"}) //没有的话 AuthorizationException 
    @GetMapping("/data/p") 
    @ResponseBody 
    public Map<String, Object> p(@RequestHeader("token")String token) { 
        System.out.println("p"); 
        Map<String, Object> map = new HashMap<String, Object>(); 
        map.put("status", 200); 
        map.put("msg", "当前用户有P角色"); 
        return map; 
    } 
} 
package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.HouseRepository; 
import com.zzg.entity.House; 
 
 
@RestController 
public class HouseController extends AbstractController{ 
	@Autowired 
	HouseRepository houseRepository; 
	 
	@RequestMapping(value = "/house/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody House house) { 
		houseRepository.save(house); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段和多对多表关系,产生原因:[email protected] 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/house/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody House house) { 
		Optional<House> old = houseRepository.findById(house.getHouseId()); 
		if(old.isPresent()){ 
			House oldHouse = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(house, oldHouse); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            houseRepository.save(oldHouse); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	 
	/** 
	 * 基于原生SQL 功能实现 
	 * @param houseId 
	 * @param costId 
	 * @return 
	 */ 
	@RequestMapping(value = "/house/userId", method = RequestMethod.GET) 
	@ResponseBody 
	public Map updateUserId(Integer userId,Integer houseId) { 
		houseRepository.modifyUserId(userId, houseId); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	@RequestMapping(value = "/house/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
		 
		Page<House> stus = houseRepository.findAll(new Specification<House>(){ 
			@Override 
			public Predicate toPredicate(Root<House> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				if(paramter.get("houseId") != null){ 
					 predicateList.add(criteriaBuilder.equal(root.get("houseId"), paramter.get("houseId"))); 
				} 
				if(paramter.get("houseNumber") != null){ 
					 predicateList.add(criteriaBuilder.equal(root.get("houseNumber"), paramter.get("houseNumber"))); 
				} 
				if(paramter.get("area") != null){ 
					 predicateList.add(criteriaBuilder.like(root.get("area"), "%" + paramter.get("area") +"%")); 
				} 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	@RequestMapping(value = "/house/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		houseRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
	 
 
 
} 
package com.zzg.controller; 
 
import java.awt.image.BufferedImage; 
import java.io.ByteArrayOutputStream; 
import javax.imageio.ImageIO; 
import javax.servlet.ServletOutputStream; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.web.bind.annotation.GetMapping; 
import org.springframework.web.bind.annotation.RestController; 
import com.google.code.kaptcha.impl.DefaultKaptcha; 
import com.zzg.redis.RedisUtils; 
import com.zzg.util.KaptchaUtil; 
 
@RestController 
public class KaptchaController { 
	public static final String VRIFY_CODE = "VRIFYCODE"; 
	 
	@GetMapping("/sys/kaptcha") 
	public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) 
			throws Exception { 
		 
		byte[] captchaChallengeAsJpeg = null; 
		ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); 
		try { 
			// 代码方式创建:DefaultKaptcha 
			KaptchaUtil single = KaptchaUtil.getInstance(); 
			DefaultKaptcha defaultKaptcha = single.produce(); 
			// 生产验证码字符串并保存到session中 
			String createText = defaultKaptcha.createText(); 
			// 基于session 方式 
			//httpServletRequest.getSession().setAttribute(VRIFY_CODE, createText); 
			// 基于redis 方式 
			RedisUtils.hPut(VRIFY_CODE, createText, createText); 
			// 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中 
			BufferedImage challenge = defaultKaptcha.createImage(createText); 
			ImageIO.write(challenge, "jpg", jpegOutputStream); 
		} catch (IllegalArgumentException e) { 
			httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); 
			return; 
		} 
  
		// 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组 
		captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); 
		httpServletResponse.setHeader("Cache-Control", "no-store"); 
		httpServletResponse.setHeader("Pragma", "no-cache"); 
		httpServletResponse.setDateHeader("Expires", 0); 
		httpServletResponse.setContentType("image/jpeg"); 
		ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream(); 
		responseOutputStream.write(captchaChallengeAsJpeg); 
		responseOutputStream.flush(); 
		responseOutputStream.close(); 
	} 
 
} 
package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.LeaseRepository; 
import com.zzg.entity.Lease; 
 
@RestController 
public class LeaseController extends AbstractController { 
	@Autowired 
	private LeaseRepository leaseRepository; 
	 
	@RequestMapping(value = "/lease/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody Lease lease) { 
		leaseRepository.save(lease); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段和和多对多表关系 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/lease/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody Lease lease) { 
		Optional<Lease> old = leaseRepository.findById(lease.getLeaseId()); 
		if(old.isPresent()){ 
			Lease oldLease = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(lease, oldLease); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            leaseRepository.save(oldLease); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
 
	@RequestMapping(value = "/lease/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
		 
		Page<Lease> stus = leaseRepository.findAll(new Specification<Lease>(){ 
			@Override 
			public Predicate toPredicate(Root<Lease> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	@RequestMapping(value = "/lease/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		leaseRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
	 
	 
 
} 
package com.zzg.controller; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.CrossOrigin; 
import org.springframework.web.bind.annotation.PostMapping; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestHeader; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.alibaba.druid.util.StringUtils; 
import com.zzg.dao.TokenRelationRepository; 
import com.zzg.dao.UserRepository; 
import com.zzg.dao.VerificationRepository; 
import com.zzg.entity.TokenRelation; 
import com.zzg.entity.User; 
import com.zzg.entity.Verification; 
import com.zzg.redis.RedisUtils; 
import com.zzg.util.JWTUtil; 
 
@RestController 
public class LoginController { 
	public static final String VRIFY_CODE = "VRIFYCODE"; 
	// 过期时间 24 小时 
	private static final long EXPIRE_TIME = 60 * 24 * 60 * 1000; 
	@Autowired 
	UserRepository userRepository; 
	@Autowired 
	TokenRelationRepository tokenRelationRepository; 
	@Autowired 
	VerificationRepository verificationRepository; 
	 
	/** 
     * 登录 
     */ 
	@CrossOrigin 
    @PostMapping("/common/login") 
    @ResponseBody 
    public Map<String, Object> commonLogin(@RequestBody Map<String, Object> parame) { 
        Map<String, Object> result = new HashMap<>(); 
        String username = (String) parame.get("username"); 
        String password = (String) parame.get("password"); 
        //用户信息 
        User user = userRepository.findByUsername(username); 
        //账号不存在、密码错误 
        if (user == null || !user.getPassword().equals(password)) { 
            result.put("status", 400); 
            result.put("msg", "账号或密码有误"); 
        } else { 
            //生成token,并保存到redis 
        	String token = JWTUtil.createToken(username); 
        	RedisUtils.set(username,token); 
        	RedisUtils.expire(username, EXPIRE_TIME); 
        	// user->token 关系保存到mysql 中 
        	TokenRelation relation = tokenRelationRepository.findByUsername(username); 
        	if(relation == null){ 
        		relation = new TokenRelation(); 
        		relation.setUsername(username); 
            	relation.setToken(token); 
        	} else { 
        		relation.setToken(token); 
        	} 
        	tokenRelationRepository.save(relation); 
        	result.put("uid", user.getUserId()); 
        	result.put("username", username); 
        	result.put("token", token); 
            result.put("status", 200); 
            result.put("msg", "登陆成功"); 
            
        } 
        return result; 
    } 
	 
	 
	/** 
     * 登录 
     */ 
    @PostMapping("/sys/login") 
    @ResponseBody 
    public Map<String, Object> login(@RequestParam("username")String username, @RequestParam("password")String password, @RequestParam("captcha")String captcha) { 
        Map<String, Object> result = new HashMap<>(); 
         
        //校验验证码 
        //基于session的验证码 
        // String sessionCaptcha = (String) SecurityUtils.getSubject().getSession().getAttribute(VRIFY_CODE); 
        //基于redis的验证码 
        String redisCaptcha = (String) RedisUtils.hGet(VRIFY_CODE, captcha); 
        if (StringUtils.isEmpty(redisCaptcha)) { 
        	 result.put("status", 400); 
             result.put("msg", "验证码有误"); 
             return result; 
        } 
        //用户信息 
        User user = userRepository.findByUsername(username); 
        //账号不存在、密码错误 
        if (user == null || !user.getPassword().equals(password)) { 
            result.put("status", 400); 
            result.put("msg", "账号或密码有误"); 
        } else { 
            //生成token,并保存到redis 
        	String token = JWTUtil.createToken(username); 
        	RedisUtils.set(username,token); 
        	RedisUtils.expire(username, EXPIRE_TIME); 
        	// user->token 关系保存到mysql 中 
        	TokenRelation relation = tokenRelationRepository.findByUsername(username); 
        	if(relation == null){ 
        		relation = new TokenRelation(); 
        		relation.setUsername(username); 
            	relation.setToken(token); 
        	} else { 
        		relation.setToken(token); 
        	} 
        	tokenRelationRepository.save(relation); 
        	result.put("token", token); 
            result.put("status", 200); 
            result.put("msg", "登陆成功"); 
            // 移除验证码 
            RedisUtils.hDelete(VRIFY_CODE, captcha); 
        } 
        return result; 
    } 
     
    public boolean validateCode(String code){ 
    	 Verification verification = verificationRepository.findByVerificationCode(code); 
    	 if(verification != null){ 
    		  
    	 } 
    	 return false; 
    } 
     
    /** 
     * 邮箱登录 
     */ 
    @PostMapping("/email/login") 
    @ResponseBody 
    public Map<String, Object> emailLogin(@RequestParam("email")String email, @RequestParam("code")String code) { 
        Map<String, Object> result = new HashMap<>(); 
         
       
        //用户信息 
        User user = userRepository.findByEmail(email); 
        Verification verification = verificationRepository.findByVerificationCode(code); 
        //账号不存在、验证码错误 
        if (user == null || verification == null) { 
            result.put("status", 400); 
            result.put("msg", "邮箱有误"); 
        } else { 
            //生成token,并保存到redis 
        	String token = JWTUtil.createToken(user.getUsername()); 
        	RedisUtils.set(user.getUsername(),token); 
        	RedisUtils.expire(user.getUsername(), EXPIRE_TIME); 
        	// user->token 关系保存到mysql 中 
        	TokenRelation relation = tokenRelationRepository.findByUsername(user.getUsername()); 
        	if(relation == null){ 
        		relation = new TokenRelation(); 
        		relation.setUsername(user.getUsername()); 
            	relation.setToken(token); 
        	} else { 
        		relation.setToken(token); 
        	} 
        	tokenRelationRepository.save(relation); 
        	result.put("token", token); 
            result.put("status", 200); 
            result.put("msg", "登陆成功"); 
             
            // 验证码移除 
            verificationRepository.deleteById(verification.getVerificationId()); 
            
        } 
        return result; 
    } 
     
    /** 
     * 邮箱登录 
     */ 
    @PostMapping("/phone/login") 
    @ResponseBody 
    public Map<String, Object> phoneLogin(@RequestParam("phone")String phone, @RequestParam("code")String code) { 
        Map<String, Object> result = new HashMap<>(); 
         
       
        //用户信息 
        User user = userRepository.findByTelephone(phone); 
        Verification verification = verificationRepository.findByVerificationCode(code); 
        //账号不存在、验证码错误 
        if (user == null || verification == null) { 
            result.put("status", 400); 
            result.put("msg", "手机号码有误"); 
        } else { 
            //生成token,并保存到redis 
        	String token = JWTUtil.createToken(user.getUsername()); 
        	RedisUtils.set(user.getUsername(),token); 
        	RedisUtils.expire(user.getUsername(), EXPIRE_TIME); 
        	// user->token 关系保存到mysql 中 
        	TokenRelation relation = tokenRelationRepository.findByUsername(user.getUsername()); 
        	if(relation == null){ 
        		relation = new TokenRelation(); 
        		relation.setUsername(user.getUsername()); 
            	relation.setToken(token); 
        	} else { 
        		relation.setToken(token); 
        	} 
        	tokenRelationRepository.save(relation); 
        	result.put("token", token); 
            result.put("status", 200); 
            result.put("msg", "登陆成功"); 
             
            // 验证码移除 
            verificationRepository.deleteById(verification.getVerificationId()); 
            
        } 
        return result; 
    } 
     
     
    /** 
     * 退出 
     */ 
    
    @PostMapping("/sys/logout") 
    public Map<String, Object> logout(@RequestHeader("token")String token) { 
        Map<String, Object> result = new HashMap<>(); 
        String username = null; 
        TokenRelation relation = tokenRelationRepository.findByToken(token); 
        if(relation != null){ 
        	username = relation.getUsername(); 
        	tokenRelationRepository.deleteById(relation.getRelationSid()); 
        } 
        if(!StringUtils.isEmpty(username)){ 
        	// redis 移除token 
            RedisUtils.del(username); 
        } 
        
        result.put("status", 200); 
        result.put("msg", "您已安全退出系统"); 
        return result; 
    } 
} 
package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
 
import org.apache.shiro.util.CollectionUtils; 
import org.springframework.beans.BeanUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.PermissionRepository; 
import com.zzg.dao.RoleRepository; 
import com.zzg.dao.UserRepository; 
import com.zzg.entity.Permission; 
import com.zzg.entity.Role; 
import com.zzg.entity.User; 
import com.zzg.vo.PermissionVo; 
 
@RestController 
public class PermissionController extends AbstractController{ 
	@Autowired 
	private PermissionRepository permissionRepository; 
	@Autowired 
	private UserRepository userRepository; 
	@Autowired 
	private RoleRepository roleRepository; 
	 
	 
	@RequestMapping(value = "/permission/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody Permission permission) { 
		permissionRepository.save(permission); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/permission/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody Permission permission) { 
		Optional<Permission> old = permissionRepository.findById(permission.getPermissionId()); 
		if(old.isPresent()){ 
			Permission oldPermission = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(permission, oldPermission); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            permissionRepository.save(oldPermission); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	@RequestMapping(value = "/permission/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
		 
		Page<Permission> stus = permissionRepository.findAll(new Specification<Permission>(){ 
			@Override 
			public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	/** 
	 * 查询用户指定权限 
	 * @param uid 
	 * @return 
	 */ 
	@RequestMapping(value = "/permission/{uid}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map findPermission(@PathVariable Integer uid) { 
		List<PermissionVo> permissionsVos = new ArrayList<PermissionVo>(); 
		 
		List<Permission> permissions = new ArrayList<Permission>(); 
		//显示第1页每页显示3条 
		User user = userRepository.findByUserId(uid); 
		 
		user.getRoles().stream().forEach(item->{ 
        	Role role = roleRepository.findByRoleId(item.getRoleId()); 
        	if(!CollectionUtils.isEmpty(role.getPermissions())){ 
        		for(Permission permission : role.getPermissions()){ 
        			if(permission.getPermisionParentId() == null){ 
        				permissions.add(permission); 
        			} 
        		} 
        	} 
        }); 
		 
	 
		 
		 
		permissions.stream().forEach(item ->{ 
			  
			 /** 
			  * Spring Data JPA 动态查询条件 
			  */ 
			 Specification<Permission> specification = new Specification<Permission>() { 
	             @Override 
	            public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { 
	                List<Predicate> predicates = new ArrayList<Predicate>(); 
	                if(null != item.getPermissionId()) { 
	                    predicates.add(cb.equal(root.<Integer>get("permisionParentId"), item.getPermissionId())); 
	                } 
	                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
	            } 
	        }; 
	        List<Permission> childPermission = permissionRepository.findAll(specification); 
	        List<PermissionVo> childPermissionVO = new ArrayList<PermissionVo>(); 
	        for(Permission permission : childPermission){ 
	        	 PermissionVo vo = new PermissionVo(); 
	        	 BeanUtils.copyProperties(permission, vo); 
	        	 childPermissionVO.add(vo); 
	        } 
	         
	        PermissionVo vo = new PermissionVo(); 
	        BeanUtils.copyProperties(item, vo); 
	        vo.setChild(childPermissionVO); 
	         
	        permissionsVos.add(vo); 
	         
		}); 
		  
		 
		// 数据清理 
//		Iterator<Permission> iterator = permissions.iterator(); 
//		while(iterator.hasNext()){ 
//			Permission permission = iterator.next(); 
//			if(permission.getPermisionParentId() != null){ 
//				iterator.remove(); 
//			} 
//		} 
		 
		 
 
//		for(Permission permission : permissions){ 
//			if(permission.getParent() != null){ 
//				permissions.remove(permission); 
//			} 
//		} 
				 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", permissionsVos); 
		return map; 
	} 
	 
	@RequestMapping(value = "/permission/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		permissionRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
 
} 
package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.RoleRepository; 
import com.zzg.entity.Role; 
 
@RestController 
public class RoleController extends AbstractController { 
	@Autowired 
	private RoleRepository roleRepository; 
	 
	@RequestMapping(value = "/role/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody Role role) { 
		roleRepository.save(role); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/role/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody Role role) { 
		Optional<Role> old = roleRepository.findById(role.getRoleId()); 
		if(old.isPresent()){ 
			Role oldRole = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(role, oldRole); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            roleRepository.save(oldRole); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	@RequestMapping(value = "/role/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
	 
		Page<Role> stus = roleRepository.findAll(new Specification<Role>(){ 
			@Override 
			public Predicate toPredicate(Root<Role> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	@RequestMapping(value = "/role/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		roleRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
 
} 
package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.UserRepository; 
import com.zzg.entity.User; 
 
@RestController 
public class UserController extends AbstractController { 
	@Autowired 
	private UserRepository userRepository; 
	 
	@RequestMapping(value = "/user/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody User user) { 
		userRepository.save(user); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/user/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody User user) { 
		Optional<User> old = userRepository.findById(user.getUserId()); 
		if(old.isPresent()){ 
			User oldUser = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(user, oldUser); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            userRepository.save(oldUser); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	@RequestMapping(value = "/user/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
	 
		Page<User> stus = userRepository.findAll(new Specification<User>(){ 
			@Override 
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	@RequestMapping(value = "/user/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		userRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
 
} 
package com.zzg.controller; 
 
import java.util.Calendar; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.Map; 
 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.GetMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.zzg.dao.VerificationRepository; 
import com.zzg.entity.Verification; 
import com.zzg.util.HttpContextUtil; 
 
@RestController 
public class VerificationController { 
	// 定义jackson对象 
    private static final ObjectMapper MAPPER = new ObjectMapper(); 
     
    @Autowired 
    VerificationRepository verificationRepository; 
     
    public Verification getVerification(String code){ 
    	Date date = new Date(); 
    	Verification verification = new Verification(); 
    	verification.setCreateDate(date); 
    	Calendar calendar = Calendar.getInstance(); 
    	calendar.setTime(date); 
    	calendar.set(Calendar.MINUTE,  calendar.get(Calendar.MINUTE) + 15);//分钟+15 
    	verification.setFailDate(calendar.getTime()); 
    	verification.setStatus(1); 
    	verification.setVerificationCode(code); 
    	return verification; 
    } 
    
     
	@GetMapping("/sys/verification") 
	public void defaultVerification(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) 
	throws Exception { 
		Verification verification = this.getVerification("123456"); 
		verificationRepository.save(verification); 
		 
		httpServletResponse.setContentType("application/json;charset=utf-8"); 
		httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true"); 
		httpServletResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin()); 
		httpServletResponse.setCharacterEncoding("UTF-8"); 
        //设置编码,否则中文字符在重定向时会变为空字符串 
        Map<String, Object> result = new HashMap<>(); 
        result.put("status", 200); 
        result.put("code", verification.getVerificationCode()); 
        result.put("msg", "验证码发送成功"); 
        String json = MAPPER.writeValueAsString(result); 
        httpServletResponse.getWriter().print(json); 
		 
	} 
} 

1.2.4 通用定义:

package com.zzg.common.constant; 
 
public class WebAppConstants { 
	public static final String LIMIT = "limit"; 
	public static final String PAGE = "page"; 
} 
package com.zzg.common; 
 
import java.util.HashSet; 
import java.util.Map; 
import java.util.Set; 
 
import org.springframework.beans.BeanUtils; 
import org.springframework.beans.BeanWrapper; 
import org.springframework.beans.BeanWrapperImpl; 
import org.springframework.beans.SimpleTypeConverter; 
import org.springframework.data.domain.PageRequest; 
 
import com.zzg.common.constant.WebAppConstants; 
 
public abstract class AbstractController { 
	/** 
	 * 参数分页参数转换校验:现在仅支持:get请求、参数格式:?page=1&limit=10 
	 *  
	 * @param param 
	 * @return 
	 */ 
	protected PageRequest initPageBounds(Map<String, Object> paramter) { 
		SimpleTypeConverter converter = new SimpleTypeConverter(); 
		// 页码、分页大小初始化设置值 
		int page = 0; 
		int limit = 10; 
		if (paramter.get(WebAppConstants.PAGE) != null) { 
			page = converter.convertIfNecessary(paramter.get(WebAppConstants.PAGE), int.class); 
		} 
		if (paramter.get(WebAppConstants.LIMIT) != null) { 
			limit = converter.convertIfNecessary(paramter.get(WebAppConstants.LIMIT), int.class); 
		} 
		PageRequest pb = new PageRequest(page, limit); 
		return pb; 
	} 
 
	public static void copyPropertiesIgnoreNull(Object src, Object target) { 
		BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); 
	} 
 
	public static String[] getNullPropertyNames(Object source) { 
		final BeanWrapper src = new BeanWrapperImpl(source); 
		java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); 
 
		Set<String> emptyNames = new HashSet<String>(); 
		for (java.beans.PropertyDescriptor pd : pds) { 
			Object srcValue = src.getPropertyValue(pd.getName()); 
			if (srcValue == null) 
				emptyNames.add(pd.getName()); 
		} 
		String[] result = new String[emptyNames.size()]; 
		return emptyNames.toArray(result); 
	} 
} 

1.2.5 配置对象定义:GlobalCorsConfig :系统跨域对象配置、ShiroConfig :apache shrio 用户登入鉴权配置

package com.zzg.config; 
 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.cors.CorsConfiguration; 
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 
import org.springframework.web.filter.CorsFilter; 
 
@Configuration 
public class GlobalCorsConfig { 
	@Bean 
    public CorsFilter corsFilter() { 
        //1.添加CORS配置信息 
        CorsConfiguration config = new CorsConfiguration(); 
          //放行哪些原始域 
          config.addAllowedOrigin("*"); 
          //是否发送Cookie信息 
          config.setAllowCredentials(true); 
          //放行哪些原始域(请求方式) 
          config.addAllowedMethod("*"); 
          //放行哪些原始域(头部信息) 
          config.addAllowedHeader("*"); 
          //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) 
          // config.addExposedHeader("*"); 
           
          config.addExposedHeader("Content-Type"); 
          config.addExposedHeader( "X-Requested-With"); 
          config.addExposedHeader("accept"); 
          config.addExposedHeader("Origin"); 
          config.addExposedHeader( "Access-Control-Request-Method"); 
          config.addExposedHeader("Access-Control-Request-Headers"); 
 
 
        //2.添加映射路径 
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); 
        configSource.registerCorsConfiguration("/**", config); 
 
        //3.返回新的CorsFilter. 
        return new CorsFilter(configSource); 
    } 
 
} 
package com.zzg.config; 
 
import java.util.HashMap; 
import java.util.LinkedHashMap; 
import java.util.Map; 
import javax.servlet.Filter; 
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; 
import org.apache.shiro.mgt.DefaultSubjectDAO; 
import org.apache.shiro.spring.LifecycleBeanPostProcessor; 
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 
import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 
import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import com.zzg.filter.JWTFilter; 
import com.zzg.shrio.MyRealm; 
 
@Configuration 
public class ShiroConfig { 
	/** 
	 * 先走 filter ,然后 filter 如果检测到请求头存在 token,则用 token 去 login,走 Realm 去验证 
	 */ 
	@Bean 
	public ShiroFilterFactoryBean factory(org.apache.shiro.mgt.SecurityManager securityManager) { 
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); 
		// 添加自己的过滤器并且取名为jwt 
		Map<String, Filter> filterMap = new LinkedHashMap<>(); 
		// 设置自定义的JWT过滤器 
		filterMap.put("jwt", new JWTFilter()); 
		factoryBean.setFilters(filterMap); 
		factoryBean.setSecurityManager(securityManager); 
 
		Map<String, String> filterRuleMap = new HashMap<>(); 
		filterRuleMap.put("/common/login", "anon"); //简单登录接口排除 
		filterRuleMap.put("/phone/login", "anon"); //邮箱登录接口排除 
		filterRuleMap.put("/email/login", "anon"); //邮箱登录接口排除 
		filterRuleMap.put("/sys/login", "anon"); //登录接口排除 
		filterRuleMap.put("/sys/logout", "anon"); //登出接口排除 
		filterRuleMap.put("/sys/kaptcha", "anon"); //验证码接口排除 
		filterRuleMap.put("/sys/verification", "anon"); //验证码接口排除 
		// 所有请求通过我们自己的JWT Filter 
		filterRuleMap.put("/**", "jwt"); 
		factoryBean.setFilterChainDefinitionMap(filterRuleMap); 
		return factoryBean; 
	} 
 
	/** 
	 * 注入 securityManager 
	 */ 
	@Bean 
	public org.apache.shiro.mgt.SecurityManager securityManager(MyRealm customRealm) { 
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 
		// 设置自定义 realm. 
		securityManager.setRealm(customRealm); 
		/* 
		 * 关闭shiro自带的session,详情见文档 
		 * http://shiro.apache.org/session-management.html#SessionManagement- 
		 * StatelessApplications%28Sessionless%29 
		 */ 
		DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); 
		DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator(); 
		defaultSessionStorageEvaluator.setSessionStorageEnabled(false); 
		subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator); 
		securityManager.setSubjectDAO(subjectDAO); 
		return securityManager; 
	} 
 
	/** 
	 * 添加注解支持 
	 */ 
	@Bean 
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); 
		// 强制使用cglib,防止重复代理和可能引起代理出错的问题 
		// https://zhuanlan.zhihu.com/p/29161098 
		defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); 
		return defaultAdvisorAutoProxyCreator; 
 
	} 
 
	@Bean 
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) { 
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); 
		advisor.setSecurityManager(securityManager); 
		return advisor; 
	} 
 
	@Bean 
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { 
		return new LifecycleBeanPostProcessor(); 
	} 
 
} 

1.2.6 全局异常定义

package com.zzg.exception; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import org.apache.shiro.authz.AuthorizationException; 
import org.springframework.web.bind.annotation.ExceptionHandler; 
import org.springframework.web.bind.annotation.RestControllerAdvice; 
 
/** 
 * 全局异常处理器 
 */ 
@RestControllerAdvice 
public class GlobalExceptionHandler { 
	@ExceptionHandler(value = AuthorizationException.class) 
	public Map<String, String> handleException(AuthorizationException e) { 
		// e.printStackTrace(); 
		Map<String, String> result = new HashMap<String, String>(); 
		result.put("status", "400"); 
		// 获取错误中中括号的内容 
		String message = e.getMessage(); 
		String msg = message.substring(message.indexOf("[") + 1, message.indexOf("]")); 
		// 判断是角色错误还是权限错误 
		if (message.contains("role")) { 
			result.put("msg", "对不起,您没有" + msg + "角色"); 
		} else if (message.contains("permission")) { 
			result.put("msg", "对不起,您没有" + msg + "权限"); 
		} else { 
			result.put("msg", "对不起,您的权限有误"); 
		} 
		return result; 
	} 
} 

1.2.7 JWTFilter 过滤器定义

package com.zzg.filter; 
 
import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 
 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.apache.shiro.authz.UnauthorizedException; 
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.web.bind.annotation.RequestMethod; 
 
import com.alibaba.druid.util.StringUtils; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.zzg.dao.TokenRelationRepository; 
import com.zzg.entity.TokenRelation; 
import com.zzg.redis.RedisUtils; 
import com.zzg.shrio.JWTToken; 
import com.zzg.spring.SpringContextUtil; 
import com.zzg.util.HttpContextUtil; 
 
public class JWTFilter extends BasicHttpAuthenticationFilter { 
	private Logger logger = LoggerFactory.getLogger(this.getClass()); 
	 
	 // 定义jackson对象 
    private static final ObjectMapper MAPPER = new ObjectMapper(); 
    
     
	/** 
     * 如果带有 token,则对 token 进行检查,否则直接通过 
     * >2 接着执行 isAccessAllowed 
     */ 
    @Override 
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException { 
        // 判断请求的请求头是否存在 Token 
        if (isLoginAttempt(request, response)) { 
            //如果存在,则进入 executeLogin 方法执行登入,检查 token 是否正确 
            // 不正常就会抛出异常 
            try { 
                // 执行登录 
                executeLogin(request, response); 
                return true; 
            } catch (Exception e) { 
                //token 错误 
                responseError(response, e.getMessage()); 
            } 
        } else { 
        	try{ 
        	 HttpServletResponse httpResponse = (HttpServletResponse) response; 
             httpResponse.setContentType("application/json;charset=utf-8"); 
             httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); 
             httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin()); 
             httpResponse.setCharacterEncoding("UTF-8"); 
             //设置编码,否则中文字符在重定向时会变为空字符串 
             Map<String, Object> result = new HashMap<>(); 
             result.put("status", 400); 
             result.put("msg", "token 已经注销"); 
             String json = MAPPER.writeValueAsString(result); 
             httpResponse.getWriter().print(json); 
             	return false; 
        	}catch(IOException e) { 
                logger.error(e.getMessage()); 
            } 
        } 
        // 如果请求头不存在 Token,则可能是执行登陆操作或者是游客状态访问, 
        // 无需检查 token,直接返回 true 
        return true; 
    } 
 
    /** 
     * 判断用户是否想要登入。 
     * 检测 header 里面是否包含 Token 字段 
     * 
     */ 
    @Override 
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) { 
        HttpServletRequest req = (HttpServletRequest) request; 
        System.out.println("req.getHeader(Token)"+req.getHeader("Token")); 
        String token = req.getHeader("Token"); 
        if(StringUtils.isEmpty(token)){ 
        	return false; 
        } 
        TokenRelationRepository tokenRelationRepository = SpringContextUtil.getBean(TokenRelationRepository.class); 
        TokenRelation relation = tokenRelationRepository.findByToken(token); 
        if(relation != null){ 
        	return RedisUtils.get(relation.getUsername()) != null; 
        } 
        return false; 
 
    } 
 
    /** 
     * 执行登陆操作 
     * 
     */ 
    @Override 
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { 
        HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
        String token = httpServletRequest.getHeader("Token"); 
 
        JWTToken jwtToken = new JWTToken(token); 
        // 提交给realm进行登入,如果错误他会抛出异常并被捕获 
        getSubject(request, response).login(jwtToken); 
        // 如果没有抛出异常则代表登入成功,返回true 
        return true; 
    } 
 
    /** 
     * 
     * 对跨域提供支持 
     * 
     * >1 请求最先从这开始执行 
     * 
     */ 
    @Override 
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { 
        HttpServletRequest httpServletRequest = (HttpServletRequest) request; 
        HttpServletResponse httpServletResponse = (HttpServletResponse) response; 
        // 设置 header key-value 
        // httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); 
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE,aaa"); 
        // System.out.println(httpServletRequest.getHeader("Origin")); 
 
        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); 
        // System.out.println( httpServletRequest.getHeader("Access-Control-Request-Headers")); 
 
        // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态 
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { 
            httpServletResponse.setStatus(HttpStatus.OK.value()); 
            return false; 
        } 
 
        return super.preHandle(request, response); 
    } 
 
    /** 
     * 将非法请求跳转到 /unauthorized/** 
     */ 
    private void responseError(ServletResponse response, String message) { 
        try { 
 
            HttpServletResponse httpResponse = (HttpServletResponse) response; 
            httpResponse.setContentType("application/json;charset=utf-8"); 
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); 
            httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin()); 
            httpResponse.setCharacterEncoding("UTF-8"); 
            //设置编码,否则中文字符在重定向时会变为空字符串 
            Map<String, Object> result = new HashMap<>(); 
            result.put("status", 500); 
            result.put("msg", message); 
            String json = MAPPER.writeValueAsString(result); 
            httpResponse.getWriter().print(json); 
        } catch (IOException e) { 
 
            logger.error(e.getMessage()); 
        } 
    } 
} 

1.2.8 Redis工具类封装

package com.zzg.redis; 
 
import java.util.Collection; 
import java.util.List; 
import java.util.Map; 
import java.util.concurrent.TimeUnit; 
 
import org.springframework.data.redis.core.RedisTemplate; 
 
import com.zzg.spring.SpringContextUtil; 
 
public class RedisUtils { 
	private RedisUtils() { 
    } 
  
    @SuppressWarnings("unchecked") 
    private static RedisTemplate<String, Object> redisTemplate = SpringContextUtil 
        .getBean("redisTemplate", RedisTemplate.class); 
  
    /** 
     * 设置有效时间 
     * 
     * @param key Redis键 
     * @param timeout 超时时间 
     * @return true=设置成功;false=设置失败 
     */ 
    public static boolean expire(final String key, final long timeout) { 
  
        return expire(key, timeout, TimeUnit.SECONDS); 
    } 
  
    /** 
     * 设置有效时间 
     * 
     * @param key Redis键 
     * @param timeout 超时时间 
     * @param unit 时间单位 
     * @return true=设置成功;false=设置失败 
     */ 
    public static boolean expire(final String key, final long timeout, final TimeUnit unit) { 
  
        Boolean ret = redisTemplate.expire(key, timeout, unit); 
        return ret != null && ret; 
    } 
  
    /** 
     * 删除单个key 
     * 
     * @param key 键 
     * @return true=删除成功;false=删除失败 
     */ 
    public static boolean del(final String key) { 
  
        Boolean ret = redisTemplate.delete(key); 
        return ret != null && ret; 
    } 
  
    /** 
     * 删除多个key 
     * 
     * @param keys 键集合 
     * @return 成功删除的个数 
     */ 
    public static long del(final Collection<String> keys) { 
  
        Long ret = redisTemplate.delete(keys); 
        return ret == null ? 0 : ret; 
    } 
  
    /** 
     * 存入普通对象 
     * 
     * @param key Redis键 
     * @param value 值 
     */ 
    public static void set(final String key, final Object value) { 
  
        redisTemplate.opsForValue().set(key, value, 1, TimeUnit.MINUTES); 
    } 
  
    // 存储普通对象操作 
  
    /** 
     * 存入普通对象 
     * 
     * @param key 键 
     * @param value 值 
     * @param timeout 有效期,单位秒 
     */ 
    public static void set(final String key, final Object value, final long timeout) { 
  
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); 
    } 
  
    /** 
     * 获取普通对象 
     * 
     * @param key 键 
     * @return 对象 
     */ 
    public static Object get(final String key) { 
  
        return redisTemplate.opsForValue().get(key); 
    } 
  
    // 存储Hash操作 
    /** 
     * 删除Hash中指定数据 
     * 
     * @param key Redis键 
     * @param hKey Hash键 
     */ 
    public static void hDelete(final String key, final String hKey) { 
        redisTemplate.opsForHash().delete(key, hKey); 
    } 
  
    /** 
     * 往Hash中存入数据 
     * 
     * @param key Redis键 
     * @param hKey Hash键 
     * @param value 值 
     */ 
    public static void hPut(final String key, final String hKey, final Object value) { 
  
        redisTemplate.opsForHash().put(key, hKey, value); 
    } 
  
    /** 
     * 往Hash中存入多个数据 
     * 
     * @param key Redis键 
     * @param values Hash键值对 
     */ 
    public static void hPutAll(final String key, final Map<String, Object> values) { 
  
        redisTemplate.opsForHash().putAll(key, values); 
    } 
  
    /** 
     * 获取Hash中的数据 
     * 
     * @param key Redis键 
     * @param hKey Hash键 
     * @return Hash中的对象 
     */ 
    public static Object hGet(final String key, final String hKey) { 
  
        return redisTemplate.opsForHash().get(key, hKey); 
    } 
  
    /** 
     * 获取多个Hash中的数据 
     * 
     * @param key Redis键 
     * @param hKeys Hash键集合 
     * @return Hash对象集合 
     */ 
    public static List<Object> hMultiGet(final String key, final Collection<Object> hKeys) { 
  
        return redisTemplate.opsForHash().multiGet(key, hKeys); 
    } 
 
  
    // 存储Set相关操作 
  
    /** 
     * 往Set中存入数据 
     * 
     * @param key Redis键 
     * @param values 值 
     * @return 存入的个数 
     */ 
    public static long sSet(final String key, final Object... values) { 
        Long count = redisTemplate.opsForSet().add(key, values); 
        return count == null ? 0 : count; 
    } 
  
    /** 
     * 删除Set中的数据 
     * 
     * @param key Redis键 
     * @param values 值 
     * @return 移除的个数 
     */ 
    public static long sDel(final String key, final Object... values) { 
        Long count = redisTemplate.opsForSet().remove(key, values); 
        return count == null ? 0 : count; 
    } 
  
    // 存储List相关操作 
  
    /** 
     * 往List中存入数据 
     * 
     * @param key Redis键 
     * @param value 数据 
     * @return 存入的个数 
     */ 
    public static long lPush(final String key, final Object value) { 
        Long count = redisTemplate.opsForList().rightPush(key, value); 
        return count == null ? 0 : count; 
    } 
  
    /** 
     * 往List中存入多个数据 
     * 
     * @param key Redis键 
     * @param values 多个数据 
     * @return 存入的个数 
     */ 
    public static long lPushAll(final String key, final Collection<Object> values) { 
        Long count = redisTemplate.opsForList().rightPushAll(key, values); 
        return count == null ? 0 : count; 
    } 
  
    /** 
     * 往List中存入多个数据 
     * 
     * @param key Redis键 
     * @param values 多个数据 
     * @return 存入的个数 
     */ 
    public static long lPushAll(final String key, final Object... values) { 
        Long count = redisTemplate.opsForList().rightPushAll(key, values); 
        return count == null ? 0 : count; 
    } 
  
    /** 
     * 从List中获取begin到end之间的元素 
     * 
     * @param key Redis键 
     * @param start 开始位置 
     * @param end 结束位置(start=0,end=-1表示获取全部元素) 
     * @return List对象 
     */ 
    public static List<Object> lGet(final String key, final int start, final int end) { 
        return redisTemplate.opsForList().range(key, start, end); 
    } 
 
} 

1.2.9  Apache Shrio 认证相关类定义

package com.zzg.shrio; 
 
import org.apache.shiro.authc.AuthenticationToken; 
 
public class JWTToken implements AuthenticationToken{ 
	/** 
	 *  
	 */ 
	private static final long serialVersionUID = -6747540462673342320L; 
	private String token; 
 
    public JWTToken(String token) { 
        this.token = token; 
    } 
 
 
    @Override 
    public Object getPrincipal() { 
        return token; 
    } 
 
    @Override 
    public Object getCredentials() { 
        return token; 
    } 
} 
package com.zzg.shrio; 
 
import java.util.HashSet; 
import java.util.Set; 
 
import org.apache.shiro.authc.AuthenticationException; 
import org.apache.shiro.authc.AuthenticationInfo; 
import org.apache.shiro.authc.AuthenticationToken; 
import org.apache.shiro.authc.SimpleAuthenticationInfo; 
import org.apache.shiro.authz.AuthorizationInfo; 
import org.apache.shiro.authz.SimpleAuthorizationInfo; 
import org.apache.shiro.realm.AuthorizingRealm; 
import org.apache.shiro.subject.PrincipalCollection; 
import org.apache.shiro.util.CollectionUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Lazy; 
import org.springframework.stereotype.Component; 
 
import com.alibaba.druid.util.StringUtils; 
import com.zzg.dao.RoleRepository; 
import com.zzg.dao.UserRepository; 
import com.zzg.entity.Permission; 
import com.zzg.entity.Role; 
import com.zzg.entity.User; 
import com.zzg.util.JWTUtil; 
 
@Component 
public class MyRealm extends AuthorizingRealm { 
	 
	@Autowired 
	@Lazy 
	private UserRepository userRepository; 
	 
	@Autowired 
	@Lazy 
	private RoleRepository roleRepository; 
 
	 /** 
     * 必须重写此方法,不然会报错 
     */ 
    @Override 
    public boolean supports(AuthenticationToken token) { 
        return token instanceof JWTToken; 
    } 
     
    /** 
     * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的 
     */ 
	@Override 
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 
		// TODO Auto-generated method stub 
		  System.out.println(">执行 doGetAuthorizationInfo 权限认证"); 
	        // principals 传过来的是 token 
	        // System.out.println(">principals = "+principals); 
	        String username = JWTUtil.getUsername(principals.toString()); 
 
	        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 
	        //获得该用户角色 
	        User user = userRepository.findByUsername(username); 
 
	        
 
	        Set<String> roleSet = new HashSet<>(); 
	        Set<String> permissionSet = new HashSet<>(); 
	        // 需要将 role, permission 封装到 Set 作为 info.setRoles(), info.setStringPermissions() 的参数 
	        user.getRoles().stream().forEach(item->{ 
	        	roleSet.add(item.getRoleName()); 
	        }); 
	        user.getRoles().stream().forEach(item->{ 
	        	Role role = roleRepository.findByRoleId(item.getRoleId()); 
	        	if(!CollectionUtils.isEmpty(role.getPermissions())){ 
	        		for(Permission permission : role.getPermissions()){ 
	        			 permissionSet.add(permission.getPermissionPath()); 
	        		} 
	        	} 
	        }); 
	        // 设置该用户拥有的角色和权限 
	        info.setRoles(roleSet); 
	        info.setStringPermissions(permissionSet); 
	        return info; 
	} 
 
	 /** 
     * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。 
     */ 
	@Override 
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { 
		// TODO Auto-generated method stub 
		  System.out.println(">执行 doGetAuthenticationInfo 身份认证"); 
 
	        String token = (String) authenticationToken.getCredentials(); 
	        System.out.println(">token "+token); 
	        // 解密获得 username 用于和数据库进行对比 
	        String username = JWTUtil.getUsername(token); 
 
	        if (username == null || !JWTUtil.verify(token, username)) { 
	            throw new AuthenticationException("token 认证失败"); 
	        } 
 
	        // 检查用户是否存在 通过密码来判断 
	        User user = userRepository.findByUsername(username); 
	        if (StringUtils.isEmpty(user.getPassword())) { 
	            throw new AuthenticationException("该用户不存在 "); 
	        } 
 
	        System.out.println(">getName "+getName()); 
	        // return new SimpleAuthenticationInfo(token, token, "MyRealm"); 
	        return new SimpleAuthenticationInfo(token, token, getName()); 
	} 
 
} 

1.2.10  Spring 工具类

package com.zzg.spring; 
 
import org.springframework.context.ApplicationContext; 
 
 
public class SpringContextUtil { 
	private static ApplicationContext applicationContext; 
 
	public static void setApplicationContext(ApplicationContext applicationContext){ 
		// TODO Auto-generated method stub 
		if(SpringContextUtil.applicationContext == null) { 
			SpringContextUtil.applicationContext = applicationContext; 
		} 
	} 
 
	public static ApplicationContext getApplicationContext() { 
		return applicationContext; 
	} 
 
	// 通过class 获取bean 
	public static <T> T getBean(Class<T> clazz) { 
		return applicationContext.getBean(clazz); 
	} 
	 
	// 通过name 获取bean 
	public static Object getBean(String name) { 
		return applicationContext.getBean(name); 
	} 
	 
	  //通过name,以及Clazz返回指定的Bean 
    public static <T> T getBean(String name,Class<T> clazz){ 
        return applicationContext.getBean(name, clazz); 
    } 
} 

1.2.11  系统封装工具类

package com.zzg.util; 
 
import javax.servlet.http.HttpServletRequest; 
 
import org.springframework.web.context.request.RequestContextHolder; 
import org.springframework.web.context.request.ServletRequestAttributes; 
 
public class HttpContextUtil { 
	public static HttpServletRequest getHttpServletRequest() { 
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 
	} 
 
	public static String getDomain() { 
		HttpServletRequest request = getHttpServletRequest(); 
		StringBuffer url = request.getRequestURL(); 
		return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString(); 
	} 
 
	public static String getOrigin() { 
		HttpServletRequest request = getHttpServletRequest(); 
		return request.getHeader("Origin"); 
	} 
} 
package com.zzg.util; 
 
import java.util.Date; 
 
import com.auth0.jwt.JWT; 
import com.auth0.jwt.JWTVerifier; 
import com.auth0.jwt.algorithms.Algorithm; 
import com.auth0.jwt.exceptions.JWTDecodeException; 
import com.auth0.jwt.interfaces.DecodedJWT; 
 
public class JWTUtil { 
	// 过期时间 24 小时 
	private static final long EXPIRE_TIME = 60 * 24 * 60 * 1000; 
 
	// 密钥 
	private static final String SECRET = "SHIRO+JWT"; 
 
	/** 
	 * 登录时通过 loginController 生成 token, 5min后过期 
	 * 
	 * @param username 
	 *            用户名 
	 * @return 加密的token 
	 */ 
	public static String createToken(String username) { 
 
		try { 
			Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); 
			Algorithm algorithm = Algorithm.HMAC256(SECRET); 
			System.out.println(">algorithm " + algorithm); 
 
			// 返回 token 
			// 附带username信息 
			return JWT.create().withClaim("username", username) 
					// 到期时间 
					.withExpiresAt(date) 
					// 创建一个新的JWT,并使用给定的算法进行标记 
					.sign(algorithm); 
		} catch (Exception e) { 
			return null; 
		} 
	} 
 
	/** 
	 * 校验 token 是否正确 
	 * 
	 * @param token 
	 *            密钥 
	 * @param username 
	 *            用户名 
	 * @return 是否正确 
	 */ 
	public static boolean verify(String token, String username) { 
		System.out.println(">执行 verify"); 
 
		try { 
			Algorithm algorithm = Algorithm.HMAC256(SECRET); 
			// 在token中附带了 username 信息 
			JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build(); 
			// 验证 token 
			verifier.verify(token); 
			return true; 
		} catch (Exception exception) { 
			// 出错就返回 false 
			return false; 
		} 
	} 
 
	/** 
	 * 根据token 获取 username 获得token中的信息,无需 secret 解密也能获得 
	 * 
	 * @return token 中包含的 username 
	 */ 
	public static String getUsername(String token) { 
		try { 
			DecodedJWT jwt = JWT.decode(token); 
			return jwt.getClaim("username").asString(); 
		} catch (JWTDecodeException e) { 
			return null; 
		} 
	} 
} 
package com.zzg.util; 
 
import java.util.Properties; 
 
import com.google.code.kaptcha.impl.DefaultKaptcha; 
import com.google.code.kaptcha.util.Config; 
 
public class KaptchaUtil { 
	private static KaptchaUtil instance; 
	  
	private KaptchaUtil() { 
	}; 
  
	public static KaptchaUtil getInstance() { 
		if (instance == null) { 
			instance = new KaptchaUtil(); 
		} 
		return instance; 
	} 
  
	/** 
	 * 生成DefaultKaptcha 默认配置 
	 * @return 
	 */ 
	public DefaultKaptcha produce() { 
		Properties properties = new Properties(); 
		properties.put("kaptcha.border", "no"); 
		properties.put("kaptcha.border.color", "105,179,90"); 
		properties.put("kaptcha.textproducer.font.color", "blue"); 
		properties.put("kaptcha.image.width", "100"); 
		properties.put("kaptcha.image.height", "50"); 
		properties.put("kaptcha.textproducer.font.size", "27"); 
		properties.put("kaptcha.session.key", "code"); 
		properties.put("kaptcha.textproducer.char.length", "4"); 
		properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); 
		properties.put("kaptcha.textproducer.char.string", "0123456789ABCEFGHIJKLMNOPQRSTUVWXYZ"); 
		properties.put("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple"); 
		properties.put("kaptcha.noise.color", "black"); 
		properties.put("kaptcha.noise.impl", "com.google.code.kaptcha.impl.DefaultNoise"); 
		properties.put("kaptcha.background.clear.from", "185,56,213"); 
		properties.put("kaptcha.background.clear.to", "white"); 
		properties.put("kaptcha.textproducer.char.space", "3"); 
		 
		Config config = new Config(properties); 
		DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); 
		defaultKaptcha.setConfig(config); 
		return defaultKaptcha; 
	} 
 
} 

1.2.12  实体对象拓展

package com.zzg.vo; 
 
import java.util.List; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
public class PermissionVo { 
	private Integer permissionId; 
	private String permissionName; 
	private String permissionZh; 
	private String permissionPath; 
	private String permisionIcon; 
	private String permisionComponent; 
	private Integer permisionParentId; 
	private List<PermissionVo> child; 
} 

1.2.13  SpringBoot 程序入口

package com.zzg; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.autoconfigure.domain.EntityScan; 
import org.springframework.context.ApplicationContext; 
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 
 
import com.zzg.spring.SpringContextUtil; 
 
 
@SpringBootApplication 
@EntityScan("com.zzg.entity") //Spring-JPA实体扫描 
@EnableJpaRepositories(basePackages = { "com.zzg.dao" }) //Spring-JPA Repository扫描 
public class ShrioApplication { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		 ApplicationContext applicationContext = SpringApplication.run(ShrioApplication.class, args); 
		 SpringContextUtil.setApplicationContext(applicationContext); 
	} 
 
} 

1.2.14 SpringBoot 程序资源文件(application.yml)

# Tomcat 
server: 
  tomcat: 
    uri-encoding: UTF-8 
    max-threads: 1000 
    min-spare-threads: 30 
  port: 9090 
  connection-timeout: 5000ms 
  servlet: 
    context-path: /shiro 
#spring 
spring: 
  # 数据源 
  datasource: 
    type: com.alibaba.druid.pool.DruidDataSource 
    druid: 
      driver-class-name: com.mysql.cj.jdbc.Driver 
      url: jdbc:mysql://127.0.0.1:3306/auth_shrio?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai 
      username: root 
      password: 123456 
      initial-size: 10 
      max-active: 100 
      min-idle: 10 
      max-wait: 60000 
      pool-prepared-statements: true 
      max-pool-prepared-statement-per-connection-size: 20 
      time-between-eviction-runs-millis: 60000 
      min-evictable-idle-time-millis: 300000 
      test-while-idle: true 
      test-on-borrow: false 
      test-on-return: false 
      stat-view-servlet: 
        enabled: true 
        url-pattern: /druid/* 
      filter: 
        stat: 
          log-slow-sql: false 
          slow-sql-millis: 1000 
          merge-sql: false 
        wall: 
          config: 
            multi-statement-allow: true 
  jpa: 
    show-sql: true 
    hibernate: 
      ddl-auto: update 
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect 
    database: mysql 
  redis: 
    database: 0 
    host: 127.0.0.1 
    port: 6379 
    password: abc123

1.2.15 SpringBoot 程序依赖pom.xml 文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.zzg</groupId> 
  <artifactId>lease_sys</artifactId> 
  <version>0.0.1-SNAPSHOT</version> 
   
  <parent> 
		<groupId>org.springframework.boot</groupId> 
		<artifactId>spring-boot-starter-parent</artifactId> 
		<version>2.1.0.RELEASE</version> 
		<relativePath /> <!-- lookup parent from repository --> 
	</parent> 
	 
	<properties> 
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
	   <encoding>UTF-8</encoding> 
	   <java.version>1.8</java.version> 
    </properties> 
     
      <dependencies> 
        <!--starter--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter</artifactId> 
        </dependency> 
        <!--  test--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-test</artifactId> 
            <scope>test</scope> 
        </dependency> 
        <!--web--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-web</artifactId> 
        </dependency> 
        <!--validation--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-validation</artifactId> 
        </dependency> 
        <!--JPA--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-data-jpa</artifactId> 
        </dependency> 
        <!--JDBC--> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-jdbc</artifactId> 
        </dependency> 
        <!--lombok--> 
        <dependency> 
            <groupId>org.projectlombok</groupId> 
            <artifactId>lombok</artifactId> 
        </dependency> 
        <!-- shiro--> 
        <dependency> 
            <groupId>org.apache.shiro</groupId> 
            <artifactId>shiro-spring</artifactId> 
            <version>1.3.2</version> 
        </dependency> 
        <!-- jwt  --> 
        <dependency> 
            <groupId>com.auth0</groupId> 
            <artifactId>java-jwt</artifactId> 
            <version>3.8.1</version> 
        </dependency> 
        <!--mysql-connector--> 
        <dependency> 
            <groupId>mysql</groupId> 
            <artifactId>mysql-connector-java</artifactId> 
            <scope>runtime</scope> 
        </dependency> 
        <!-- druid-spring-boot-starter --> 
        <dependency> 
            <groupId>com.alibaba</groupId> 
            <artifactId>druid-spring-boot-starter</artifactId> 
            <version>1.1.10</version> 
        </dependency> 
        <!-- redis--> 
		<dependency> 
    		<groupId>org.springframework.boot</groupId> 
    		<artifactId>spring-boot-starter-data-redis</artifactId> 
		</dependency> 
        <!-- commons-lang --> 
        <dependency> 
            <groupId>commons-lang</groupId> 
            <artifactId>commons-lang</artifactId> 
            <version>2.6</version> 
        </dependency> 
        <!-- apache common 模块 --> 
		<!--commons-lang3 工具包 --> 
		<dependency> 
			<groupId>org.apache.commons</groupId> 
			<artifactId>commons-lang3</artifactId> 
			<version>3.9</version> 
		</dependency> 
		<!--commons-codec 加密工具包 --> 
		<dependency> 
			<groupId>commons-codec</groupId> 
			<artifactId>commons-codec</artifactId> 
			<version>1.10</version> 
		</dependency> 
		<!--commons-net 网络工具包 --> 
		<dependency> 
			<groupId>commons-net</groupId> 
			<artifactId>commons-net</artifactId> 
			<version>3.6</version> 
		</dependency> 
		<!--common-io 工具包 --> 
		<dependency> 
			<groupId>commons-io</groupId> 
			<artifactId>commons-io</artifactId> 
			<version>2.6</version> 
		</dependency> 
		<!--common-collection 工具包 --> 
		<dependency> 
			<groupId>commons-collections</groupId> 
			<artifactId>commons-collections</artifactId> 
			<version>3.2.1</version> 
		</dependency> 
        <!-- 依赖kaptcha图形生成器  --> 
		<dependency> 
			<groupId>com.github.penggle</groupId> 
			<artifactId>kaptcha</artifactId> 
			<version>2.3.2</version> 
		</dependency> 
    </dependencies> 
   
</project>

1.2.15 SpringBoot  项目整体截图:

1.3 Vue项目源码

1.3.1 Vue 项目整体结构图

1.3.2 main.js 函数:安装element-ui、安装axios、集成路由(router)、集成Vuex(store)

// The Vue build version to load with the `import` command 
// (runtime-only or standalone) has been set in webpack.base.conf with an alias. 
import Vue from 'vue' 
import App from './App' 
import router from './router' 
import store from  './store' 
import ElementUI from 'element-ui'; 
import 'element-ui/lib/theme-chalk/index.css'; 
import axios from 'axios' 
 
Vue.prototype.$axios = axios 
Vue.use(ElementUI); 
Vue.config.productionTip = false 
 
/* eslint-disable no-new */ 
new Vue({ 
  el: '#app', 
  router, 
  store, 
  components: { App }, 
  template: '<App/>' 
}) 

1.3.3 App.vue:定义Vue程序入口

<template> 
  <div id="app"> 
    <router-view/> 
  </div> 
</template> 
 
<script> 
export default { 
  name: 'App' 
} 
</script> 
 
<style> 
* { 
  margin: 0; 
  padding: 0; 
  box-sizing: border-box; 
} 
</style> 

1.3.4 utils 文件夹:封装axios 请求(post\get\delete),  封装axios 请求拦截器和响应拦截器 、异步转同步定时函数

import axios from 'axios' 
// 设置后端请求地址 
axios.defaults.baseURL='http://192.168.1.74:9090/shiro' 
// post请求头 
axios.defaults.headers.post['Content-Type'] = 'application/json' 
// 携带凭证信息 
axios.defaults.withCredentials = true 
 
// 添加请求拦截器,在请求头中加token 
axios.interceptors.request.use( 
    config => { 
      if (window.localStorage.getItem('token')) { 
        config.headers.token = window.localStorage.getItem('token'); 
      } 
      return config; 
    }, 
    error => { 
      return Promise.reject(error); 
    }); 
   
  // 添加响应拦截器,移除token 
  axios.interceptors.response.use( 
    response =>{ 
      return response; 
    }, 
    error=>{ 
      if(error.response){ 
        switch(error.response.status){ 
          case 401: 
            localStorage.removeItem('token'); 
            this.$router.push('/login'); 
        } 
      } 
    }) 
 
/** 
 * get方法,对应get请求 
 * @param {Stringf} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */ 
export function get (url, params) { 
    return new Promise((resolve, reject) => { 
      axios.get(url, { 
        params: params 
      }).then(res => { 
        resolve(res.data) 
      }).catch(err => { 
        reject(err.data) 
      }) 
    }) 
  } 
   
  /** 
   * post方法,对应post请求 
   * @param {String} url [请求的url地址] 
   * @param {Object} params [请求时携带的参数] 
   */ 
  export function post (url, params) { 
    return new Promise((resolve, reject) => { 
      axios.post(url, params).then(res => { 
        resolve(res.data) 
      }).catch(err => { 
        reject(err.data) 
      }) 
    }) 
  } 
   
  /** 
   * del 方法,对应del 请求 
   * @param {String} url [请求的url地址]  
   * @param {Object} params [请求时携带的参数]  
   */ 
  export function del (url, params) { 
    return new Promise((resolve, reject) => { 
      axios.delete(url, params).then(res => { 
        resolve(res.data) 
      }).catch(err => { 
        reject(err.data) 
      }) 
    }) 
  } 
 
  export function waitsleep (method) { 
    const start = Number(Date.now()) 
    return new Promise((resolve) => { 
      (function selfRecursion () { 
        setTimeout(() => { 
          let flag 
          if (typeof method === 'function') { 
            flag = method() 
          } 
          if (typeof method === 'number') { 
            flag = Number(Date.now()) - start < method 
          } 
          if (flag) { 
            selfRecursion() 
          } else { 
            resolve() 
          } 
        }, 10) 
      })() 
    }) 
  }

 routerFormat.js :动态加载菜单函数定义

/** 
 * 构建动态菜单路由对象 
 * @param {Object} routes [后台返回路由数据] 
 */ 
export function formatRoutes (routes) { 
    console.log(routes) 
    let fmtRoutes = [] 
    routes.forEach(routes => { 
      if (routes.child) { 
        routes.child = formatRoutes(routes.child) 
      } 
   
      let fmtRoute = { 
        path: routes.permissionPath, 
        component: resolve => { 
          require(['@/components/admin/' + routes.permisionComponent + '.vue'], resolve) 
        }, 
        name: routes.permissionName, 
        nameZh: routes.permissionZh, 
        iconCls: routes.permisionIcon, 
        children: routes.child 
      } 
      fmtRoutes.push(fmtRoute) 
    }) 
    return fmtRoutes 
  } 
  

initAdmin.js:触发动态加载菜单函数

import {get, waitsleep} from '@/utils/http' 
import {formatRoutes} from '../utils/routerFormat' 
 
export default function initAdminMenu (router, store) { 
  if (store.state.adminMenus.length > 0) { 
    return 
  } 
 
  // 定时函数:定时函数实现异步方法模拟同步方法 
  waitsleep(() => store.state.uid === -1).then(() => { 
    // 动态权限请求 
    get('/permission/' + store.state.uid).then(resp => { 
    console.log(resp.date) 
    console.log(resp.date) 
    var fmtRoutes = formatRoutes(resp.date) 
    router.addRoutes(fmtRoutes) 
    store.commit('initAdminMenu', fmtRoutes) 
    }) 
  }) 
} 

1.3.5 store文件夹:定义存储在Vuex 中的变量

index.js

import Vue from 'vue' 
import Vuex from 'vuex' 
Vue.use(Vuex); 
  
const store = new Vuex.Store({ 
  
  state: { 
    // 存储token 
    token: window.localStorage.getItem('token') ? window.localStorage.getItem('token') : '', 
    // 存储username 
    username: window.localStorage.getItem('username')  ? window.localStorage.getItem('username') : '', 
    // 存储用户ID 
    uid: -1, 
    // 存储用户菜单 
    adminMenus: [] 
  }, 
  
  mutations: { 
    // 修改token,并将token存入localStorage 
    setToken (state, user) { 
      console.log(user) 
      state.token = user; 
      window.localStorage.setItem('token', user); 
    }, 
    setUserName (state, user) { 
      console.log(user) 
      state.username = user; 
      window.localStorage.setItem('username', user); 
    }, 
    setUserId (state, user) { 
      console.log(user) 
      state.uid = user 
    }, 
    initAdminMenu (state, menu) { 
      state.adminMenus = menu 
    }, 
    logout (state, user) { 
      state.username = '' 
      state.token = '' 
      state.uid = -1 
      state.adminMenus = [] 
      localStorage.removeItem('token') 
      localStorage.removeItem('username') 
    } 
  } 
}); 
  
export default store;

1.3.6 route文件夹:定义组件路由访问和路由守护

index.js

import Vue from 'vue' 
import Router from 'vue-router' 
import login from '@/components/login'; 
import Admin from '@/components/admin/AdminIndex' 
import initAdminMenu from '../utils/initAdmin' 
import store from  '../store' 
 
Vue.use(Router) 
 
const router = new Router({ 
  routes: [ 
    { 
      path: '/', 
      redirect: '/login' 
    }, 
    { 
      path: '/login', 
      name: 'login', 
      component: login 
    }, 
    { 
      path: '/admin', 
      name: 'admin', 
      component: Admin, 
      redirect: '/admin/dashboard', 
      children: [ 
        { 
          path: '/admin/dashboard', 
          name: 'adminDashboard', 
          component: () => import('@/components/admin/dashboard/Index') 
        }, 
        { 
          path: '/admin/user/Profile', 
          name: 'adminUserProfile', 
          component: () => import('@/components/admin/user/Profile') 
        }, 
        { 
          path: '/admin/user/Role', 
          name: 'adminUserRole', 
          component: () => import('@/components/admin/user/Role') 
        }, 
        { 
          path: '/admin/test/Test1', 
          name: 'adminTest1', 
          component: () => import('@/components/admin/test/Test1') 
        }, 
        { 
          path: '/admin/test/Test2', 
          name: 'adminTest2', 
          component: () => import('@/components/admin/test/Test2') 
        } 
      ] 
    } 
  ] 
}) 
// 导航守卫 
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆 
router.beforeEach((to, from, next) => { 
  if (to.path === '/login') { 
    next(); 
  } else { 
    let token = localStorage.getItem('token'); 
    if (token === null || token === '') { 
      next('/login'); 
    } else { 
      console.log('12345') 
      // 查询动态表单 
      initAdminMenu(router, store) 
      // 跳转至指定页面 
      next(); 
    } 
  } 
}); 
  
export default router; 

1.3.7 components文件夹:定义组件

components/login.vue 定义:登入首页

 
<template> 
  <div class="login-container"> 
    <el-form label-position="left" 
      label-width="0px" 
      status-icon> 
        <h3 class="login_title">系统登录</h3> 
        <el-form-item> 
          <el-input 
            type="text" 
            v-model="loginForm.username" 
            auto-coplete="off" 
            placeholder="账号"> 
          </el-input> 
        </el-form-item> 
        <el-form-item> 
          <el-input 
            type="password" 
            v-model="loginForm.password" 
            auto-coplete="off" 
            placeholder="密码"> 
          </el-input> 
        </el-form-item> 
        <el-form-item style="width: 100%"> 
          <el-button type="primary" @click.native.prevent="login" style="width: 100%">登录</el-button> 
          <!-- 
          <el-button type="primary" @click.native.prevent="register" style="width: 100%; margin-top: 30px">注册</el-button> 
          --> 
        </el-form-item> 
      </el-form> 
  </div> 
</template> 
  
<script> 
import { post, waitsleep } from '@/utils/http' 
export default { 
  data () { 
    return { 
      loginForm: { 
        username: '', 
        password: '' 
      }, 
      userToken: '' 
    }; 
  }, 
  
  methods: { 
    login () { 
      let _this = this; 
      if (this.loginForm.username === '' || this.loginForm.password === '') { 
        alert('账号或密码不能为空'); 
      } else { 
        var params = { 
        username: _this.loginForm.username, 
        password: _this.loginForm.password 
      } 
        post('/common/login',params).then(res => { 
           console.log(res); 
          _this.userToken = res.token; 
          // 将用户token保存到vuex中 
          _this.$store.commit('setToken', res.token); 
          _this.$store.commit('setUserName', res.username); 
          _this.$store.commit('setUserId', res.uid); 
 
          _this.$router.push('/admin'); 
          alert('登陆成功'); 
        }) 
         
      } 
    } 
  } 
}; 
</script> 
<style scoped> 
.login-container{ 
  border-radius: 15px; 
  background-clip: padding-box; 
  margin: 10% auto; 
  width: 350px; 
  padding: 35px 35px 15px 35px; 
  background: #fff; 
  border: 1px solid #eaeaea; 
  box-shadow: 0 0 25px #cac6c6; 
} 
.login_title{ 
  margin: 0px auto 40px auto; 
  text-align: center; 
  color: #505458; 
} 
</style> 
 

components/home/Head.vue 定义:公共顶部栏组件

<!--  --> 
<template> 
  <div> 
    <div class="home_title">后台系统</div> 
    <div class="home_userinfoContainer"> 
      <el-dropdown @command="handleCommand"> 
        <span class="el-dropdown-link home_userinfo"> 
          {
  {currentUserName}} 
          <i class="el-icon-arrow-down el-icon--right home_userinfo"></i> 
        </span> 
        <el-dropdown-menu slot="dropdown"> 
          <el-dropdown-item command="goIndex">返回主页</el-dropdown-item> 
          <el-dropdown-item command="logout" divided>退出登录</el-dropdown-item> 
        </el-dropdown-menu> 
      </el-dropdown> 
    </div> 
  </div> 
</template> 
 
<script> 
import {post} from '@/utils/http' 
export default { 
  data () { 
    return { 
      currentUserName: '' 
    } 
  }, 
  mounted: function getUser () { 
    this.currentUserName = this.$store.state.username 
  }, 
  methods: { 
    handleCommand (command) { 
      var _this = this 
      if (command === 'logout') { 
        this.$confirm('注销登录吗?', '提示', { 
          confirmButtonText: '确定', 
          cancelButtonText: '取消', 
          type: 'warning' 
        }).then(function () { 
          post('/sys/logout') 
          _this.$store.commit('logout') 
          _this.$router.replace({name: 'login'}) 
          _this.$message.success('退出成功') 
        }, function () { 
          // 取消 
        }) 
      } else if (command === 'goIndex') { 
        this.$router.push({name: 'index'}) 
      } 
    } 
  } 
} 
</script> 
<style> 
  .el-header { 
    background-color: #20a0ff; 
    color: #333; 
    text-align: center; 
    display: flex; 
    align-items: center; 
    justify-content: space-between; 
  } 
 
  .home_title { 
    color: #fff; 
    font-size: 22px; 
    display: inline; 
  } 
 
  .home_userinfo { 
    color: #fff; 
    cursor: pointer; 
  } 
 
  .home_userinfoContainer { 
    position: absolute; 
    right: 0px; 
    display: inline; 
    margin-right: 20px; 
  } 
</style> 

components/home/Side.vue 定义:公共动态菜单栏组件

<!--  --> 
<template> 
  
    <el-menu router default-active="/admin/dashboard" mode="vertical" :collapse="isCollapse"  style="height:100%"> 
      <template v-for="(item,i) in adminMenus"> 
        <el-submenu :key="i" :index="i + ''" style="text-align: left"> 
          <span slot="title"> 
              <i :class="item.iconCls" style="font-size:10px"></i> 
            {
  {item.nameZh}} 
          </span> 
          <el-menu-item v-for="child in item.children" :key="child.path" :index="child.path"> 
            <i :class="child.icon"></i> 
            {
  { child.nameZh }} 
          </el-menu-item> 
        </el-submenu> 
      </template> 
    </el-menu> 
   
</template> 
 
<script> 
export default { 
  data () { 
    return { 
      isCollapse: false 
      // adminMenus: [ 
      //   { 
      //     iconCls: 'el-icon-s-home', 
      //     nameZh: '首页', 
      //     children: [ 
      //       { 
      //         icon: '', 
      //         nameZh: '首页1-1', 
      //         path: '/admin/user/Profile' 
      //       } 
      //     ] 
      //   } 
      // ] 
    } 
  }, 
  computed: { 
    adminMenus () { 
      return this.$store.state.adminMenus 
    } 
  } 
} 
</script> 

components/admin/AdminIndex.vue: 系统首页框架

<!--  --> 
<template> 
  <div> 
    <el-container> 
      <el-header> 
        <Head></Head> 
      </el-header> 
      <el-container ref="homePage"> 
        <el-aside :width="sideWidth"> 
          <Side></Side> 
        </el-aside> 
        <el-main> 
          <router-view /> 
        </el-main> 
      </el-container> 
    </el-container> 
  </div> 
</template> 
 
<script> 
import Side from '@/components/home/Side' 
import Head from '@/components/home/Head' 
export default { 
  data () { 
    return { 
      clientHeight: '', 
      sideWidth: '200px' 
    } 
  }, 
  mounted: function () { 
    // 获取浏览器可视区域高度 
    this.clientHeight = `${document.documentElement.clientHeight}` 
    this.sideWidth = document.body.clientWidth * 0.15 + 'px' 
    // document.body.clientWidth; 
    // console.log(self.clientHeight); 
    window.onresize = function temp () { 
      this.clientHeight = `${document.documentElement.clientHeight}` 
    } 
  }, 
  watch: { 
    // 如果 `clientHeight` 发生改变,这个函数就会运行 
    clientHeight: function () { 
      this.changeFixed(this.clientHeight) 
    } 
  }, 
  methods: { 
    changeFixed (clientHeight) { 
      // 动态修改样式 
      // console.log(clientHeight); 
      // console.log(this.$refs.homePage.$el.style.height); 
      this.$refs.homePage.$el.style.height = clientHeight - 80 + 'px' 
    } 
  }, 
  components: { 
    Head, 
    Side 
  } 
} 
</script> 
<style> 
</style> 

components/admin/dashboard/index.vue: 系统首页详情

<template> 
    <div> 
      首页 
    </div> 
</template> 
 
<script> 
export default { 
  name: 'Index', 
  data () { 
    return {} 
  }, 
  computed: {}, 
  watch: {}, 
  methods: {} 
} 
</script> 
 
<style scoped> 
 
</style> 

components/admin/test/Test1.vue: 测试页面一

<template> 
    <div> 
      测试1 
    </div> 
</template> 
 
<script> 
export default { 
  name: 'Test1', 
  data () { 
    return {} 
  }, 
  computed: {}, 
  watch: {}, 
  methods: {} 
} 
</script> 
 
<style scoped> 
 
</style> 

components/admin/test/Test2.vue: 测试页面二

<template> 
    <div> 
      测试2 
    </div> 
</template> 
 
<script> 
export default { 
  name: 'Test2', 
  data () { 
    return {} 
  }, 
  computed: {}, 
  watch: {}, 
  methods: {} 
} 
</script> 
 
<style scoped> 
 
</style> 

components/admin/user/Role.vue: 角色配置详情页面

<template> 
    <div> 
      角色配置 
    </div> 
</template> 
 
<script> 
export default { 
  name: 'Role', 
  data () { 
    return {} 
  }, 
  computed: {}, 
  watch: {}, 
  methods: {} 
} 
</script> 
 
<style scoped> 
 
</style> 

components/admin/user/Profile.vue: 用户详情页面

<template> 
    <div> 
        用户信息 
    </div> 
</template> 
 
<script> 
export default { 
  name: 'Profile', 
  data () { 
    return {} 
  }, 
  computed: {}, 
  watch: {}, 
  methods: {} 
} 
</script> 
 
<style scoped> 
 
</style> 

1.3.8 package.json:需要安装的第三方工具包

1.4 效果展示

 

前端git 项目地址:https://github.com/zhouzhiwengang/eight.git

后台git 项目地址:https://github.com/zhouzhiwengang/lease_sys.git

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
KIKK导航

KIKK导航

关注我们