spring-boot 學習

spring-boot 的學習

spring-boot出來很長一段時間了,一直也沒有時間去學習一下暇屋,正好這段時間項目沒有那么忙了,學習記錄一下洞辣。

由于東西感覺有些多咐刨,所以就分成幾個分支分別記錄了。
整個學習過程以spring-boot-starter-thymeleaf為基礎扬霜,在這個基礎上再按照需要添加其它的組件.

github:https://github.com/liangyt/springbootbase

learn.01

這個分支是比較基礎的一些配置集成定鸟。

一. mybatis-spring-boot-starter 和 druid

引入相關的依賴包

<!--mybatis mysql-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis.springboot.version}</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--datasource-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>

spring-boot 的默認配置文件 application.properties 配件mysql 和 druid 相關的數(shù)據(jù)

# 數(shù)據(jù)庫驅動配置信息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost/test?useUnicode=true&characterEncode=utf-8
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# druid連接池配置信息
# 初始化的大小、最小著瓶、最大
spring.druid.initial-size=5
spring.druid.min-idle=5
spring.druid.max-active=20
# 獲取連接等待超時時間
spring.druid.max-wait=60000
# 間隔多久才進行一次檢測联予,檢測需要關閉的空閑連接,單位是毫秒
spring.druid.time-between-eviction-run-millis=60000
# 一個連接在池中最小生存的時間材原,單位是毫秒
spring.druid.min-evictable-idle-time-millis=30000
spring.druid.validation-query=select 1 from dual
spring.druid.test-while-idle=true
spring.druid.test-on-borrow=false
spring.druid.test-on-return=false
spring.druid.pool-prepared-statement-per-connection-size=20
# 監(jiān)控統(tǒng)計攔截的filters沸久,去掉后監(jiān)控界面sql無法統(tǒng)計,'wall'用于防火墻
spring.druid.filters=stat,wall,log4j
# 通過connectProperties屬性來打開mergeSql功能余蟹;慢SQL記錄
spring.druid.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

要使用druid還需要做一些java配置的工作
具體看這個類:

com.liangyt.config.db.DruidSource

里面有兩個事情處理:
重新處理dataSource和事務
還有另一個類也要關注一下:

com.liangyt.config.db.DruidConfig

這個類是針對druid本身servlet的處理卷胯,感覺如果不訪問druid的客戶界面的話不需要處理.

mybatis的配置:
這個配置比較簡單了,在application.properties文件中只有兩行配置代碼

# mybatis
mybatis.type-aliases-package=com.liangyt.entity
mybatis.mapper-locations=classpath:mybatis/**/*.xml,classpath:mybatis/*.xml

告訴mybatis需要處理實體的路徑和需要掃描的mapper文件位置.
同樣在spring-boot啟動的時候需要添加注解

@MapperScan(basePackages = "com.liangyt.repository")

啟動mapperScan掃描.

二. mybatis-generator 主要為了方便由數(shù)據(jù)庫表到Entity威酒、mapper和repository的生成.

一個依賴

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>${mybatis.generator.version}</version>
</dependency>

一個插件

<!-- mvn mybatis-generator:generate -->
<plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>${mybatis.generator.version}</version>
    <configuration>
        <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
        <overwrite>true</overwrite>
        <verbose>true</verbose>
    </configuration>
</plugin>

其中mybatis-generator的配置在文件(src/main/resources/generator/generatorConfig.xml)中已經(jīng)有詳細的說明窑睁,直接看就可以了挺峡。

持久層相關的處理基本上就是這些了。

三. thymeleaf-layout-dialect

視圖層使用的是spring-boot推薦的thymeleaf担钮,由于以前習慣了使用sitemesh橱赠,所以這里也使用thymeleaf-layout-dialect配置類似于sitemesh的功能。
由于spring-boot-starter-thymeleaf依賴已經(jīng)包含了spring-layout-dialect箫津,所以就不用重復添加依賴,直接配置就可以了病线。
說thymeleaf-layout-dialect之前先添加一個依賴吧,就是nekohtml。如果沒有添加這個依賴的話鲤嫡,也行解釋運行送挑,但是對標簽的解析很嚴格,稍微寫錯一點則編譯錯誤暖眼,特別是引入前端庫的話惕耕。
引入也比較簡單:

<!--加入這個主要是為了減少thymeleaf的嚴格檢查,方便使用其它的前端庫同時需要設置 spring.thymeleaf.mode=LEGACYHTML5-->
<dependency>
    <groupId>nekohtml</groupId>
    <artifactId>nekohtml</artifactId>
    <version>1.9.6.2</version>
</dependency>

同時在application.properties添加配置

spring.thymeleaf.mode=LEGACYHTML5

回到thymeleaf-layout-dialect上,使用它之前需要先配置一下LayoutDialect:

@Configuration
public class ThymeleafLayout{

    @Bean
    public LayoutDialect layoutDialect() {
        return new LayoutDialect();
    }
}

配置一個Bean LayoutDialect,然后就可以使用了诫肠。
這里簡單的配置了兩個頁面示意一下:
layout.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>首頁</title>
    <link rel="stylesheet" th:href="@{css/element-ui.css}" />
    <script th:src="@{js/vue.js}"></script>
    <script th:src="@{js/element-ui.js}"></script>
    <script th:src="@{js/axios.js}"></script>
</head>
<body>
test
<div layout:fragment="content"></div>
</body>
</html>

關注點主要有兩個:

1.xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
2.<div layout:fragment="content"></div>

這個布局文件一般是留一個位置用于存放動態(tài)變化的內容司澎,也就是<code>layout:fragment="content"</code>這個Div的位置.

再來看看動態(tài)內容的文件:hello.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultrag.net.nz/thymeleaf/layout"
    layout:decorator="layout/layout">
<head>
    <title>Hello</title>
    <link rel="stylesheet" th:href="@{css/hello.css}">
    <script th:src="@{js/hello.js}"></script>
</head>
<body>
<div layout:fragment="content">
    <span th:text="${hello}"></span>
</div>
</body>
</html>

這個文件的內容比較少關注的點有三個:

1.html標簽的內容
2.head標簽的內容
3.layout:fragment="content"標簽的內容

1.html標簽的定義主要說明了這個文件需要使用的是哪一個布局文件。
2.head標簽的內容會追加到布局文件的head標簽的內容后面栋豫,并且title的內容會替換掉布局文件的title的內容.
3.<code>layout:fragment="content"</code>標簽的內容的替換掉布局文件的<code><div layout:fragment="content"></div></code>的內容挤安。

后面訪問的時候,通過控制層直接訪問動態(tài)內容的文件就可以了丧鸯。

四. 訪問編譯thymeleaf

如果是正常的通過controller查詢內容蛤铜,然后設置model,再然后跳轉到頁面的話丛肢,則Controller可以這樣處理:

@Controller
@RequestMapping(value = "/")
public class TestController {

    @RequestMapping(value = "/hello")
    public String hello(Model model) {
        model.addAttribute("hello", "您好");
        return "hello";
    }
}

還有另外一種則是不通過Controller围肥,直接跳轉訪問頁面:
這個需要實現(xiàn)<code>WebMvcConfigurerAdapter</code>類。 覆蓋方法<code>addViewControllers</code>:

/**
 * 定義訪問路徑與視圖之間的關系蜂怎,不經(jīng)過Controller
 * @param registry
 */
@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("index").setViewName("/index");
    super.addViewControllers(registry);
}

如果代碼可以直接訪問 /index 這個路徑穆刻,即訪問 /resource/templates/index.html頁面。如果有其它的頁面直接按類似的方法添加中進去就可以了杠步,也可以使用表達式氢伟。

五.web攔截器

攔截器的實現(xiàn)跟spring mvc 一樣,都需要實現(xiàn) <code>org.springframework.web.servlet.HandlerInterceptor</code>,這里簡單的貼一下代碼出來幽歼,僅供參考:

@Component
public class TestControllerInterceptor implements HandlerInterceptor {

    @Autowired
    private TestService testService;

    /**
     * 進入controller 之前的處理
     * @param request
     * @param response
     * @param handler
     * @return 返回 false 不進入controller 返回 true 進入controller
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(request.getRequestURI());

//        if ("/api/test/all".equals(request.getRequestURI())) return false;
        return true;
    }

    /**
     * 進入controller 完成之后朵锣,但沒有渲染頁面之前處理,一般主要用于修改model的值
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        List<Test> list = testService.selectAll();
        System.out.println(list);
    }

    /**
     * 頁面已渲染完成后的處理
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

主要是配置這個攔截器的地方试躏,由原來的xml配置到java代碼的配置.這個跟配置不通過Controller直接訪問頁面是同一個類猪勇,只是覆蓋實現(xiàn)了另一個方法:

@Autowired
private TestControllerInterceptor testControllerInterceptor;
    
/**
 * 設置攔截器
 * @param registry
 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(testControllerInterceptor).addPathPatterns("/api/test/**");
    super.addInterceptors(registry);
}

有一個需要注意的點是<code>TestControllerInterceptor</code>的實例需要由<code>@Autowired</code>注解生成,而不能由<code>new</code>生成颠蕴,否則攔截器里面使用<code>@Autowired</code>可能得不到實例.

六.hibernate validator

這個依賴也不需要單獨引入泣刹,在spring-boot-starter-web下面已經(jīng)有這個依賴了助析。
要配置這個就比較簡單了,在實體類里面使用注解的方法直接在屬性處定義驗證通過的條件椅您,同時需要在<code>Controller</code>類里面使用注解<code>@Validated</code>說明該實體需要驗證:

@RequestMapping(value = "/saveOrUpdate", method = RequestMethod.POST)
public Object saveOrUpdate(@RequestBody @Validated Test test) {
    if (test.getId() != null) {
        testService.update(test);
    }
    else {
        test.setId((int)(Math.random() * 100));
        testService.insert(test);
    }
    return MessageReturn.success("成功");
}

具體使用方式網(wǎng)上的教程也不少,這里貼出注解:

注解         作用
@Valid  被注釋的元素是一個對象外冀,需要檢查此對象的所有字段值
@Null   被注釋的元素必須為 null
@NotNull    被注釋的元素必須不為 null
@AssertTrue 被注釋的元素必須為 true
@AssertFalse    被注釋的元素必須為 false
@Min(value) 被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@Max(value) 被注釋的元素必須是一個數(shù)字掀泳,其值必須小于等于指定的最大值
@DecimalMin(value)  被注釋的元素必須是一個數(shù)字雪隧,其值必須大于等于指定的最小值
@DecimalMax(value)  被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@Size(max, min) 被注釋的元素的大小必須在指定的范圍內
@Digits (integer, fraction) 被注釋的元素必須是一個數(shù)字员舵,其值必須在可接受的范圍內
@Past   被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Pattern(value) 被注釋的元素必須符合指定的正則表達式

2. Hibernate Validator 附加的 constraint

注解           作用
@Email  被注釋的元素必須是電子郵箱地址
@Length(min=, max=) 被注釋的字符串的大小必須在指定的范圍內
@NotEmpty   被注釋的字符串的必須非空
@Range(min=, max=)  被注釋的元素必須在合適的范圍內
@NotBlank   被注釋的字符串的必須非空
@URL(protocol=, host=,    port=,  regexp=, flags=)  被注釋的字符串必須是一個有效的url
@CreditCardNumber 被注釋的字符串必須通過Luhn校驗算法脑沿, 銀行卡,信用卡等號碼一般都用Luhn 計算合法性
@ScriptAssert(lang=, script=, alias=)   要有Java Scripting API 即JSR 223 ("Scripting for the JavaTM Platform")的實現(xiàn)
@SafeHtml(whitelistType=, additionalTags=)  classpath中要有jsoup包

hibernate補充的注解中马僻,最后3個不常用庄拇,可忽略。
主要區(qū)分下@NotNull  @NotEmpty  @NotBlank 3個注解的區(qū)別:
@NotNull           任何對象的value不能為null
@NotEmpty       集合對象的元素不為0韭邓,即集合不為空措近,也可以用于字符串不為null
@NotBlank        只能用于字符串不為null,并且字符串trim()以后length要大于0

在<code>com.liangyt.common.view.BaseController</code>基礎控制類做了一個針對驗證的全局攔截方法女淑,統(tǒng)一處理返回的異常信息:

/**
     * 統(tǒng)一處理hibernate validator 不通過的數(shù)據(jù)  (BindException)
     *
     * @param ex 異常
     * @return 組裝異常結果
     * {
     *     code: 0,
     *     message: "失敗",
     *     data: {
     *         name: "姓名不能為空",
     *         ...
     *     }
     * }
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validatorException(MethodArgumentNotValidException ex) {

        List<FieldError> errors = ex.getBindingResult().getFieldErrors();

        MessageReturn mr = MessageReturn.fail();
        for (FieldError fe : errors) {
            mr.add(fe.getField(), fe.getDefaultMessage());
        }

        return mr;
    }
  • 第一個分支學習到這里全結束

learn.02

從這里開始是在分支<code>learn.01</code>的基礎上進行的改進瞭郑。

一、logback

spring-boot 默認的日志插件就是logback,在spring-boot-starter下面默認依賴了

logback-classic
logback-core
slf4-api
jcl-over-slf4j
jul-to-slf4j
log4j-over-slf4j

spring-boot 也提供了一些參數(shù)用于設置日志鸭你,但相對于配置文件來說話稍微簡單了一點屈张,其中部分配置如下:

# 日志處理
# 默認情況下,spring boot從控制臺打印出來的日志級別只有ERROR,WARN,INFO;如果希望放開DEBUG級別的話設置 debug=true;
debug=true
# 日志格式
logging.pattern.console=%-4relative [%thread] %-5level %logger{35} - %msg %n
logging.pattern.file=%-4relative [%thread] %-5level %logger{35} - %msg %n
# 針對不同的類或者包設置日志級別;root為父級別
logging.level.root=DEBUG
logging.level.com.liangyt=DEBUG
#logging.level.org.springframework.web=DEBUG
# 日志輸出文件
logging.path=logs
logging.file=log.log

如果要求不是特別高的話苇本,這個配置也基本夠用了袜茧。當然這里也提供了一個引入日志配置文件的參數(shù),不過我沒有試過

logging.config=logconfig.xml

除了使用application.properties配置以外瓣窄,那就是直接配置logback.xml文件了。
在logback.xml配置文件里面我做了詳細的說明纳鼎,這里就不再重復說了俺夕,看文件就知道每個標簽是什么含義了。
我試了一下把日志保存到mongodb里面贱鄙,感覺還不錯劝贸,配置也比較簡單。
添加依賴:

<!--mongodb-->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.4.2</version>
</dependency>

一個類和一部分日志配置:
配置mongodb的連接配置逗宁,以及保存日志到數(shù)據(jù)庫的一個類映九,使用class屬性引入:

<!--日志保存到Mongondb-->
<appender name="MONGODB" class="com.liangyt.config.db.LogMongoDBAppender">
    <DbHost>localhost</DbHost>
    <DbPort>27017</DbPort>
    <DbName>exapp</DbName>
    <DbCollectionName>logging</DbCollectionName>
</appender>

<!--再配置一個logger-->

<logger name="com.liangyt" level="DEBUG">
    <appender-ref ref="MONGODB" />
</logger>

這樣的話<code>com.liangyt</code>生成的日志就會進到這個類<code>com.liangyt.config.db.LogMongoDBAppender</code>,然后覆蓋方法 <code>append</code>保存進數(shù)據(jù)庫.

如果想讓相關的日志信息保存到數(shù)據(jù)庫中,則可以這樣使用:

protected Logger mongodbLogger = LoggerFactory.getLogger("MONGODB");
mongodbLogger.info("保存到數(shù)據(jù)庫中");
二瞎颗、添加AOP

因為<code>spring-boot-starter-thymeleaf</code>下已經(jīng)有了 <code>spring-aop</code>,只是缺少了<code>org.aspectj</code>相關的兩個包件甥,所以只需要添加中兩個依賴:

<!--aspectj-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>${aspectj.version}</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${aspectj.version}</version>
</dependency>

就可以了捌议。
如果只是想單純的玩玩aop的話,那可以起一個項目引有,引入 <code>spring-boot-starter-aop</code>,里面包含了spring-boot-starter ??spring-aop ??AspectJ Runtime ??AspectJ Weaver ??spring-core瓣颅。

利用Java注解的方式,只有一個類:

com.liangyt.common.view.RestRequestMappingAspectInterceptor

這個類詳細說明了實現(xiàn)的細節(jié)譬正。這里不再重復解說了宫补,看這個類就知道了。

  • 好了曾我,第二個分支的內容就到這里了粉怕,下一個分支想把shiro集成進來,看有沒有時間吧抒巢。

learn.03

這個分支沒有寫shiro,不過寫了一些為集成shiro做準備的工作贫贝,把基本的用戶管理,角色管理虐秦,功能管理平酿,登錄,退出工作處理了悦陋,還實現(xiàn)了簡單的是否登錄攔截跳轉蜈彼。如果不想集成shiro的話,
也可以作為一個小系統(tǒng)工作了俺驶,這里簡單說一下吧幸逆。
UI層面使用的是 element ui,使用的是最簡單的方式集成進來的暮现,直接引用相應的靜態(tài)資源还绘。

<link rel="stylesheet" href="../../static/css/element-ui.css" th:href="@{/css/element-ui.css}" />
<link rel="stylesheet" href="../../static/css/style.css" th:href="@{/css/style.css}">
<script src="../../static/js/jquery.3.0.min.js" th:src="@{/js/jquery.3.0.min.js}"></script>
<script src="../../static/js/vue.js" th:src="@{/js/vue.js}"></script>
<script src="../../static/js/element-ui.js" th:src="@{/js/element-ui.js}"></script>
<script src="../../static/js/axios.js" th:src="@{/js/axios.js}"></script>

以上這些就是所有的全局外部資源了。
關于 element ui 的使用方法栖袋,需要的同學直接看它的官網(wǎng)文檔就可以了拍顷。
接著看一下數(shù)據(jù)結構,總共5個表:

用戶表:

1   id  varchar 32  0   0       主鍵  0           0
0   username    varchar 20  0   0       員工編號            0
0   password    varchar 50  0   0       密碼          0
0   name    varchar 50  0   0       員工名稱            0
0   status  int 1   0   0   0   用戶狀態(tài) 0 正常   0   0   0

角色表:
1   id  varchar 32  0   0           0           0
0   rolename    varchar 100 0   0       角色名         0
0   status  int 1   0   0   0   角色狀態(tài)    0   0   0
0   description varchar 200 0   1       角色描述            0

功能表:
1   id  varchar 32  0   0       主鍵  0           0
0   permission_name varchar 100 0   0       功能名稱            0
0   permission_code varchar 100 0   0       功能代碼            0
0   status  int 1   0   0   0   功能狀態(tài)    0   0   0
0   url varchar 200 0   1                   0
0   pid varchar 32  0   0       父ID         0

用戶跟角色關系表:
1   user_id varchar 32  0   0       用戶主鍵    0           0
2   role_id varchar 32  0   0       角色主鍵    0           0

角色跟功能關系表:
1   permission_id   varchar 32  0   0       功能主鍵    0           0
2   role_id varchar 32  0   0       角色主鍵    0           0

好了塘幅,這就是所有的表了昔案,可以直接使用 mybatis-generator 生成 mapper entity reposity 到對應的包中(這里的代碼示例已經(jīng)生成,就不需要重新生成了)电媳。

├── entity
│   ├── system
│   │   ├── Permission.java
│   │   ├── PermissionRole.java
│   │   ├── Role.java
│   │   ├── User.java
│   │   └── UserRole.java
├── repository
│   ├── system
│   │   ├── PermissionMapper.java
│   │   ├── PermissionRoleMapper.java
│   │   ├── RoleMapper.java
│   │   └── UserMapper.java
├── rest
│   ├── system
│   │   ├── LoginController.java
│   │   ├── PermissionController.java
│   │   ├── RoleController.java
│   │   └── UserController.java
└── service
    ├── system
    │   ├── LoginService.java
    │   ├── PermissionService.java
    │   ├── RoleService.java
    │   └── UserService.java

這個是它們的代碼結構踏揣,后續(xù)如果有其它的業(yè)務代碼的話,直接按照這個結構添加就可以了匾乓。具體的代碼寫法也比較簡單捞稿,就不一一展示了,直接看就行。

└── templates
    ├── layout
    │   ├── adminlayout.html
    ├── login.html
    └── system
        ├── demo.html
        ├── index.html
        ├── permission.html
        ├── role.html
        └── user.html

這個是視圖層代碼結構娱局,也比較簡單彰亥。一個布局頁面,其它的是業(yè)務頁面铃辖。
[圖片上傳失敗...(image-185c2b-1511490320108)]
[圖片上傳失敗...(image-db7f4e-1511490320108)]
[圖片上傳失敗...(image-570b9-1511490320108)]
[圖片上傳失敗...(image-c2fa36-1511490320108)]

在類 <code>com.liangyt.config.view.WebMvcViewController</code>設置了過濾:

/**
 * 設置攔截器
 * @param registry
 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(testControllerInterceptor).addPathPatterns("/api/**");
    // 登錄頁和登錄接口不攔截
    registry.addInterceptor(testControllerInterceptor).excludePathPatterns("/login").excludePathPatterns("/api/login");
    super.addInterceptors(registry);
}

在攔截器類 <code>com.liangyt.common.view.TestControllerInterceptor</code>處理攔截:

/**
 * 進入controller 之前的處理
 * @param request
 * @param response
 * @param handler
 * @return 返回 false 不進入controller 返回 true 進入controller
 * @throws Exception
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    logger.info(request.getRequestURI());
    // 用戶未登錄剩愧,則跳轉登錄頁先進行登錄
    if (request.getSession().getAttribute("loginuser") == null) {
        response.sendRedirect("/login");
        return false;
    }
    return true;
}

好了,第三個分支內容就這么多了娇斩,直接下載安裝依賴仁卷,數(shù)據(jù)庫連接配置好,基本就可以跑起來看一下了犬第。下一個分支锦积,估計就是配置shiro了。

learn.04

隔了這么長的時間歉嗓,由于項目比較忙丰介,所以寫得斷斷續(xù)續(xù)的。
這個分支那就把shiro集成進來了.
還是老規(guī)則鉴分,先添加依賴

<!--shiro-spring  包含 shiro-core 和 shiro-web -->
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>${shiro.version}</version>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-ehcache</artifactId>
   <version>${shiro.version}</version>
</dependency>

依賴不多就兩個哮幢,添加依賴之后那就開始配置本次的shiro。由于代碼基本都添加了注釋志珍,所以跟代碼相關的就不多說了吧橙垢,直接更新看代碼就行。
主要的配置類<code>com.liangyt.config.shiro.ShirlConfig</code>就是這個伦糯,springboot啟動的時候會去配置相關的設置柜某,配置的先后順序可以看日志就知道了,每個方法都添加了執(zhí)行日志敛纲。
這里也啟用了shiro緩存喂击,使用的是比較簡單的ehcache本地緩存.本來是想使用redis緩存的,感覺redis可以作為一個比較大的處理方式淤翔,后面再集成進來吧翰绊。
配置shiroFilter的時候,參數(shù)有一個<code>ShiroService</code>,這個服務是用來讀取跟shiro相關數(shù)據(jù)的類旁壮。
比如啟動過程中就需要配置過濾的權限角色等數(shù)據(jù)辞做,就是通過這個服務讀取的。這樣的話在這個服務中引用這個配置類<code>ShirlConfig</code>中某些Bean的時候就需要注意一下寡具,別出來循環(huán)引用了。
<code>ShiroService</code>還可以處理一些緩存相關的操作稚补,比如更新用戶角色童叠,更新角色限權時,就需要刪除緩存,甚至更新filterShiro的過濾鏈(<code>com.liangyt.common.service.DynamicShiroService</code>類)厦坛。

  • 這種做法有一個問題五垮,只能針對單服務應用有效,集群的時候需要另外考慮方式方法了.

配置了shiro之后杜秸,原來的攔截器可以注釋掉了放仗。使用shiro的驗證就可以了,未登錄用戶直接跳轉登錄頁.

重新寫了一個角色驗證器<code>com.liangyt.config.shiro.filter.AnyRolesAuthorizationFilter</code>撬碟,因為每個用戶可以配置多個角色诞挨,每個功能權限可能被多個角色選用,所以用戶只需要滿足其中的一個角色就可以通過驗證。

這部分有參考網(wǎng)上的一個網(wǎng)友的例子,忘記了出處

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末呢蛤,一起剝皮案震驚了整個濱河市惶傻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌其障,老刑警劉巖银室,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異励翼,居然都是意外死亡蜈敢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門汽抚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抓狭,“玉大人,你說我怎么就攤上這事殊橙》觯” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵膨蛮,是天一觀的道長叠纹。 經(jīng)常有香客問我,道長敞葛,這世上最難降的妖魔是什么誉察? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮惹谐,結果婚禮上持偏,老公的妹妹穿的比我還像新娘。我一直安慰自己氨肌,他們只是感情好鸿秆,可當我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怎囚,像睡著了一般卿叽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天考婴,我揣著相機與錄音贩虾,去河邊找鬼。 笑死沥阱,一個胖子當著我的面吹牛缎罢,可吹牛的內容都是我干的。 我是一名探鬼主播考杉,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼策精,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奔则?” 一聲冷哼從身側響起蛮寂,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎易茬,沒想到半個月后酬蹋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡抽莱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年范抓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片食铐。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡匕垫,死狀恐怖,靈堂內的尸體忽然破棺而出虐呻,到底是詐尸還是另有隱情象泵,我是刑警寧澤,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布斟叼,位于F島的核電站偶惠,受9級特大地震影響,放射性物質發(fā)生泄漏朗涩。R本人自食惡果不足惜忽孽,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谢床。 院中可真熱鬧兄一,春花似錦兴革、人聲如沸捷兰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渡讼。三九已至蹋盆,卻和暖如春费薄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背栖雾。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伟众,地道東北人析藕。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像凳厢,于是被迫代替她去往敵國和親账胧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內容