Java 企业级权限管理项目笔记(六) - - - 项目准备与核心辅导工具类开发

权限管理开发-准备

一、核心类生成 - Mybatis generate

功能 : MyBatis官方提供了逆向工程 mybatis-generator,可以针对数据库表自动生成MyBatis执行所需要的代码(如Mapper.java、Mapper.xml、POJO)。mybatis-generator 有三种用法:命令行、eclipse插件、maven插件。

1、添加generate插件到permission工程中   

   

根据插件包路径对配置文件 generator.xml 配置文件进行相应修改:

第一点:

修改为mysql-connector-java.5.1.34.jar所在的路径

第二点:

修改数据库连接配置

扫描二维码关注公众号,回复: 7468670 查看本文章
	<jdbcConnection driverClass="com.mysql.jdbc.Driver"				
	connectionURL="jdbc:mysql://192.168.254.111:3306/test1?characterEncoding=utf8"
			userId="root"
			password="root">  <!-- 2 -->

第三点到第五点:

配置生成的类的包及保存路径

第六点:

配置要生成的表及对应的表的实体类名称。

2、执行生成命令:

J:\permission\permission\generator>java -jar mybatis-generator-core-1.3.2.jar -configfile generator.xml
MyBatis Generator finished successfully.

执行结果:

                

二、项目接口定义 -json,page

后台收到前台的请求时,一般有两种请求,一种是数据请求,一种页面请求;返回请求结果时,除了返回请求的结果时,还需要返回相关的状态,用于返回异常以及异常描述。

创建JsonData用于封装数据

package com.webcode.springboot.common;

import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.Map; /** * @ClassName JsonData * @Description TODO * @Author wushaopei * @Date 2019/10/11 14:05 * @Version 1.0 */ @Setter @Getter public class JsonData { private boolean ret; private String msg; private Object data; public JsonData(boolean ret) { this.ret = ret; } //需要传数据和异常状态 public static JsonData success(Object object,String msg){ JsonData jsonData = new JsonData(true); jsonData.data = object; jsonData.msg = msg; return jsonData; } //只需要传数据 public static JsonData success(Object object){ JsonData jsonData = new JsonData(true); jsonData.data = object; return jsonData; } //不需要数据,只需要传状态 public static JsonData success(){ return new JsonData(true); } //请求失败 public static JsonData fail(String msg){ JsonData jsonData = new JsonData(false); jsonData.msg = msg; return jsonData; } } 

ret为true代表请求结果为所需要的数据内容,为false时代表请求被拒绝或权限不足、异常等,配合msg进行描述。

三、接口请求全局异常处理-设计与验证

添加相关依赖:

    <!--jsp-->
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>jsp-api</artifactId>
      <version>6.0.36</version>
    </dependency>

创建异常拦截类:

/**
 * @ClassName SpringExceptionResolver
 * @Description TODO
 * @Author wushaopei
 * @Date 2019/10/11 14:27 * @Version 1.0 */ @Slf4j public class SpringExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception ex) { String url = request.getRequestURL().toString(); String[] split = url.split(""); String s = split[split.length - 1]; int i = s.indexOf("/"); if(s.indexOf("/")==0){ StringBuffer sb = new StringBuffer(url); url= sb.substring(0, sb.length() - 1); System.out.println(url); } ModelAndView mv; //声明一个modelandvie,用于返回 String defaultMsg = "System error"; //这里区别对数据请求和页面请求进行的处理 //.json , .page ,请求的区分根据其后缀进行区分 //这里要求项目中所有请求json数据,都使用.json结尾 if (url.endsWith(".json")){ }else{ } return null; } } 

这里使用@Slf4j进行日志的输出。

创建自定义异常类 PermissionException:

package com.webcode.springboot.exception;
/**
 * @ClassName PermissionException
 * @Description TODO
 * @Author wushaopei * @Date 2019/10/11 14:36 * @Version 1.0 */ public class PermissionException extends RuntimeException { public PermissionException() { super(); } public PermissionException(String message) { super(message); } public PermissionException(String message, Throwable cause) { super(message, cause); } public PermissionException(Throwable cause) { super(cause); } public PermissionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } } 

JsonData.java 补充:

 public Map<String, Object> toMap(){
        HashMap<String, Object> result = new HashMap<>(); result.put("ret",ret); result.put("msg",msg); result.put("data",data); return result; }

创建exception.jsp 异常描述页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Exception</title> </head> <body> </body> </html> 

完整的异常拦截:

 @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception ex) { String url = request.getRequestURL().toString(); ModelAndView mv; //声明一个modelandvie,用于返回 String defaultMsg = "System error"; //这里区别对数据请求和页面请求进行的处理 //.json , .page ,请求的区分根据其后缀进行区分 //这里要求项目中所有请求json数据,都使用.json结尾 if (url.endsWith(".json")){ //当前异常是否匹配自定义异常拦截的实例或子类实例 if(ex instanceof PermissionException){ //只要异常是我们创建出来的时,才处理自己抛出来的异常 JsonData fail = JsonData.fail(ex.getMessage()); mv = new ModelAndView("jsonView",fail.toMap()); }else { log.error("unknown json exception, url:" + url, ex); JsonData fail = JsonData.fail(defaultMsg); mv = new ModelAndView("jsonView",fail.toMap()); } }else if(url.endsWith(".page")){ // 这里我们要求项目中所有请求page页面,都使用.page结尾 log.error("unknown page exception, url:" + url, ex); JsonData fail = JsonData.fail(defaultMsg); mv = new ModelAndView("exception",fail.toMap()); }else { JsonData fail = JsonData.fail(defaultMsg); mv = new ModelAndView("jsonView",fail.toMap()); } return mv; }

为什么 ModelAndView的构造器加入 ".toMap()"方法:

               

由图中ModelAndView的源码可知,其构造器默认对数据使用Map进行封装,所以为了符合ModelAndView的代码规范,这里对JsonData的异常返回结果进行Map的转化。

而第一个参数“jsonView”对应spring-servlet.xml中的配置:

Bean配置:

    <bean class="com.webcode.springboot.common.SpringExceptionResolver"/>

接口测试异常拦截:

使用普通的RuntimeException创建异常对象:

@Controller
@RequestMapping("/test")
@Slf4j
public class TestController { @RequestMapping("/hello.json") @ResponseBody public JsonData hello(){ log.info("hello"); throw new RuntimeException("test exception"); } }

             

使用自定义的PermissionException创建异常对象:

   @RequestMapping("/hello.json")
    @ResponseBody
    public JsonData hello(){ log.info("hello"); throw new PermissionException("test exception"); // return JsonData.success("hello,permission"); }

             

四、校验工具-BeanValidator开发

1、添加环境依赖:

    <!--validator-->
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.2.4.Final</version>
    </dependency>

2、创建BeanValidator类

public class BeanValidator {

    private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); public static <T> Map<String,String> validate(T t, Class... groups){ Validator validator = validatorFactory.getValidator(); Set validateResult = validator.validate(t,groups); if (validateResult.isEmpty()){ return Collections.emptyMap(); }else { LinkedHashMap errors = Maps.newLinkedHashMap(); Iterator iterator = validateResult.iterator(); while (iterator.hasNext()){ ConstraintViolation violation = (ConstraintViolation) iterator.next(); errors.put(violation.getPropertyPath().toString(),violation.getMessage()); } return errors; } } public static Map<String,String> validateList(Collection<?> collection){ Preconditions.checkNotNull(collection); Iterator<?> iterator = collection.iterator(); Map errors; do { if (!iterator.hasNext()){ return Collections.emptyMap(); } Object object = iterator.next(); errors = validate(object,new Class[0]); }while (errors.isEmpty()); return errors; } }

创建TestVo类:

@Getter
@Setter
public class TestVo { @NotBlank private String msg; @NotNull private Integer id; } 

接口测试:

@ResponseBody
    @RequestMapping("/validate.json")
    public JsonData validate(TestVo vo){ log.info("validate"); try { Map<String, String> map = BeanValidator.validateObject(vo); if (map != null && map.entrySet().size() > 0){ for (Map.Entry<String, String> entry : map.entrySet()) { log.info("{}->{}",entry.getKey(),entry.getValue()); } } }catch (Exception e){ } return JsonData.success("test validate"); }

没有传参的情况下,控制台打印异常报警日志:

带参数的请求:

http://localhost/test/validate.json/?id=1&msg=123123

没有异常报警:

BeanValidator的使用:

说明:BeanValidator是基于注解的,

基于@NotBlank、@NotNull、@NotEmpty等注解

@Getter
@Setter
public class TestVo { @NotBlank private String msg; @NotNull(message = "id不可以为空") @Max(value = 10,message = "id 不能大于10") @Min(value = 0,message = "id 至少大于等于0") private Integer id; @NotEmpty private List<String> str; } 

对Object参数进行判空,不做结果返回:

  public static void check(Object param){ //参数异常处理 Map<String, String> map = BeanValidator.validateObject(param); if(MapUtils.isNotEmpty(map)){ throw new ParamException(map.toString()); } }

MapUtils用于判空,需要引入相关依赖:

    <!--tools-->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.2.2</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.10</version>
    </dependency>

创建参数异常处理类 ParamException.java

public class ParamException extends RuntimeException { public ParamException() { public ParamException(String message) { super(message); } public ParamException(String message, Throwable cause) { super(message, cause); } public ParamException(Throwable cause) { super(cause); } public ParamException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } } 

测试:

  @ResponseBody
    @RequestMapping("/validate2.json")
    public JsonData validate2(TestVo vo){ log.info("validate2"); BeanValidator.check(vo); return JsonData.success("test validate2"); }

五、权限管理开发 - 工具相关

校验工具 - validator

Json转换工具 - jackson convert

导入相关依赖:

   <!--jackson-->
    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-core-asl</artifactId>
      <version>1.9.13</version>
    </dependency>
    <dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-mapper-asl</artifactId>
      <version>1.9.13</version>
    </dependency>

创建JsonMapper.java类,该类可以把类转换为一个json对象,也可以把类转换为我们指定的类对象。

package com.webcode.springboot.util;




import lombok.extern.slf4j.Slf4j;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider; import org.codehaus.jackson.type.TypeReference; /** * @ClassName JsonMapper * @Description TODO * @Author wushaopei * @Date 2019/10/11 22:56 * @Version 1.0 */ @Slf4j public class JsonMapper { private static ObjectMapper objectMapper = new ObjectMapper(); static { //config objectMapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false); objectMapper.setFilters(new SimpleFilterProvider().setFailOnUnknownId(false)); objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY); } public static <T> String obj2String(T src){ if (src == null){ return null; } try { return src instanceof String ? (String) src : objectMapper.writeValueAsString(src); }catch (Exception e){ log.warn("parse object to String exception",e); return null; } } public static <T> T string2Obj(String src, TypeReference<T> typeReference){ if (src == null || typeReference == null){ return null; } try { return (T) (typeReference.getType().equals(String.class)? src : objectMapper.readValue(src,typeReference)); }catch (Exception e){ log.warn("parse String to Object exception,String:{},TypeReference<T>:{},error{}",src,typeReference.getType()); return null; } } } 

六、获取Spring上下文工具-ApplicationContextHelper开发

创建一个获取上下文的类:

package com.webcode.springboot.common;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; /** * @ClassName ApplicationContextHelper * @Description TODO * @Author wushaopei * @Date 2019/10/11 23:19 * @Version 1.0 */ //该注解将当前类交给Spring进行管理 @Component("applicationContextHelper") public class ApplicationContextHelper implements ApplicationContextAware{ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { applicationContext = applicationContext; } public static <T> T popBean(Class<T> clazz){ //如果applicationContext为空,则返回一个空值 if(applicationContext == null){ return null; } //否则,就返回当前applicationContext的Bean映射的类 return applicationContext.getBean(clazz); } public static <T> T popBean(String name,Class<T> clazz){ //如果applicationContext为空,则返回一个空值 if(applicationContext == null){ return null; } //否则,就返回name和当前applicationContext的Bean映射的类 return applicationContext.getBean(name,clazz); } } 

配置对应的Bean:

    <bean class="com.webcode.springboot.common.ApplicationContextHelper" lazy-init="false"/>

测试:通过DB进行验证操作:

    @ResponseBody
    @RequestMapping("/validate3.json")
    public JsonData valitade3(TestVo vo){ log.info("validate"); SysAclModuleMapper moduleMapper = ApplicationContextHelper.popBean(SysAclModuleMapper.class); SysAclModule module = moduleMapper.selectByPrimaryKey(1); BeanValidator.check(vo); return JsonData.success("test validate3"); }

            ​\

七、 Http请求前后监听工具-HttpInterceptor开发

创建HttpInterceptor.java类,继承HandlerInterceptorAdapter类,对Http请求前后进行监听

@Slf4j
public class HttpInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); log.info("request start. url:{}, params:{}",url, JsonMapper.obj2String(parameterMap)); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); log.info("request finished. url:{}, params:{}",url,JsonMapper.obj2String(parameterMap)); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { String url = request.getRequestURI(); Map parameterMap = request.getParameterMap(); log.info("request completed. url:{}, params:{}",url,JsonMapper.obj2String(parameterMap)); } }

配置Bean被Spring进行管理:

   <mvc:interceptors>
        <bean class="com.webcode.springboot.common.HttpInterceptor"/>
    </mvc:interceptors>

测试:

   @ResponseBody
    @RequestMapping("/validate3.json")
    public JsonData valitade3(TestVo vo){ log.info("validate"); SysAclModuleMapper moduleMapper = ApplicationContextHelper.popBean(SysAclModuleMapper.class); SysAclModule module = moduleMapper.selectByPrimaryKey(1); log.info(JsonMapper.obj2String(module)); BeanValidator.check(vo); return JsonData.success("test validate3"); }

任何请求在被进行处理前,会先被preHandle方法进行处理,如果该方法处理通过,就会执行postHandle方法,任何请求执行结束后都会被afterCompletion方法进行处理

记录请求开始到结束所花费的时间

  private static final String START_TIME = "requestStartTime";
    @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); log.info("request start. url:{}, params:{}",url, JsonMapper.obj2String(parameterMap)); long start = System.currentTimeMillis(); request.setAttribute(START_TIME, start); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { String url = request.getRequestURI().toString(); Map parameterMap = request.getParameterMap(); long start = (Long) request.getAttribute(START_TIME); long end = System.currentTimeMillis(); log.info("request finished. url:{}, cost:{}",url,end - start); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { String url = request.getRequestURI().toString(); long start = (Long) request.getAttribute(START_TIME); long end = System.currentTimeMillis(); log.info("request completed. url:{}, cost:{}",url,end - start); }

监听器除了可以进行登录时间的监控外,还可进行用户的cookie、session、登录是否过期等进行监听。

猜你喜欢

转载自www.cnblogs.com/wushaopei/p/11681423.html