springboot筆記

1.    簡介:

1.1.  SpringBoot介紹

Spring Boot使開發獨立的,產品級別的基於Spring的應用變得很是簡單,你只需"just run"。 咱們爲Spring平臺及第三方庫提供開箱即用的設置,這樣你就能夠有條不紊地開始。多數Spring Boot應用須要不多的Spring配置。css

你可使用Spring Boot建立Java應用,並使用java -jar啓動它或採用傳統的war部署方式。html

1.1.1.    解決的問題

l  依賴太多了, 且存在版本問題前端

l  配置太多了且每次都同樣, 大部分工程, 配置每次都是同樣的, 從一個地方拷貝到另一個地方. 且Spring發展10多年, 各類配置版本太多, 對於不少程序員來講, 分不清哪一個是有效, 哪一個無效.java

l  部署太麻煩. 須要tomcat部署, 項目結構也須要照着Java EE的目錄結構來寫.mysql

1.1.2.    SpringBoot特色

l  建立獨立的Spring應用程序程序員

l  嵌入的Tomcat,無需部署WAR文件web

l  簡化Maven配置redis

l  自動配置Springspring

l  提供生產就緒型功能,如指標,健康檢查和外部配置sql

l  絕對沒有代碼生成和對XML沒有要求配置

 

1.1.3.    SpringBoot功能

自動配置(auto-configuration)

一項簡化配置的功能,好比在classpath中發現有spring security的jar包,則自動建立相關的bean等

 

starters(簡化依賴)

這個比較關鍵,方便spring去集成各種組件,好比redis、mongodb等等。

 

 

1.1.4.    SpringBoot的發展

 

 

 

1.2.  系統要求

默認狀況下,本堂課使用SpringBoot 2.1.2最新版本,最好安裝JDK8以及以上的版本,maven使用3.3或者以上的版本(本教程使用maven3.6版本)

 

1.3.  第一個SpringBoot項目

新建一個普通maven項目

 

建立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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>enjoy</groupId>

    <artifactId>springbootvip</artifactId>

    <version>1.0-SNAPSHOT</version>

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.1.2.RELEASE</version>

    </parent>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

    </dependencies>

 

</project>

 

編寫代碼:

爲了完成應用程序,咱們須要建立一個單獨的Java文件。Maven默認會編譯src/main/java下的源碼

新建:cn.enjoy.Example

package cn.enjoy;

import org.springframework.boot.*;

import org.springframework.boot.autoconfigure.*;

import org.springframework.stereotype.*;

import org.springframework.web.bind.annotation.*;

@RestController

@EnableAutoConfiguration

public class Example {

    @RequestMapping("/")

    String home() {

        return "Hello World!";

    }

    public static void main(String[] args) throws Exception {

        SpringApplication.run(Example.class, args);

    }

}

@RestController和@RequestMapping說明:

@RestController。這被稱爲一個構造型(stereotype)註解。它爲閱讀代碼的人們提供建議。對於Spring,該類扮演了一個特殊角色。在本示例中,咱們的類是一個web @Controller,因此當處理進來的web請求時,Spring會詢問它。

@RequestMapping註解提供路由信息。它告訴Spring任何來自"/"路徑的HTTP請求都應該被映射到home方法。@RestController註解告訴Spring以字符串的形式渲染結果,並直接返回給調用者。

@EnableAutoConfiguration。這個註解告訴Spring Boot根據添加的jar依賴猜想你想如何配置Spring。因爲spring-boot-starter-web添加了Tomcat和Spring MVC,因此auto-configuration將假定你正在開發一個web應用並相應地對Spring進行設置。

main方法。這只是一個標準的方法,它遵循Java對於一個應用程序入口點的約定。咱們的main方法經過調用run,將業務委託給了Spring Boot的SpringApplication類。SpringApplication將引導咱們的應用,啓動Spring,相應地啓動被自動配置的Tomcat web服務器。咱們須要將Example.class做爲參數傳遞給run方法來告訴SpringApplication誰是主要的Spring組件。

 

執行main方法,使用一個瀏覽器打開 localhost:8080,如下輸出:

Hello World!

 

1.4.  注意事項

Spring Boot不須要使用任何特殊的代碼結構,然而,這裏有一些地方須要注意

使用"default"

當類沒有包含package聲明時,它被認爲處於default package下。一般不推薦使用default package,並應該避免使用它。由於對於使用@ComponentScan,@EntityScan或@SpringBootApplication註解的Spring Boot應用來講,來自每一個jar的類都會被讀取,這會形成必定的問題。

定位main應用類

一般建議你將main應用類放在位於其餘類上面的根包(root package)中。一般使用@EnableAutoConfiguration註解你的main類,而且暗地裏爲某些項定義了一個基礎「search package」。例如,若是你正在編寫一個JPA應用,被@EnableAutoConfiguration註解的類所在包將被用來搜索@Entity項。

使用根包容許你使用@ComponentScan註解而不須要定義一個basePackage屬性。若是main類位於根包中,你也可使用@SpringBootApplication註解。

下面是一個典型的結構:

cn

 +- enjoy

     +- myproject

         +- Application.java

         |

         +- domain

         |   +- Customer.java

         |   +- CustomerRepository.java

         |

         +- service

         |   +- CustomerService.java

         |

         +- web

             +- CustomerController.java

 

 

 

2.   SpringBoot快速入門

能夠繼承spring-boot-starter-parent項目來獲取合適的默認設置。

想配置你的項目繼承spring-boot-starter-parent只須要簡單地設置parent爲:

<parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.1.2.RELEASE</version>

</parent>

注:你應該只須要在該依賴上指定Spring Boot版本。若是導入其餘的starters,你能夠放心的省略版本號。

使用沒有父POMSpring Boot

不是每一個人都喜歡繼承spring-boot-starter-parent POM。你可能須要使用公司標準parent,或你可能傾向於顯式聲明全部Maven配置。

若是你不使用spring-boot-starter-parent,經過使用一個scope=import的依賴,你仍能獲取到依賴管理的好處:

  <dependencyManagement>

        <dependencies>

            <dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-dependencies</artifactId>

                <version>2.1.2.RELEASE</version>

                <type>pom</type>

                <scope>import</scope>

            </dependency>

        </dependencies>

    </dependencyManagement>

 

 

登錄\註冊

 

2.1.  建表

CREATE TABLE `enjoy_user` (

                      `id`  int NOT NULL AUTO_INCREMENT ,

                      `passwd`  varchar(255) NULL ,

                      `username`  varchar(255) NULL ,

                      PRIMARY KEY (`id`)

);

2.2.  搭建springboot環境

   <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.1.2.RELEASE</version>

    </parent>

          <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <maven.compiler.source>1.8</maven.compiler.source>

        <maven.compiler.target>1.8</maven.compiler.target>

    </properties>

        <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

    </dependencies>

       

新建App.java

        @SpringBootApplication

public class App {

    public static void main(String[] args) throws Exception {

            SpringApplication.run(App.class, args);

    }

}

       

2.3.  新建Controller

package cn.enjoy.controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class UserController {

 

    @RequestMapping("/hello")

    public Object sayHello() {

        return "hello";

    }

}

運行App,在瀏覽器輸入:localhost:8080/hello,發現「hello」說明第一步部署成功。

 

2.4.  集成mybatis

   <dependency>

    <groupId>org.mybatis.spring.boot</groupId>

    <artifactId>mybatis-spring-boot-starter</artifactId>

    <version>1.2.0</version>

</dependency>

 

<dependency>

         <groupId>mysql</groupId>

         <artifactId>mysql-connector-java</artifactId>

  </dependency>

 

2.5.  生成mapper

在resources目錄,新建application.properties文件,增長內容以下

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring?serverTimezone=GMT%2B8

spring.datasource.username=root

spring.datasource.password=root1234%

 

mybatis.mapperLocations=classpath:mapping/*.xml

 

準備mybatis的生成文件generatorConfig.xml,並在相應目錄建立好model,dao,mapping文件夾

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE generatorConfiguration

        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <!-- 數據庫驅動:選擇你的本地硬盤上面的數據庫驅動包-->

    <classPathEntry  location="C:\Users\VULCAN\.m2\repository\mysql\mysql-connector-java\5.1.37\mysql-connector-java-5.1.37.jar"/>

    <context id="DB2Tables"  targetRuntime="MyBatis3">

        <commentGenerator>

            <property name="suppressDate" value="true"/>

            <!-- 是否去除自動生成的註釋 true:是 : false:否 -->

            <property name="suppressAllComments" value="true"/>

        </commentGenerator>

        <!--數據庫連接URL,用戶名、密碼 -->

        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/spring" userId="root" password="root1234%">

        </jdbcConnection>

        <javaTypeResolver>

            <property name="forceBigDecimals" value="false"/>

        </javaTypeResolver>

        <!-- 生成模型的包名和位置-->

        <javaModelGenerator targetPackage="cn.enjoy.model" targetProject="src/main/java">

            <property name="enableSubPackages" value="true"/>

            <property name="trimStrings" value="true"/>

        </javaModelGenerator>

        <!-- 生成映射文件的包名和位置-->

        <sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">

            <property name="enableSubPackages" value="true"/>

        </sqlMapGenerator>

        <!-- 生成DAO的包名和位置-->

        <javaClientGenerator type="XMLMAPPER" targetPackage="cn.enjoy.dao" targetProject="src/main/java">

            <property name="enableSubPackages" value="true"/>

        </javaClientGenerator>

        <!-- 要生成的表 tableName是數據庫中的表名或視圖名 domainObjectName是實體類名-->

        <table tableName="enjoy_user" domainObjectName="Users" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>

    </context>

</generatorConfiguration>

 

右鍵生成:結構圖以下

 

注意:得再App啓動類上增長@MapperScan掃描註解

@SpringBootApplication

@MapperScan("cn.enjoy.dao")

public class App {

    public static void main(String[] args) throws Exception {

        SpringApplication.run(App.class, args);

    }

}

 

2.6.  新增mapper登錄方法

Users findByUsernameAndPasswd(@Param("username") String username, @Param("passwd") String passwd);

 

對應的XML配置

<select id="findByUsernameAndPasswd" resultType="cn.enjoy.model.Users" parameterType="map">

    select

    <include refid="Base_Column_List" />

    from enjoy_user where 1=1

    <if test="passwd != null" >

      and passwd = #{passwd,jdbcType=VARCHAR}

    </if>

    <if test="username != null" >

      and username = #{username,jdbcType=VARCHAR}

</if>

limit 1

  </select>

 

2.7.  SpringBoot單元測試

  要測試剛纔新增的Mapper方法是否成功,這裏須要單元測試,在springboot中是有專門的組件來作單元測試的,在pom文件中新增依賴

 

<dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

        </dependency>

新建UserTest放置在test目錄下

package cn.enjoy.test;

import cn.enjoy.App;

 

import cn.enjoy.dao.UsersMapper;

import cn.enjoy.model.Users;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;

 

import javax.annotation.Resource;

 

 

@SpringBootTest(classes = {App.class})

@RunWith(SpringRunner.class)

public class UserTest {

 

    @Resource

    private UsersMapper usersMapper;

 

    @Test

    public void testAdd() {

        Users user = new Users() ;

        user.setPasswd("123");

        user.setUsername("enjoy");

        usersMapper.insertSelective(user);

    }

 

    @Test

    public void testFindUser() {

        Users enjoy = usersMapper.findByUsernameAndPasswd("enjoy", "123");

        System.out.println(enjoy);

    }

 

}

 

這樣SpringBoot集成單元測試成功!

2.8.  新建service

新增接口IUserService

public interface IUserService {

     boolean login(String username,String passwd);

     boolean register(String username,String passwd);

}

建立實現類

package cn.enjoy.service.impl;

import cn.enjoy.dao.UsersMapper;

import cn.enjoy.model.Users;

import cn.enjoy.service.IUserService;

import javax.annotation.Resource;

@Service

public class UserServiceImpl implements IUserService {

 

    @Resource

    private UsersMapper usersMapper;

 

    @Override

    public boolean login(String username, String passwd) {

        Users users = usersMapper.findByUsernameAndPasswd(username, passwd);

        return users != null;

    }

 

    @Override

    public boolean register(String username, String passwd) {

        Users users = new Users();

        users.setUsername(username);

        users.setPasswd(passwd);

        int cnt = usersMapper.insertSelective(users);

        return cnt > 0;

    }

}

 

 

2.9.  修改controller

修改UserController,增長login和register方法

package cn.enjoy.controller;

 

import cn.enjoy.service.IUserService;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

import javax.annotation.Resource;

 

@RestController

public class UserController {

 

    @Resource

    private IUserService iUserService;

 

 

    @RequestMapping("/hello")

    public Object sayHello() {

        return "hello";

    }

 

    @RequestMapping("/login")

    public String login(String username,String passwd) {

        boolean login = iUserService.login(username, passwd);

        if(login) {

            return "登錄成功";

        }else {

            return  "登錄失敗";

        }

    }

 

    @RequestMapping("/register")

    public String register(String username,String passwd) {

        boolean login = iUserService.register(username, passwd);

        if(login) {

            return "註冊成功";

        }else {

            return  "註冊失敗";

        }

    }

}

 

 

在瀏覽器上輸入:localhost:8080/register?username=deer&passwd=123,顯示「註冊成功」

在瀏覽器上輸入:localhost:8080/login?username=deer&passwd=123,顯示「登錄成功」

 

2.10.    事務支持

修改IUserService接口,增長一個新增batchAdd方法,在UserServiceImpl增長相應實現類,在實現類中故意產生一個被0整除得異常

package cn.enjoy.service;

public interface IUserService {

     boolean login(String username,String passwd);

 

     boolean register(String username,String passwd);

 

     void batchAdd(String username,String passwd);

}

                 

package cn.enjoy.service.impl;

import cn.enjoy.dao.UsersMapper;

import cn.enjoy.model.Users;

import cn.enjoy.service.IUserService;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

 

@Service

public class UserServiceImpl implements IUserService {

 

    @Resource

    private UsersMapper usersMapper;

 

    @Override

    public boolean login(String username, String passwd) {

        Users users = usersMapper.findByUsernameAndPasswd(username, passwd);

        return users != null;

    }

 

    @Override

    public boolean register(String username, String passwd) {

        Users users = new Users();

        users.setUsername(username);

        users.setPasswd(passwd);

        int cnt = usersMapper.insertSelective(users);

        return cnt > 0;

    }

    @Override

    public void batchAdd(String username, String passwd) {

        Users users = new Users();

        users.setUsername(username);

        users.setPasswd(passwd);

        usersMapper.insertSelective(users);

         int i = 10 /0;

         users = new Users();

        users.setUsername(username+"2");

        users.setPasswd(passwd);

        usersMapper.insertSelective(users);

    }

}

 

修改UserContoller,增長batchAdd方法

@RequestMapping("/batchAdd")

    public String batchAdd(String username,String passwd) {

        iUserService.batchAdd(username, passwd);

      return "成功";

    }

 

從新運行,在瀏覽器上輸入:localhost:8080/batchAdd?username=enjoy&passwd=123

 

能夠發如今瀏覽器上出現

 

 

檢查數據庫,發現表裏面已經產生了一個錯誤的數據,產生了事務問題。

 

事務支持:

在batchAdd方法上增長@Transactional註解,重啓服務後,在瀏覽器上輸入

localhost:8080/batchAdd?username=enjoy&passwd=123

 

瀏覽器還繼續報錯,但檢查數據庫,事務問題已經獲得瞭解決

2.11.    全局異常處理

經過上面步驟,雖然已經解決了事務問題,但界面上出現這500錯誤,這對用戶來講仍是不友好。

 

通常在企業裏面對這些異常通常都會統一捕獲,由一個專門的異常處理類來統一處理。

2.11.1.            異常捕獲

 

package cn.enjoy.utils;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**

 * 異常處理類

 */

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(value = RuntimeException.class)

    @ResponseBody

    public Object defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {

        e.printStackTrace();

        return "我是個異常處理類";

    }

}

 

重啓服務後,在瀏覽器上輸入會出現異常的服務

localhost:8080/batchAdd?username=enjoy&passwd=123

 

界面返回:

 

 

2.11.2.            404頁面處理

在瀏覽器上故意輸錯地址

localhost:8080/batchAddx?username=enjoy&passwd=123,後端並無這服務,雖然已經作了相關的異常捕獲,但瀏覽器仍是顯示了。

 

這個時候就要作404(其餘異常代碼同樣)

 

在配置這樣錯誤頁面的時候,之前是在WEB.XML中進行配置,而在這裏,須要有個WebServerFactoryCustomizer的實例進行配置

 

在前面創建的GlobalExceptionHandler,新建一個方法

@Bean

    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){

        return (factory->{

            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.do");

            factory.addErrorPages( error404Page);

        });

    }

 

新建BaseController

package cn.enjoy.controller;

 

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class BaseController {

 

    @RequestMapping("/404.do")

    public Object error_404() {

        return "你要找的頁面,被lison偷吃了!";

    }

}

 

 

重啓服務,在瀏覽器上輸入

localhost:8080/batchAddx?username=enjoy&passwd=123

此時,頁面返回「你要找的頁面,被lison偷吃了!」

 

注意:WebServerFactoryCustomizer這種配置方式是在SpringBoot2以後才這樣配置的,在1.X的版本須要用到的是EmbeddedServletContainerCustomizer

代碼以下

   @Bean

   public EmbeddedServletContainerCustomizer containerCustomizer() {

       return (container -> {

           ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.do");

           container.addErrorPages( error404Page);

        });

   }

 

2.12.    靜態資源訪問

靜態資源:js, css, html, 圖片,音視頻等

靜態資源路徑:是指系統能夠直接訪問的路徑,且路徑下的全部文件都可被用戶直接讀取。

Spring Boot默認提供靜態資源目錄位置需置於classpath下,目錄名需符合以下規則:

/static

/public

/resources

/META-INF/resources

 

在resources目錄下面創建static文件夾,在文件夾裏面任意放張圖片。

命名爲:enjoy.jpg

 

 

在地址欄上輸入localhost:8080/enjoy.jpg,能夠看到圖片

 

2.13.    前端界面

2.13.1.            JSP集成

 通常來講springboot不建議直接使用jsp頁面,但不排除有些公司的項目依然使用jsp作前端界面。

 

springboot內置的tomcat並無集成對jsp的支持,也沒有對EL表達式的支持,所以要使用jsp應該先把相關的依賴集成進來

 

在pom文件裏面新增

      <!--JavaServer Pages Standard Tag Library,JSP標準標籤庫-->

        <dependency>

            <groupId>javax.servlet</groupId>

            <artifactId>jstl</artifactId>

        </dependency>

 

        <!--內置tocat對Jsp支持的依賴,用於編譯Jsp-->

        <dependency>

            <groupId>org.apache.tomcat.embed</groupId>

            <artifactId>tomcat-embed-jasper</artifactId>

        </dependency>

 

因爲要springmvc解析jsp,要配置試圖解析器,在applicaiton.properties 裏面新增

spring.mvc.view.prefix=/WEB-INF/jsp/

spring.mvc.view.suffix=.jsp

 

在resources裏面新建WEB-INF文件夾,在裏面放一個index.jsp頁面

 

內容以下:

<%@ page language="java" contentType="text/html; charset=UTF-8"

        pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>享學課堂</title>

</head>

<body>

        <h1>這是個jsp頁面!!</h1>

</body>

</html>

 

最後新建一個controller,注意這裏的註解是@Controller,千萬不能用@RestController

package cn.enjoy.controller;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping("/jsp")

public class JspController {

    @RequestMapping("/hi")

    public String sayHello() {

        return "index";

    }

}

 

 

在瀏覽器上輸入:localhost:8080/jsp/hi,能夠看到JSP頁面。

 

2.13.2.            模板引擎

SpringBoot 推薦使用模板引擎來渲染html,若是你不是歷史遺留項目,必定不要使用JSP,經常使用的模板引擎不少,有freemark,thymeleaf等,其實都大同小異

其中springboot 強烈推薦的是用thymeleaf

 

pom文件種添加thymeleaf的支持,而且刪除JSP的支持

  <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-thymeleaf</artifactId>

        </dependency>

 

        <!--&lt;!&ndash;JavaServer Pages Standard Tag Library,JSP標準標籤庫&ndash;&gt;-->

        <!--<dependency>-->

            <!--<groupId>javax.servlet</groupId>-->

            <!--<artifactId>jstl</artifactId>-->

        <!--</dependency>-->

 

        <!--&lt;!&ndash;內置tocat對Jsp支持的依賴,用於編譯Jsp&ndash;&gt;-->

        <!--<dependency>-->

            <!--<groupId>org.apache.tomcat.embed</groupId>-->

            <!--<artifactId>tomcat-embed-jasper</artifactId>-->

        <!--</dependency>-->

 

刪除application.properties文件裏面視圖解析器內容

#spring.mvc.view.prefix=/WEB-INF/jsp/

#spring.mvc.view.suffix=.jsp

 

新建Controller內容以下

package cn.enjoy.controller;

 

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping("/tpl")

public class ThymeleafController {

    @RequestMapping("/testThymeleaf")

    public String testThymeleaf(ModelMap map) {

     // 設置屬性

     map.addAttribute("name", "enjoy");

     // testThymeleaf:爲模板文件的名稱

     // 對應src/main/resources/templates/testThymeleaf.html

     return "testThymeleaf";

 }

}

 

 

Springboot默認的模板配置路徑爲:src/main/resources/templates

在resources目錄裏面新建一個templates目錄,在目錄裏面新建testThymeleaf.html文件

<!DOCTYPE html>

<html xmlns:th="http://www.w3.org/1999/xhtml">

<head lang="en">

    <meta charset="UTF-8" />

    <title>enjoy</title>

</head>

<body>

<h1 th:text="${name}"/>

</body>

</html>

 

        在瀏覽器上輸入:localhost:8080/tpl/testThymeleaf,能夠看到頁面。

 

2.14.    集成Swagger2構建API文檔

Swagger2 的做用

l  隨項目自動生成強大RESTful API文檔,減小工做量

l  API文檔與代碼整合在一塊兒,便於同步更新API說明

l  頁面測試功能來調試每一個RESTful API

 

修改pom文件,添加swagger2的相關依賴

  <dependency>

            <groupId>io.springfox</groupId>

            <artifactId>springfox-swagger2</artifactId>

            <version>2.7.0</version>

        </dependency>

        <dependency>

            <groupId>io.springfox</groupId>

            <artifactId>springfox-swagger-ui</artifactId>

            <version>2.7.0</version>

        </dependency>

 

 

新建一個swagger的配置類SwaggerConfig.java

package cn.enjoy.utils;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;

import springfox.documentation.builders.PathSelectors;

import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.service.ApiInfo;

import springfox.documentation.service.Contact;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

 

@Configuration

@EnableSwagger2

public class SwaggerConfig {

 

    @Bean

    public Docket createRestApi() {

        return new Docket(DocumentationType.SWAGGER_2)

                .apiInfo(apiInfo())

                .select()

                .apis(RequestHandlerSelectors.basePackage("cn.enjoy"))// 指定掃描包下面的註解

                .paths(PathSelectors.any())

                .build();

    }

    // 建立api的基本信息

    private ApiInfo apiInfo() {

        return new ApiInfoBuilder()

                .title("集成Swagger2構建RESTful APIs")

                .description("集成Swagger2構建RESTful APIs")

                .termsOfServiceUrl("http://www.xiangxueketang.cn/")

                .contact(new Contact("enjoy","cn.xiangxueketang","enjoy@enjoy.cn"))

                .version("1.0.0")

                .build();

    }

}

 

新建Controller用於顯示相關接口

package cn.enjoy.controller;

 

 

import io.swagger.annotations.ApiImplicitParam;

import io.swagger.annotations.ApiOperation;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RestController;

 

import java.util.HashMap;

import java.util.Map;

 

@RestController

@RequestMapping(value="/swagger")

public class SwaggerController {

    @ApiOperation(value="獲取用戶信息", notes="根據id來獲取用戶詳細信息")

    @ApiImplicitParam(name="id", value="用戶ID", required=true, dataType="String")

    @RequestMapping(value="/{id}", method= RequestMethod.GET)

    public Map<String,String> getInfo(@PathVariable String id) {

        Map<String ,String> map = new HashMap<String, String>();

        map.put("name", "lison");

        map.put("age", "38");

        return map;

    }

}

 

訪問:http://localhost:8080/swagger-ui.html

2.15.    日誌集成

java有許多的日誌組件,好比 log4j,log4j2,logback還有java自生提供的Java Util Logging,其實在springboot中對這些組件都提供了支持,log4j,log4j2和logback都提供相應的組件支持。

 

2.15.1.            Logback

在springboot中默認使用的日誌工具是logback,不過在說起具體的日誌工具以前要提一個名詞,這個名詞就是slf4j(Simple Logging Facade For Java)

 

百度百科解釋

https://baike.baidu.com/item/slf4j/6408868

 

slf4j不是具體的日誌解決方案,它有點相似於jdbc,使用了門面模式,是一個針對各種日誌的抽象實現,既然是抽象的日誌實現,在springboot中確定不須要額外導入。

 

注意:spring-boot-starter中就提供了對spring-boot-starter-logging的依賴

在spring-boot-starter-logging中能夠看到以及集成了slf4j與具體實現logback的默認支持

 

 

 

修改UserController

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

private final Logger logger = LoggerFactory.getLogger(UserController.class);

 

 

 

在瀏覽器上輸入:localhost:8080/hello,能夠看控制檯日誌的輸出

 

2.15.1.1.     日誌級別

修改controller 把日誌的輸出改爲

logger.debug("這個一個hello日誌");

 

這個時候重啓,再調用,發現後臺並不會有任何輸出,這緣由是日誌級別在做祟

 

默認狀況下,Spring Boot 配置的是INFO 日誌級別,也就是會輸出INFO級別以上的日誌(ERROR, WARN, INFO)。

若是須要 Debug 級別的日誌。在 src/main/resources/application.properties 中配置。

debug=true

此外,配置 logging.level.* 來具體輸出哪些包的日誌級別。

例如

logging.level.root=INFO

logging.level.org.springframework.web=DEBUG

logging.level.cn.enjoy.controller=DEBUG

 

 

這個時候,包括springframework.web以及cn.enjoy.controller的debug日誌均可以輸出來了

 

 

 

2.15.1.2.     日誌文件

通常狀況下,springboot日誌只會輸出到控制檯,並不會寫入到日誌文件,可是,在一些正式環境的應用中,咱們須要經過在 application.properites 文件中配置 logging.file 文件名稱和 logging.path 文件路徑,將日誌輸出到日誌文件中。

 

logging.path = /var/tmp

logging.file = xxx.log

logging.level.root = info

 

注意:

 

若是隻配置 logging.path,在 /var/tmp文件夾生成一個日誌文件爲 spring.log。若是隻配置 logging.file,會在項目的當前路徑下生成一個 xxx.log 日誌文件。

 

這裏有一個坑,logging.path 和logging.file都配置了,只會有logging.file生效,因此,若是要指定日誌生成的具體位置使用logging.file 配置就好

 

在application.properties中配置

logging.file =F:\\log\\enjoy.log

 

 

這樣在F盤的相應位置出現日誌文件

 

2.15.2.            log4j2

 

在spring-boot-dependencies POMs中搜索spring-boot-starter-log4j2

發現Spring boot父Pom中本身提供了這個依賴,因而咱們加入以下jar依賴:

 

修改pom.xml文件

 <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

            <exclusions>

                <exclusion>

                    <groupId>org.springframework.boot</groupId>

                    <artifactId>spring-boot-starter-logging</artifactId>

                </exclusion>

            </exclusions>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-log4j2</artifactId>

        </dependency>

 

注意: 因爲默認使用logback在擴展log4j2以前先要把logback移除

 

日誌使用跟上面logback同樣。

 

2.15.3.            log4j

若是不僅爲了學習集成log4j,在工做是最好不要使用log4j,畢竟有了log4j2,也有了logback使用log4j就是吃飽了撐着

在springboot中並無提供對log4j這個依賴的支持,所以要使用它配置起來仍是挺麻煩的。

在: mvnrepository.com 中發現log4j最新版本spring-boot-starter-log4j是1.3.8.RELEASE

修改pom.xml文件

 <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

            <exclusions>

                <exclusion>

                    <groupId>org.springframework.boot</groupId>

                    <artifactId>spring-boot-starter-logging</artifactId>

                </exclusion>

            </exclusions>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-log4j</artifactId>

            <version>1.3.8.RELEASE</version>

        </dependency>

 

在classpath下增長log4j.properties文件

log4j.rootCategory=INFO, stdout, file, errorfile

log4j.category.cn.enjoy=INFO, myFile

log4j.logger.error=errorfile

 

# 控制檯輸出

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

 

# root日誌輸出

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender

log4j.appender.file.file=logs/all.log

log4j.appender.file.DatePattern='.'yyyy-MM-dd

log4j.appender.file.layout=org.apache.log4j.PatternLayout

log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

 

# error日誌輸出

log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender

log4j.appender.errorfile.file=logs/error.log

log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd

log4j.appender.errorfile.Threshold = ERROR

log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout

log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

 

# cn.enjoy下的日誌輸出

log4j.appender.myFile=org.apache.log4j.DailyRollingFileAppender

log4j.appender.myFile.file=logs/my.log

log4j.appender.myFile.DatePattern='.'yyyy-MM-dd

log4j.appender.myFile.layout=org.apache.log4j.PatternLayout

log4j.appender.myFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n

 

在代碼中使用

import org.apache.log4j.Logger;

private final Logger logger = Logger.getLogger(xxx.class);

 

2.15.4.            使用AOP統一日誌處理

爲了防止在工做中常常在代碼中加入大量的日誌處理代碼,在實際項目開發中,通常使用AOP統一完成日誌處理工做

 

修改pom文件,引入springboot對aop的支持

<dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-aop</artifactId>

 </dependency>

 

新增AOP日誌處理類

package cn.enjoy.utils;

 

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

 

import javax.servlet.http.HttpServletRequest;

import java.util.Enumeration;

 

 

@Aspect

@Component

public class WebLogAspect {

 

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

 

    @Pointcut("execution(public * cn.enjoy.controller.*.*(..))")

    public void webLog() {

    }

 

    @Before("webLog()")

    public void doBefore(JoinPoint joinPoint) throws Throwable {

        // 接收到請求,記錄請求內容

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        // 記錄下請求內容

        logger.info("URL : " + request.getRequestURL().toString());

        logger.info("HTTP_METHOD : " + request.getMethod());

        logger.info("IP : " + request.getRemoteAddr());

        Enumeration<String> enu = request.getParameterNames();

        while (enu.hasMoreElements()) {

            String name = (String) enu.nextElement();

            logger.info("name:{},value:{}", name, request.getParameter(name));

        }

    }

 

    @AfterReturning(returning = "ret", pointcut = "webLog()")

    public void doAfterReturning(Object ret) throws Throwable {

        // 處理完請求,返回內容

        logger.info("RESPONSE : " + ret);

    }

}

相關文章
相關標籤/搜索