慕課網_《SpringBoot開發經常使用技術整合》學習總結

時間:2018年04月19日星期四
說明:本文部份內容均來自慕課網。@慕課網:https://www.imooc.com
教學源碼:https://github.com/zccodere/s...
學習源碼:https://github.com/zccodere/s...css

第一章:基礎介紹

1-1 簡介說明

SpringBoot簡介html

  • 微框架,與Spring4一塊兒誕生,好比@RestController
  • 能夠快速上手,整合了一些子項目(開源框架或者第三方開源庫)
  • 能夠依賴不多的配置就能夠十分快速的搭建而且運行項目

SpringBoot特色java

  • Spring全家桶的一員:基於Spring,使開發者快速入門,門檻很低
  • SpringBoot能夠建立獨立運行的應用而不依賴於容器
  • 不須要打成war包,能夠放入tomcat中直接運行
  • 提供maven極簡配置,缺點就是會引入不少不須要的包
  • 根據項目來依賴,從而配置Spring,須要什麼引用什麼
  • 提供可視化的相關功能,方便監控,好比性能、應用的健康程度等
  • 簡化配置,不用再看過多的xml,使用註解進行配置
  • 爲微服務SpringCloud鋪路,SpringBoot能夠整合不少框架來構建微服務,好比Dubbo、Thrift等

SpringBoot使用場景mysql

  • 有Spring的地方均可以使用SpringBoot
  • JavaWeb項目:JavaEE項目等
  • 微服務:SpringCloud微服務開發的基礎

1-2 首個項目

Spring官方提供的項目骨架生成地址git

代碼編寫github

1.建立名爲boot-start的maven項目pom文件以下web

<?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>com.myimooc</groupId>
    <artifactId>boot-start</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>boot-start</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--spring boot 熱啓動模塊-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <!--optional = true,表示依賴不會傳遞,即該項目依賴 devtools;若是有其它項目依賴該項目,則其它項目不會自動依賴 devtools-->
            <optional>true</optional>
        </dependency>

        <!--spring boot 配置文件加載模塊-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>

        <!--引入 Freemarker 模版引擎依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--引入 Thymeleaf 模版引擎依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--<dependency>-->
            <!--<groupId>com.alibaba</groupId>-->
            <!--<artifactId>druid</artifactId>-->
            <!--<version>1.1.0</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!--mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>1.2.4</version>
        </dependency>
        <!--pagehelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>com.alibaba</groupId>-->
            <!--<artifactId>druid-spring-boot-starter</artifactId>-->
            <!--<version>1.1.0</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.2</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

        <!--引入redis依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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


</project>

2.編寫BootStartApplication類ajax

package com.myimooc.boot.start;

import org.n3r.idworker.Sid;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import tk.mybatis.spring.annotation.MapperScan;

/**
 * <br>
 * 標題: 啓動類<br>
 * 描述: 首個SpringBoot項目<br>
 * 使用 @EnableScheduling 開啓支持定時任務
 * 使用 @EnableAsync 開啓異步執行程序
 * @author zc
 * @date 2018/04/19
 */
@SpringBootApplication
@MapperScan("com.myimooc.boot.start.dao.mapper")
@EnableScheduling
@EnableAsync
public class BootStartApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootStartApplication.class, args);
    }

    @Bean
    public Sid sid() {
        return new Sid();
    }
}

3.編寫HelloController類redis

package com.myimooc.boot.start.controller;

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

/**
 * <br>
 * 標題: 基於REST的Controller<br>
 * 描述: 返直接返回方法的響應內容<br>
 *
 * @author zc
 * @date 2018/04/19
 */
@RestController
public class HelloController {

    @GetMapping("/hello")
    public Object hello(){
        return "Hello SpringBoot!";
    }

}

而後啓動BootStartApplication,訪問http://localhost:8080/hellospring

第二章:經常使用開發

2-1 響應對象

一般一個應用都會有一個統一的響應對象,用於封裝響應狀態、響應消息、響應數據等,並提供一些經常使用靜態方法

代碼編寫

1.編寫JsonResult類

package com.myimooc.boot.start.domain;

import java.io.Serializable;

/**
 * <br>
 * 標題: 自定義JSON響應數據結構<br>
 * 描述: 統一請求響應返回的格式<br>
 * 200 成功
 * 500 錯誤,錯誤信息在msg字段中
 * 501 Bean驗證錯誤信息,以map返回
 * 502 攔截器攔截到用戶token出錯
 * 555:拋出異常信息
 * @author zc
 * @date 2018/04/19
 */
public class JsonResult implements Serializable{

    private static final long serialVersionUID = 4997293587553904193L;
    /**
     * 響應狀態
     */
    private Integer status;
    /**
     * 響應消息
     */
    private String msg;
    /**
     * 響應數據
     */
    private Object data;

    public static JsonResult build(Integer status,String msg,Object data){
        return new JsonResult(status,msg,data);
    }
    public static JsonResult ok(Object data){
        return new JsonResult(200,"ok",data);
    }
    public static JsonResult ok(){
        return JsonResult.ok(null);
    }
    public static JsonResult errMsg(String msg){
        return new JsonResult(500,msg,null);
    }
    public static JsonResult errMap(Object data){
        return new JsonResult(501,"error",data);
    }
    public static JsonResult errTokenMsg(String msg){
        return new JsonResult(502,msg,null);
    }
    public static JsonResult errException(String msg){
        return new JsonResult(555,msg,null);
    }

    public JsonResult() {
    }

    public JsonResult(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    @Override
    public String toString() {
        return "JsonResult{" +
                "status=" + status +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

2.編寫User類

package com.myimooc.boot.start.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

import java.io.Serializable;
import java.util.Date;

/**
 * <br>
 * 標題: POJO類<br>
 * 描述: 用戶信息<br>
 *
 * @author zc
 * @date 2018/04/19
 */
public class User implements Serializable {

    private static final long serialVersionUID = 7332961063564924222L;
    /**
     * 名稱
     */
    private String name;
    /**
     * 密碼,使用 @JsonIgnore 註解,在序列化爲 JSON 時,忽略該字段
     */
    @JsonIgnore
    private String password;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 生日,使用 @JsonFormat 註解,在序列化爲 JSON 時,使用 pattern 屬性指定的值格式化日期時間
     */
    @JsonFormat(pattern = "yyyy-MM-dd",locale = "zh",timezone = "GMT+8")
    private Date birthday;
    /**
     * 描述,使用 @JsonInclude 註解,在序列化爲 JSON 時,當字段爲 null 時,則忽略該字段
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String note;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", note='" + note + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}

3.編寫UserController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * <br>
 * 標題: 使用Controller<br>
 * 描述: 返回JSON數據<br>
 *
 * @author zc
 * @date 2018/04/19
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/getUser")
    public User getUser(){
        User user = new User();
        user.setName("myImooc2");
        user.setPassword("myImooc");
        user.setAge(22);
        user.setBirthday(new Date());
        user.setNote("Hello");
        return user;
    }

    @GetMapping("/getUserJson")
    public JsonResult getUserJson(){
        User user = new User();
        user.setName("myImooc2");
        user.setPassword("myImooc");
        user.setAge(22);
        user.setBirthday(new Date());
        user.setNote("Hello");
        return JsonResult.ok(user);
    }

}

2-2 配置文件

資源文件中的屬性配置與映射到實體類,即加載配置文件到實體類中

代碼編寫

1.編寫resource.properties

com.imooc.opensource.name=imooc
com.imooc.opensource.website=www.imooc.com
com.imooc.opensource.language=java

2.編寫Resource類

package com.myimooc.boot.start.domain;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * <br>
 * 標題: 配置屬性實體類<br>
 * 描述: 從配置文件中獲取屬性值<br>
 *
 * @author zc
 * @date 2018/04/25
 */
@Configuration
@ConfigurationProperties(prefix = "com.imooc.opensource")
@PropertySource(value = "classpath:resource.properties")
public class Resource {

    private String name;

    private String website;

    private String language;

    @Override
    public String toString() {
        return "Resource{" +
                "name='" + name + '\'' +
                ", website='" + website + '\'' +
                ", language='" + language + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }
}

3.修改HelloController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <br>
 * 標題: 基於REST的Controller<br>
 * 描述: 返直接返回方法的響應內容<br>
 *
 * @author zc
 * @date 2018/04/19
 */
@RestController
public class HelloController {

    @Autowired
    private Resource resource;

    @GetMapping("/hello")
    public Object hello(){
        return "Hello SpringBoot!";
    }

    @GetMapping("/getResource")
    public JsonResult getResource(){
        Resource target = new Resource();
        BeanUtils.copyProperties(resource,target);
        return JsonResult.ok(target);
    }
}

第三章:技術整合

3-1 模版引擎

Spring Boot 整合模版引擎

  • Spring Boot 整合 Freemarker
  • Spring Boot 整合 Thymeleaf

代碼編寫

1.修改pom引入依賴

<!--引入 Freemarker 模版引擎依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--引入 Thymeleaf 模版引擎依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

2.修改application.properties

#------------ Server 服務端相關配置
# 配置 api 端口號
#server.port=8080
# 配置 context-path,通常在正式發佈時不配置
#server.servlet.context-path=/start
# 錯誤頁,指定發生錯誤時,跳轉的URL -> BasicErrorController
#server.error.path=/error
# session 最大超時時間(單位:秒;默認值:30分鐘)
server.servlet.session.timeout=3600
# 綁定ID地址,若是本機不是該ID地址則拋出異常,根據具體業務需求來設置
#server.address=192.168.1.8

# tomcat 最大線程數(默認值:200)
#server.tomcat.max-threads=250
# tomcat 的URI編碼
server.tomcat.uri-encoding=UTF-8

# 配置 i18N 資源文件,供 thymeleaf 讀取
spring.messages.basename=i18n/messages
spring.messages.cache-duration=3600
spring.messages.encoding=UTF-8

# 設置靜態文件路徑,js、css等
spring.mvc.static-path-pattern=/static/**

#------------ Freemarker 靜態資源配置
# 設置 ftl 文件路徑
spring.freemarker.template-loader-path=classpath:/templates/
# 關閉緩存,即時刷新,生產環境需改成true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl

#------------ Thymeleaf 靜態資源配置
spring.thymeleaf.prefix=classpath:/templates/
# 關閉緩存,即時刷新,生產環境需改成true
spring.thymeleaf.cache=false
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html

3.編寫FreemarkerController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.domain.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * <br>
 * 標題: Freemarker<br>
 * 描述: 整合 Freemarker<br>
 *
 * @author zc
 * @date 2018/04/25
 */
@Controller
@RequestMapping("ftl")
public class FreemarkerController {

    @Autowired
    private Resource resource;

    @GetMapping("/index")
    public String index(ModelMap map){
        map.addAttribute("resource",resource);
        return "freemarker/index";
    }

    @GetMapping("/center")
    public String center(){
        return "freemarker/center/center";
    }
}

4.編寫ThymeleafController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <br>
 * 標題: Thymeleaf<br>
 * 描述: 整合 Thymeleaf<br>
 *
 * @author zc
 * @date 2018/04/25
 */
@Controller
@RequestMapping("th")
public class ThymeleafController {

    @RequestMapping("/index")
    public String index(ModelMap map) {
        map.addAttribute("name", "thymeleaf-imooc");
        return "thymeleaf/index";
    }

    @RequestMapping("center")
    public String center() {
        return "thymeleaf/center/center";
    }

    @RequestMapping("test")
    public String test(ModelMap map) {

        User u = new User();
        u.setName("superadmin");
        u.setAge(10);
        u.setPassword("123465");
        u.setBirthday(new Date());
        u.setNote("<font color='green'><b>hello imooc</b></font>");

        map.addAttribute("user", u);

        User u1 = new User();
        u1.setAge(19);
        u1.setName("imooc");
        u1.setPassword("123456");
        u1.setBirthday(new Date());

        User u2 = new User();
        u2.setAge(17);
        u2.setName("LeeCX");
        u2.setPassword("123456");
        u2.setBirthday(new Date());

        List<User> userList = new ArrayList<>();
        userList.add(u);
        userList.add(u1);
        userList.add(u2);

        map.addAttribute("userList", userList);

        return "thymeleaf/test";
    }

    @PostMapping("postform")
    public String postform(User user) {

        System.out.println("姓名:" + user.getName());
        System.out.println("年齡:" + user.getAge());

        return "redirect:/th/test";
    }

    @RequestMapping("showerror")
    public String showerror(User user) {

        int a = 1 / 0;

        return "redirect:/th/test";
    }
}

5.受篇幅限制,頁面代碼就不顯示了,源碼請到github查看。完成後的目錄結構以下

clipboard.png

3-2 全局異常

代碼編寫

1.編寫ErrorController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * <br>
 * 標題: 錯誤頁演示<br>
 * 描述: 跳轉至錯誤頁<br>
 *
 * @author zc
 * @date 2018/04/25
 */
@Controller
@RequestMapping("err")
public class ErrorController {

    @RequestMapping("/error")
    public String error() {
        int a = 1 / 0;
        return "thymeleaf/error";
    }
    
    @RequestMapping("/ajaxerror")
    public String ajaxerror() {
        return "thymeleaf/ajaxerror";
    }
    
    @RequestMapping("/getAjaxerror")
    @ResponseBody
    public JsonResult getAjaxerror() {
        int a = 1 / 0;
        return JsonResult.ok();
    }
}

2.編寫GlobalExceptionHandler類

package com.myimooc.boot.start.exception;

import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * <br>
 * 標題: 全局異常捕獲,兼容 web 和 ajax<br>
 * 描述: 使用 @ControllerAdvice 聲明當前是助手類<br>
 *
 * @author zc
 * @date 2018/04/25
 */
@ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final String ERROR_VIEW = "error";

    @ExceptionHandler(Exception.class)
    public Object handler(HttpServletRequest request, HttpServletResponse response, Exception e) {
        e.printStackTrace();

        if (isAjax(request)) {
            return this.responseByAjax(request, response, e);
        }
        return this.responseByWeb(request, response, e);
    }

    private boolean isAjax(HttpServletRequest request) {
        return (request.getHeader("X-Requested-With") != null) && ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) ;
    }

    private JsonResult responseByAjax(HttpServletRequest request, HttpServletResponse response, Exception e) {
        return JsonResult.errException(e.getMessage());
    }

    private ModelAndView responseByWeb(HttpServletRequest request, HttpServletResponse response, Exception e) {
        ModelAndView mav = new ModelAndView();
        mav.setViewName(ERROR_VIEW);
        mav.addObject("exception", e);
        mav.addObject("url", request.getRequestURL());
        return mav;
    }
}

3-3 持久框架

Spring Boot 整合 MyBatis

  • 使用generatorConfig生成mapper以及pojo
  • 實現基於MyBatis的CRUD功能
  • 整合MyBatis-pagehelper實現分頁
  • 自定義mapper的實現

受篇幅限制,代碼就不顯示了,源碼請到github查看。

3-4 緩存技術

Spring Boot 整合 Redis

代碼編寫

1.引入redis依賴

<!--引入redis依賴-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.配置application.properties

#------------ redis 配置
# redis 數據庫索引(默認值:0)
spring.redis.database=0
# redis 服務器地址
spring.redis.host=127.0.0.1
# redis 服務器端口
spring.redis.port=6379

3.編寫JsonUtils類

package com.myimooc.boot.start.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;

/**
 * <br>
 * 標題: 定義響應結構, 轉換類<br>
 * 描述: Json工具<br>
 *
 * @author zc
 * @date 2018/04/26
 */
public class JsonUtils {

    // 定義jackson對象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 將對象轉換成json字符串。
     * <p>Title: pojoToJson</p>
     * <p>Description: </p>
     * @param data
     * @return
     */
    public static String objectToJson(Object data) {
        try {
            String string = MAPPER.writeValueAsString(data);
            return string;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 將json結果集轉化爲對象
     * 
     * @param jsonData json數據
     * @param beanType 對象中的object類型
     * @return
     */
    public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
        try {
            T t = MAPPER.readValue(jsonData, beanType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 將json數據轉換成pojo對象list
     * @param jsonData
     * @param beanType
     * @return
     */
    public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            List<T> list = MAPPER.readValue(jsonData, javaType);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
}

4.編寫RedisOperator類

package com.myimooc.boot.start.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <br>
 * 標題: Redis 經常使用方法封裝<br>
 * 描述: 使用redisTemplate的操做實現類<br>
 *
 * @author zc
 * @date 2018/04/26
 */
@Component
public class RedisOperator {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // Key(鍵),簡單的key-value操做

    /**
     * 實現命令:TTL key,以秒爲單位,返回給定 key的剩餘生存時間(TTL, time to live)。
     *
     * @param key
     * @return
     */
    public long ttl(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 實現命令:expire 設置過時時間,單位秒
     *
     * @param key
     * @return
     */
    public void expire(String key, long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 實現命令:INCR key,增長key一次
     *
     * @param key
     * @return
     */
    public long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 實現命令:KEYS pattern,查找全部符合給定模式 pattern的 key
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 實現命令:DEL key,刪除一個key
     *
     * @param key
     */
    public void del(String key) {
        redisTemplate.delete(key);
    }

    // String(字符串)

    /**
     * 實現命令:SET key value,設置一個key-value(將字符串值 value關聯到 key)
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 實現命令:SET key value EX seconds,設置key-value和超時時間(秒)
     *
     * @param key
     * @param value
     * @param timeout (以秒爲單位)
     */
    public void set(String key, String value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 實現命令:GET key,返回 key所關聯的字符串值。
     *
     * @param key
     * @return value
     */
    public String get(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    // Hash(哈希表)

    /**
     * 實現命令:HSET key field value,將哈希表 key中的域 field的值設爲 value
     *
     * @param key
     * @param field
     * @param value
     */
    public void hset(String key, String field, Object value) {
        redisTemplate.opsForHash().put(key, field, value);
    }

    /**
     * 實現命令:HGET key field,返回哈希表 key中給定域 field的值
     *
     * @param key
     * @param field
     * @return
     */
    public String hget(String key, String field) {
        return (String) redisTemplate.opsForHash().get(key, field);
    }

    /**
     * 實現命令:HDEL key field [field ...],刪除哈希表 key 中的一個或多個指定域,不存在的域將被忽略。
     *
     * @param key
     * @param fields
     */
    public void hdel(String key, Object... fields) {
        redisTemplate.opsForHash().delete(key, fields);
    }

    /**
     * 實現命令:HGETALL key,返回哈希表 key中,全部的域和值。
     *
     * @param key
     * @return
     */
    public Map<Object, Object> hgetall(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    // List(列表)

    /**
     * 實現命令:LPUSH key value,將一個值 value插入到列表 key的表頭
     *
     * @param key
     * @param value
     * @return 執行 LPUSH命令後,列表的長度。
     */
    public long lpush(String key, String value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 實現命令:LPOP key,移除並返回列表 key的頭元素。
     *
     * @param key
     * @return 列表key的頭元素。
     */
    public String lpop(String key) {
        return (String) redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 實現命令:RPUSH key value,將一個值 value插入到列表 key的表尾(最右邊)。
     *
     * @param key
     * @param value
     * @return 執行 LPUSH命令後,列表的長度。
     */
    public long rpush(String key, String value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

}

5.編寫RedisController類

package com.myimooc.boot.start.controller;

import com.myimooc.boot.start.dao.po.SysUser;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.User;
import com.myimooc.boot.start.util.JsonUtils;
import com.myimooc.boot.start.util.RedisOperator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <br>
 * 標題: 整合redis<br>
 * 描述: redis訪問<br>
 *
 * @author zc
 * @date 2018/04/26
 */
@RestController
@RequestMapping("redis")
public class RedisController {

    @Autowired
    private StringRedisTemplate strRedis;

    @Autowired
    private RedisOperator redis;

    @RequestMapping("/test")
    public JsonResult test() {
        strRedis.opsForValue().set("imooc-cache", "hello 慕課網~~~~~~");
        SysUser user = new SysUser();
        user.setId("100111");
        user.setUsername("imooc");
        user.setPassword("abc123");
        user.setIsDelete(0);
        user.setRegistTime(new Date());
        strRedis.opsForValue().set("json:user", JsonUtils.objectToJson(user));
        SysUser jsonUser = JsonUtils.jsonToPojo(strRedis.opsForValue().get("json:user"), SysUser.class);
        return JsonResult.ok(jsonUser);
    }

    @RequestMapping("/getJsonList")
    public JsonResult getJsonList() {

        User user = new User();
        user.setAge(18);
        user.setName("慕課網");
        user.setPassword("123456");
        user.setBirthday(new Date());

        User u1 = new User();
        u1.setAge(19);
        u1.setName("imooc");
        u1.setPassword("123456");
        u1.setBirthday(new Date());

        User u2 = new User();
        u2.setAge(17);
        u2.setName("hello imooc");
        u2.setPassword("123456");
        u2.setBirthday(new Date());

        List<User> userList = new ArrayList<>();
        userList.add(user);
        userList.add(u1);
        userList.add(u2);

        redis.set("json:info:userlist", JsonUtils.objectToJson(userList), 2000);

        String userListJson = redis.get("json:info:userlist");
        List<User> userListBorn = JsonUtils.jsonToList(userListJson, User.class);

        return JsonResult.ok(userListBorn);
    }
}

3-5 定時任務

代碼編寫

1.修改BootStartApplication啓動類,增長註解

@EnableScheduling

2.編寫TestTask類

package com.myimooc.boot.start.tasks;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * <br>
 * 標題: 測試定時任務<br>
 * 描述: 自定義定時任務<br>
 *
 * @author zc
 * @date 2018/04/26
 */
@Component
public class TestTask {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    /**
     * 定義每過3秒執行任務
     * 支持使用 @Scheduled(cron = "4-40 * * * * ?") cron表達式
     */
    @Scheduled(fixedRate = 3000)
    public void reportCurrentTime() {
        System.out.println("如今時間:" + dateFormat.format(new Date()));
    }
}

3-6 異步任務

異步任務使用場景

  • 發送短信
  • 發送郵件
  • APP消息推送
  • 提升效率

代碼編寫

1.修改BootStartApplication啓動類,增長註解

@EnableAsync

2.編寫AsyncTask類

package com.myimooc.boot.start.tasks;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import java.util.concurrent.Future;

/**
 * <br>
 * 標題: 自定義異步執行任務<br>
 * 描述: 異步方法需使用 @Async 註解<br>
 * 判斷任務是否完成,必須返回 Future 接口
 * @author zc
 * @date 2018/04/26
 */
@Component
public class AsyncTask {

    @Async
    public Future<Boolean> doTask11() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(1000);
        long end = System.currentTimeMillis();
        System.out.println("任務1耗時:" + (end - start) + "毫秒");
        return new AsyncResult<>(true);
    }

    @Async
    public Future<Boolean> doTask22() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(700);
        long end = System.currentTimeMillis();
        System.out.println("任務2耗時:" + (end - start) + "毫秒");
        return new AsyncResult<>(true);
    }

    @Async
    public Future<Boolean> doTask33() throws Exception {
        long start = System.currentTimeMillis();
        Thread.sleep(600);
        long end = System.currentTimeMillis();
        System.out.println("任務3耗時:" + (end - start) + "毫秒");
        return new AsyncResult<>(true);
    }
}

3.編寫DoTaskController類

package com.myimooc.boot.start.tasks;

import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Future;

/**
 * <br>
 * 標題: 調用異步方法的controller<br>
 * 描述: 異步任務<br>
 *
 * @author zc
 * @date 2018/04/26
 */
@RestController
@RequestMapping("/tasks")
public class DoTaskController {

    @Autowired
    private AsyncTask asyncTask;

    @RequestMapping("/asyncTask")
    public JsonResult asyncTask() throws Exception {
        long start = System.currentTimeMillis();
        Future<Boolean> a = asyncTask.doTask11();
        Future<Boolean> b = asyncTask.doTask22();
        Future<Boolean> c = asyncTask.doTask33();
        while (!a.isDone() || !b.isDone() || !c.isDone()) {
            if (a.isDone() && b.isDone() && c.isDone()) {
                break;
            }
        }
        long end = System.currentTimeMillis();
        String times = "任務所有完成,總耗時:" + (end - start) + "毫秒";
        System.out.println(times);
        return JsonResult.ok(times);
    }
}

3-7 用攔截器

Spring Boot 攔截器的使用

  • 使用註解@Configuration配置攔截器
  • 繼承WebMvcConfigurerAdapter
  • 從新addInterceptors增長鬚要的攔截器地址

代碼編寫

1.編寫OneInterceptor類

package com.myimooc.boot.start.interceptor;

import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.util.JsonUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;

/**
 * <br>
 * 標題: 自定義攔截器一<br>
 * 描述: 攔截器<br>
 *
 * @author zc
 * @date 2018/04/26
 */
public class OneInterceptor implements HandlerInterceptor {

    /**
     * 在請求處理以前進行調用(Controller方法調用以前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object object) throws Exception {

        System.out.println("被one攔截,放行...");
        return true;

//         當校驗不經過時,返回 ajax 錯誤信息
//        if (true) {
//            this.returnErrorResponse(response, JsonResult.errMsg("被one攔截"));
//        }
//        return false;
    }

    /**
     * 請求處理以後進行調用,可是在視圖被渲染以前(Controller方法調用以後)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object object, ModelAndView mv)
            throws Exception {
        // 能夠修改返回的數據
    }

    /**
     * 在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行
     * (主要是用於進行資源清理工做)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object object, Exception ex)
            throws Exception {

    }

    private void returnErrorResponse(HttpServletResponse response, JsonResult result) throws Exception {
        OutputStream out = null;
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/json");
            out = response.getOutputStream();
            out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
            out.flush();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

2.編寫TwoInterceptor類

package com.myimooc.boot.start.interceptor;

import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.util.JsonUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;

/**
 * <br>
 * 標題: 自定義攔截器二<br>
 * 描述: 攔截器<br>
 *
 * @author zc
 * @date 2018/04/26
 */
public class TwoInterceptor implements HandlerInterceptor  {

    /**
     * 在請求處理以前進行調用(Controller方法調用以前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        if (true) {
            returnErrorResponse(response, JsonResult.errMsg("被two攔截"));
        }
        System.out.println("被two攔截...");
        return false;
    }
    
    /**
     * 請求處理以後進行調用,可是在視圖被渲染以前(Controller方法調用以後)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv)
            throws Exception {
    }
    
    /**
     * 在整個請求結束以後被調用,也就是在DispatcherServlet 渲染了對應的視圖以後執行(主要是用於進行資源清理工做)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex)
            throws Exception {
    }
    
    public void returnErrorResponse(HttpServletResponse response, JsonResult result) throws Exception{
        OutputStream out=null;
        try{
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/json");
            out = response.getOutputStream();
            out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
            out.flush();
        } finally{
            if(out!=null){
                out.close();
            }
        }
    }
}

3.編寫WebMvcConfig類

package com.myimooc.boot.start.config;

import com.myimooc.boot.start.interceptor.OneInterceptor;
import com.myimooc.boot.start.interceptor.TwoInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * <br>
 * 標題: 自定義配置類<br>
 * 描述: 註冊自定義的攔截器<br>
 *
 * @author zc
 * @date 2018/04/26
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /**
         * 攔截器按照順序執行
         */
        registry.addInterceptor(new TwoInterceptor()).addPathPatterns("/two/**").addPathPatterns("/one/**");
        registry.addInterceptor(new OneInterceptor()).addPathPatterns("/one/**");
        super.addInterceptors(registry);
    }
}

第四章:課程總結

4-1 課程總結

課程總結

  • 搭建項目
  • 模版引擎
  • 全局異常
  • 持久框架
  • 緩存技術
  • 定時任務
  • 異步任務
  • 使用攔截器
相關文章
相關標籤/搜索