權限管理--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

 

 

 

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