权限管理--03(项目搭建)

目录

1.引入相关的pom依赖

2.编写基本的类

3.全局异常定义与处理

4.校验工具类编写

5.JSON转换工具开发

6.获取Spring上下文的工具:applicationContext

7.Http请求前后的监听工具


1.引入相关的pom依赖

    搭建一个工程需要引入相关的依赖

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wx</groupId>
    <artifactId>permission</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>permission</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--热部署依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!--SpringBoot开启AOP功能-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>
        <!--guava -->

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.1-jre</version>
        </dependency>

        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.26</version>
        </dependency>
        <!--连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--通用Mapper的依赖-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        <!--jackson-datatype-guava -->
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-guava</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!--swagger-->

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!--校验相关类-->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.0.Final</version>
        </dependency>
        <!--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.13</version>
        </dependency>

        <!--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>



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  包括整合MyBatis,通用Mapper,数据的返回格式JsonData,编写BaseDTO等等。

 JsonData:

package com.wx.permission.infra.common;

import lombok.Getter;
import lombok.Setter;


/**
 * User: Mr.Wang
 * Date: 2019/12/14
 */
@Getter
@Setter
public class JsonData {
    private Boolean ret;
    private String msg;
    private Object data;

    public JsonData(Boolean ret) {
        this.ret = ret;
    }

    public static JsonData success(String msg, Object data) {
        JsonData jsonData = new JsonData(true);
        jsonData.msg = msg;
        jsonData.data = data;
        return jsonData;
    }

    public static JsonData success(Object data) {
        JsonData jsonData = new JsonData(true);
        jsonData.data = data;
        return jsonData;
    }

    public static JsonData success() {
        return new JsonData(true);
    }

    public static JsonData fail(String msg) {
        JsonData jsonData = new JsonData(true);
        return jsonData;
    }
}

2.编写基本的类

package com.wx.permission.infra.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.units.qual.A;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * User: Mr.Wang
 * Date: 2019/12/14
 */
@Table(name = "sys_acl")
@Accessors(chain = true)
@Setter
@Getter
public class AclDTO {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ApiModelProperty("权限码")
    private String code;
    private String name;
    private Long aclModuleId;
    @ApiModelProperty("请求的url,可以填正则表达式")
    private String url;
    @ApiModelProperty("类型。1 菜单 2按钮 3其他")
    private Short type;
    @ApiModelProperty("该权限是否可以用 1可用,0不可用")
    private Boolean status;
    private String remark;
}

 这里需要注意的时已攻入了lombok的包,所以可以省略get set方法,创建对象的时候还可以进行链式调用,然后是主键的一个生成的策略,这个注解是必须要打上的不然项目启动会报错,

@GeneratedValue注解有两个属性,分别是strategy和generator:

    generator属性的值是一个字符串,默认为"",其声明了主键生成器的名称。

    strategy属性:提供四种值:

    

默认SpringBoot的@GeneratedValue 是不需要加参数的,但是如果数据库控制主键自增(auto_increment), 不加参数就会报错

 

3.全局异常定义与处理

   这里有三种种当时处理全局的异常, HandlerExceptionResolver,@Controlleradvice @ExceptionHandler

  • @ExceptionHandler

    注解只能作用为对象的方法上,并且在运行时有效,value() 可以指定异常类。由该注解注释的方法可以具有灵活的输入参  数。异常参数可以包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。

  用法:

  

  •   HandlerExceptionResolver 接口

  HandlerExceptionResolve 虽然能够处理全局异常,但是 Spring 官方不推荐使用它。

  用法:这里他可以拿到请求参数的信息,可以去做一些判断

  

  • @Controlleradvice 注解

  用法:

package com.wx.permission.infra.exception;

/**
 * User: Mr.Wang
 * Date: 2019/12/14
 */
public class CommonException extends RuntimeException {
//    private Long id;
    public CommonException() {
        super();
    }

    public CommonException(String message) {
        super(message);
    }

    public CommonException(String message, Throwable cause) {
        super(message, cause);
    }

    public CommonException(Throwable cause) {
        super(cause);
    }

    protected CommonException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
package com.wx.permission.infra.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;
import java.util.Map;

/**
 * User: Mr.Wang
 * Date: 2019/12/14
 */

/**
 * 全局自定义异常处理
 */
@ControllerAdvice
public class ControllerExceptionHandler {
    //现在我要我自定义异常返回的信息是一个Map
    @ExceptionHandler(CommonException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Map<String, Object> handUserNotExistException(CommonException ex) {
        Map<String, Object> map = new HashMap<>();
//        map.put("id", ex.getId());
        map.put("message", ex.getMessage());
        return map;
    }
}

  如果说不用@ControllerAdvice直接抛出异常,那么返回:

  

 适用他的好处就是可以去封装特定的返回信息:

 

4.校验工具类编写

 校验工具类主要是对validator的封装,他提供了哪些默认的校验,以及如何自定义校验,如何分组校验在文章SpringMVC--01(SpringMVC的数据校验)里面,只是这里呢不在使用@Valida来校验,而是使用自己的封装的类来校验并返回指定的异常。

package com.wx.permission.api.validator;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.wx.permission.infra.exception.CommonException;
import org.apache.commons.collections.MapUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.*;

/**
 * User: Mr.Wang
 * Date: 2019/12/14
 * <p>
 * 这个类可以拿到按照自己喜欢的参数格式来封装校验结果
 * 所有的校验结果,BindingResult都可以拿到
 */
public class BeanValidator {
    private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    /**
     * 检验一个Bean
     *
     * @param t
     * @param groups
     * @param <T>
     * @return
     */
    public static <T> Map<String, String> validate(T t, Class... groups) {
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> validateResult = validator.validate(t, groups);
        if (validateResult.isEmpty()) {
            return Collections.emptyMap();
        } else {
            LinkedHashMap error = Maps.newLinkedHashMap();
            Iterator iterator = validateResult.iterator();
            while (iterator.hasNext()) {
                ConstraintViolation constraintViolation = (ConstraintViolation) iterator.next();
                error.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage());
            }
            return error;
        }
    }

    /**
     * 校验集合  ???? 校验逻辑
     *
     * @param collection
     * @return
     */
    public static Map<String, String> validateList(Collection<?> collection) {
        //Preconditions和断言的思想一致
        Preconditions.checkNotNull(collection);
        Iterator<?> iterator = collection.iterator();
        Map erros;
        do {
            //如果这个List的第一个元素没有错 第二个元素有错能检测到吗?
            if (!iterator.hasNext()) {
                return Collections.emptyMap();
            } else {
                //new Class[0]表示有零个元素的Class数组,即空数组,
                // 与传入null结果是一样的,
                // 都表示取得无参构造方法。但是循环的时候他不会抛错。
                erros = validate(iterator.next(), new Class[0]);
            }
        } while (erros.isEmpty());
        return erros;
    }

    /**
     * 可以传多个参数的校验
     *
     * @param first
     * @param objects
     * @return
     */
    public static Map<String, String> validatorObject(Object first, Object... objects) {
        if (objects != null && objects.length >= 0) {
            return validateList(Arrays.asList(first, objects));
        } else {
            return validate(first, new Class[0]);
        }
    }

    /**
     * 校验不过抛出异常
     * @param parms
     * @throws CommonException
     */
    public static void check(Object parms) throws CommonException {
        Map<String, String> validatorRet = validatorObject(parms);
        if (MapUtils.isNotEmpty(validatorRet)) {
            throw new CommonException(validatorRet.toString());
        }
    }
}

  new Class[0]就是传入一个空数组,如果直接传nul进去历遍会报错。

 使用就非常简单:

 

 这是一个公共的校验方法,如果对象需要校验特俗的规则那么可以如下:

public class AppInstanceValidator {
    //appServiceInstance name
    private static final String NAME_PATTERN = "[a-z]([-a-z0-9]*[a-z0-9])?";

    private AppInstanceValidator() {
    }


    public static void checkName(String name) {
        if (!Pattern.matches(NAME_PATTERN, name)) {
            throw new CommonException("error.app.instance.name.notMatch");
        }
    }
}

 如果这个特俗的规则在个对象的字段上用到,可以写成注解,使用上面的通用对象校验的类依然可以校验。

5.JSON转换工具开发

主要是对jaskon的一个封装:

package com.wx.permission.infra.utils;

/**
 * User: Mr.Wang
 * Date: 2019/12/15
 */

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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 封装Jackson 把一个类转换成json对象,把一个json转换成类对象
 */
public class JsonMapper {
    private static final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //初始化objectMapper的配置,处理空字段
        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);
    }

    /**
     * 对象转换为json
     *
     * @param src
     * @param <T>
     * @return
     */
    public static <T> String object2String(T src) {
        if (src == null) {
            logger.warn("parse object is null");
            return null;
        }
        try {
            return src instanceof String ? (String) src : objectMapper.writeValueAsString(src);
        } catch (Exception e) {
            logger.warn("parse object to String exception,error:{}", e);
            return null;
        }
    }

    /**
     * json转换为对象
     *
     * @param src
     * @param tTypeReference
     * @param <T>
     * @return
     */
    public static <T> T string2Object(String src, TypeReference<T> tTypeReference) {
        if (src == null || tTypeReference == null) {
            return null;
        }
        try {
            return (T) (tTypeReference.getType().equals(String.class) ? src : objectMapper.readValue(src, tTypeReference));
        } catch (Exception e) {
            logger.warn("parse String to object exception,String:{}, TypeReference<T>:{},error:{} ", src, tTypeReference, e);
            return null;
        }
    }
}

6.获取Spring上下文的工具:applicationContext

package com.wx.permission.infra.common;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * User: Mr.Wang
 * Date: 2019/12/15
 */
@Component("applicationContextHelper")
public class ApplicationContextHelper implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }

    /**
     * 根据Class返回容器中的Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T popBean(Class<T> clazz) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(clazz);
    }

    /**
     * 根据name和Class返回Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T popBean(String name, Class<T> clazz) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(name, clazz);
    }

//    @Override
//    public int getOrder() {
//        return Ordered.HIGHEST_PRECEDENCE;
//    }
}

7.Http请求前后的监听工具

    主要有什么作用呢?可以用来输出请求的参数信息,敏感信息需要过滤,可以用来记录调用接口的时间

过滤器只能获得原始的http请求和响应,而无法获得具体调用的哪个方法,要想获得就要使用过滤器,需要注意的事自己处理了的异常在最后的afterCompletion拿不到。

package com.wx.permission.infra.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * User: Mr.Wang
 * Date: 2019/12/15
 */
@Component
public class HttpInterceptor extends HandlerInterceptorAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}

 他每个方法的含义和使用在:https://blog.csdn.net/weixin_37650458/article/details/100637670

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章