天天看點

畢業季·大學最遺憾的事/沒有完成的事?

活動位址:​​畢業季·進擊的技術er​​

夏日炎炎,熱浪中我們迎來畢業季,這是告别,也是邁向新起點的開始,CSDN誠邀各畢業生/在校生/職場人講述自己的畢業季故事,分享自己的經驗,技術er的進擊之路。

畢業生
大學最遺憾的事/沒有完成的事?
活動位址:​​畢業季·進擊的技術er​​

大學最遺憾的事/沒有完成的事?

大學中最應該做的一件事就是學一個傍身的技能,讓自己有一個比較穩妥高新的工作,否則你将面臨的是無數人都不願意面臨的很多問題。

一技在手,吃喝不愁

實施運維工程師,是一個非常不錯的選擇,而且現階段中國在大搞基礎網絡裝置建設,大搞網際網路、大資料、雲計算經濟,隻要能在這個大潮中分一杯羹,起碼能讓你過一個普普通通的生活是沒問題的。

目錄

​​​​​​​​必備技能,基礎服務架設​​

​​📋文章連結📋​​

​​學習方法備注:​​

​​初學者:​​

​​複習者:​​

​​環境架設,必不可少​​

​​📋文章連結📋​​

​​聯考後能學習——阿裡雲-winserver伺服器購買以及使用(包含【.Net】、【PHP】、【MySQL】、【Navicat】、【Java】、安裝)​​

​​linux環境架設​​

​​📋文章連結📋​​

​​阿裡雲——ECS——Linux伺服器購買流程——超級細緻​​

​​Linux複習資料(二)、Linux基本操作​​

​​Linux複習資料——CentOS7下安裝MySQL5.7.22(完整版本)​​

​​Linux複習資料——一篇文章學會安裝Java(免環境配置)以及tomcat服務ASP.NET Core微服務(七)——【docker部署linux上線】(RDS+API接口測試部分)​​

​​ASP.NETCore微服務(七)——【docker部署linux上線】(ECS+linux+docker+API上線部分)​​

​​程式設計語言,首選Java,架構必須springboot​​

​​springboot快速入門一篇文章全​​

​​ springboot01、基本配置​​

​​springboot簡介​​

​​1、pom.xml​​

​​2、項目層次​​

​​3、啟動檔案【com.item/Action.java】​​

​​4、controller檔案​​

​​5、啟動測試(資料是跨域的)​​

​​ springboot02、打war包​​

​​Spring Boot 打包為 war 并運作​​

​​1、修改打包方式​​

​​2、修改啟動檔案【Action.java】​​

​​3、打包指令​​

​​4、打包效果:​​

​​springboot03、實作mybatis​​

​​1、pom引包​​

​​2、資料源配置application.properties​​

​​3、model對應資料庫的類Users​​

​​4、dao層·需要加上@Repository注解​​

​​5、添加映射檔案UsersMapper.xml​​

​​6、service層編碼​​

​​7、serviceimpl層編碼​​

​​8、Controller層編碼​​

​​備注:dao層引入​​

​​9、測試效果:​​

​​StringUtils判斷字元串是否為空​​

​​StringUtils依賴包:​​

​​StringUtils測試編碼:​​

​​StringUtils測試效果:​​

​​ springboot04、swagger配置​​

​​前言:​​

​​1、pom依賴​​

​​2、swagger配置檔案​​

​​3、接口api寫法​​

​​4、啟動效果:【http://127.0.0.1:8088/swagger-ui.html】​​

​​5、使用方法​​

​​編輯​​

​​6、可能出現的異常總結:​​

​​ springboot05、封裝結果集​​

​​建立【com.item.res】包​​

​​注意問題:​​

​​ springboot06、log4j2日志配置​​

​​前言:​​

​​1、pom配置​​

​​2、log4j2-spring.xml配置檔案​​

​​3、在application.properties中引入log4j2的配置​​

​​4、log4j使用​​

​​ springboot07、task定時任務​​

​​定時任務的概述​​

​​1、啟動類上添加@EnableScheduling​​

​​2、建立測試包【com.item.task】​​

​​2.1fixedRate定時​​

​​2.2cron定時​​

​​springboot08、攔截器HandlerInterceptor​​

​​前言​​

​​1、建立攔截器【com.item.handler】​​

​​2、生效配置【com.item.handler】内建立【WebConfig】​​

​​3、攔截器效果: ​​

​​4、攔截器作用​​

​​springboot09、監控​​

​​前言​​

​​1、pom配置​​

​​2、啟動項配置​​

​​3、通路首頁​​

​​4、用戶端pom依賴:​​

​​5、修改用戶端配置​​

​​ springboot10、AOP​​

​​前言​​

​​1、pom依賴​​

​​2、AOP控制器【com.item.aop】​​

​​3、測試apo效果​​

​​4、使用 AOP 監控性能​​

​​springboot11、redis​​

​​前言​​

​​1、pom依賴​​

​​2、配置聲明(application.properties中)​​

​​3、編寫配置檔案【com.item.redis】​​

​​4、操作提示​​

​​5、RedisBase編碼(隻包含字元串處理)​​

​​6、建立測試接口【com.item.controller】内​​

​​7、編寫redis層級【com.item.Base】​​

​​8、啟動測試http://127.0.0.1:8088/swagger-ui.htm​​

必備技能,基礎服務架設

一切的基礎都是資料庫,是以第一步要搞定的就是MySQL操作:

📋文章連結📋

​​MySQL複習資料(一)——MySQL環境安裝​​

​​MySQL複習資料(二)——MySQL-DDL語句​​

​​MySQL複習資料(三)——MySQL-DML語句​​

​​MySQL複習資料(四)——MySQL-聚合函數​​

​​MySQL複習資料(五)——MySQL-索引​​

​​MySQL複習資料(六)——MySQL-多表聯合查詢​​

​​MySQL複習資料(七)——MySQL-存儲過程​​

​​MySQL複習資料(八)——MySQL-事務​​

​​MySQL複習資料(九)——MySQL-圖形化工具使用​​

學習方法備注:

初學者:

學習步驟按順序即可。從一到九,完整的學習過程。

複習者:

先看【九】,所有的操作過程使用【圖形化工具】進行操作,複習時間預計2個小時。

環境架設,必不可少

📋文章連結📋

​​聯考後能學習——阿裡雲-winserver伺服器購買以及使用(包含【.Net】、【PHP】、【MySQL】、【Navicat】、【Java】、安裝)​​

通過此篇文章可以讓你掌握多種語言的運作環境搭建。這篇是winserver的後面還會有linux版本的,内容更豐富。

linux環境架設

📋文章連結📋

​​阿裡雲——ECS——Linux伺服器購買流程——超級細緻​​

​​Linux複習資料(二)、Linux基本操作​​

​​Linux複習資料——CentOS7下安裝MySQL5.7.22(完整版本)​​

​​Linux複習資料——一篇文章學會安裝Java(免環境配置)以及tomcat服務​​​

ASP.NET Core微服務(七)——【docker部署linux上線】(RDS+API接口測試部分)​​

​​ASP.NETCore微服務(七)——【docker部署linux上線】(ECS+linux+docker+API上線部分)​​

程式設計語言,首選Java,架構必須springboot

畢業季·大學最遺憾的事/沒有完成的事?

springboot快速入門一篇文章全

 springboot01、基本配置

springboot簡介

Spring Boot 為簡化 Spring 應用開發而生,Spring Boot 中的 Boot 一詞,即為快速啟動的意思。Spring Boot 可以在零配置情況下一鍵啟動,簡潔而優雅。

為了讓 Spring 開發者痛快到底,Spring 團隊做了以下設計:

  • 簡化依賴,提供整合的依賴項,告别逐一添加依賴項的煩惱;
  • 簡化配置,提供約定俗成的預設配置,告别編寫各種配置的繁瑣;
  • 簡化部署,内置 servlet 容器,開發時一鍵即運作。可打包為 jar 檔案,部署時一行指令即啟動;
  • 簡化監控,提供簡單友善的運作監控方式。
基于以上設計目的,Spring 團隊推出了 Spring Boot 。

目錄

​​1、pom.xml​​

​​2、項目層次​​

​​3、啟動檔案【com.item/Action.java】​​

​​4、controller檔案​​

​​5、啟動測試(資料是跨域的)​​

1、pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>      

2、項目層次

畢業季·大學最遺憾的事/沒有完成的事?

3、啟動檔案【com.item/Action.java】

package com.item;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Action {
    public static void main(String[] args) {
        SpringApplication.run(Action.class,args);//一定是被@SpringBootApplication标記的類
    }

}      

4、controller檔案

其中@RestController = @Controller + @ResponseBody;

package com.item.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
@CrossOrigin
public class UsersController {

    @GetMapping("GetInfo")
    public Object GetInfo(){
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","有一個字元串");
        return map;
    }
}      

5、啟動測試(資料是跨域的)

畢業季·大學最遺憾的事/沒有完成的事?

通路路徑:【​​http://127.0.0.1:8080/GetInfo​​】

畢業季·大學最遺憾的事/沒有完成的事?

 springboot02、打war包

Spring Boot 打包為 war 并運作

将 Spring Boot 打包為 war ,然後放置于 Tomcat 的 webapps 目錄下加載運作,接下來我們就較長的描述下打包為 war 的過程。

目錄

​​1、修改打包方式​​

​​2、修改啟動檔案【Action.java】​​

​​3、打包指令​​

​​4、打包效果:​​

1、修改打包方式

在【pom.xml】檔案中修改預設的打包方式,顯式指定打包方式為 war。

<name>demospring</name>
<packaging>war</packaging>      
畢業季·大學最遺憾的事/沒有完成的事?

由于 Spring Boot 内置了 Tomcat ,是以我們在打包時需要排除内置的 Tomcat ,這樣可以避免内置 Tomcat 和 war 包部署運作的 Tomcat 産生沖突。在 pom.xml 中添加如下依賴即可:

畢業季·大學最遺憾的事/沒有完成的事?
<!-- 阻斷器·打包的是否排除内置的tomcat -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>      

2、修改啟動檔案【Action.java】

package com.item;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Action extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Action.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Action.class,args);//一定是被@SpringBootApplication标記的類
    }
}      

3、打包指令

項目路徑中打開【cmd】并執行

mvn clean package -Dmaven.test.skip=true      
畢業季·大學最遺憾的事/沒有完成的事?

4、打包效果:

使用 ​

​mvn clean package -Dmaven.test.skip=true​

​ 指令打包應用了,運作指令後會在 target 目錄下生成 war 檔案,将該檔案放置于 Tomcat 的 webapps 目錄下運作即可。
畢業季·大學最遺憾的事/沒有完成的事?

前後端分離部署的方式,更能發揮伺服器的性能,如果要進行版本更新,直接替換後端war包就OK。

springboot03、實作mybatis

目錄

​​1、pom引包​​

​​2、資料源配置application.properties​​

​​3、model對應資料庫的類Users​​

​​4、dao層·需要加上@Repository注解​​

​​5、添加映射檔案UsersMapper.xml​​

​​6、service層編碼​​

​​7、serviceimpl層編碼​​

​​8、Controller層編碼​​

​​9、測試效果:​​

1、pom引包

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- 熱部署 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <!-- Web支援 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- JDBC -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- MySQL驅動 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- 內建MyBatis -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.2</version>
    </dependency>
    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>test</scope>
    </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>      

2、資料源配置application.properties

Spring Boot 會将資料源自動注入到 MyBatis 的 sqlSessionFactory 元件中。對于我們開發者來說,這一切都是自動實作的,非常簡單。
# 配置資料庫驅動
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置資料庫url
spring.datasource.url=jdbc:mysql://rm-bp1zq3879r28p726lco.mysql.rds.aliyuncs.com:3306/test?characterEncoding=utf8
# 配置資料庫使用者名
spring.datasource.username=qwe8403000
# 配置資料庫密碼
spring.datasource.password=Qwe8403000
# 指定MyBatis配置檔案位置
mybatis.mapper-locations=classpath:mapper/*.xml
# 指定模型位置
mybatis.typeAliasesPackage=com.item.model
# 修改端口号避免沖突
server.port=8088
# 服務路徑
server.servlet.context-path=/demospring      

3、model對應資料庫的類Users

package com.item.model;
 
public class Users {
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getPwd() {
        return pwd;
    }
 
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
 
    public String getNickName() {
        return nickName;
    }
 
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
 
    @Override
    public String toString() {
        return "Users{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", pwd='" + pwd + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
 
    private int id;
    private String userName;
    private String pwd;
    private String nickName;
 
}      

4、dao層·需要加上@Repository注解

package com.item.dao;

import com.item.model.Users;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
/**
 * 資料通路元件
 */
@Repository
public interface UsersMapper {
    List<Users> GetInfo();
    List<Users> SelectName(@Param("nickName") String nickName);
    Users UsersSelectById(@Param("id") int id);
    int UsersAddInfo(
            @Param("userName") String userName,
            @Param("pwd") String pwd,
            @Param("nickName") String nickName
    );
    int UsersUpdateInfo(
            @Param("pwd") String pwd,
            @Param("id") int id
    );
    int UsersDeleteById(@Param("id") int id);
}      

5、添加映射檔案UsersMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.item.dao.UsersMapper">
    <!-- 用作基礎查詢測試 -->
    <select id="GetInfo" resultType="Users">
        select * from users
    </select>
    <!-- 用做傳遞參數測試 -->
    <select id="SelectName" resultType="Users">
        select * from users where nickName like "%${nickName}%"
    </select>
    <!-- id精準查詢 -->
    <select id="UsersSelectById" resultType="Users">
        select * from users where id=#{id}
    </select>
    <!-- 增加 -->
    <insert id="UsersAddInfo">
        insert into users values(0,"${userName}","${pwd}","${nickName}");
    </insert>
    <!-- 修改 -->
    <update id="UsersUpdateInfo">
        update users set pwd="${pwd}" where id=#{id}
    </update>
    <!-- 删除 -->
    <delete id="UsersDeleteById">
        delete from users where id=#{id}
    </delete>
</mapper>      

6、service層編碼

package com.item.service;
 
import com.item.model.Users;

import java.util.List;
 
public interface UsersService {
    /**
     * 擷取所有
     * @return
     */
    List<Users> GetInfo();
 
    /**
     * 擷取nickName的模糊查詢結果集
     * @param nickName
     * @return
     */
    List<Users> SelectName(String nickName);
 
    /**
     * id精準查詢
     * @param id
     * @return
     */
    Users UsersSelectById(int id);
 
    /**
     * 添加資訊
     * @param userName
     * @param pwd
     * @param nickName
     * @return
     */
    int UsersAddInfo(
            String userName,
            String pwd,
            String nickName
    );
 
    /**
     * 修改密碼
     * @param pwd
     * @param id
     * @return
     */
    int UsersUpdateInfo(
            String pwd,
            int id
    );
 
    /**
     * 删除資訊
     * @param id
     * @return
     */
    int UsersDeleteById(int id);
}      

7、serviceimpl層編碼

package com.item.serviceimpl;
 
import com.item.dao.UsersMapper;
import com.item.model.Users;
import com.item.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
 
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
 
@Service
public class UsersServiceImpl implements UsersService {
    @Autowired
    private UsersMapper usersMapper;
 
    @Override
    public List<Users> GetInfo() {
        return usersMapper.GetInfo();
    }
 
    @Override
    public List<Users> SelectName(String nickName) {
        return usersMapper.SelectName(nickName);
    }
 
    @Override
    public Users UsersSelectById(int id) {
        return usersMapper.UsersSelectById(id);
    }
 
    @Override
    public int UsersAddInfo(String userName, String pwd, String nickName) {
        pwd=encrypt(pwd);
        return usersMapper.UsersAddInfo(userName, pwd, nickName);
    }
 
    @Override
    public int UsersUpdateInfo(String pwd, int id) {
        pwd=encrypt(pwd);
        return usersMapper.UsersUpdateInfo(pwd, id);
    }
 
    /**
     * MD5加密
     * @param password
     * @return
     */
    private String encrypt(String password) {
        String passwordMd5 = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(password.getBytes("utf-8"));
            passwordMd5 = toHex(bytes);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return passwordMd5;
    }
 
    private static String toHex(byte[] bytes) {
        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }
 
    @Override
    public int UsersDeleteById(int id) {
        return usersMapper.UsersDeleteById(id);
    }
}      

8、Controller層編碼

package com.item.controller;

import com.item.model.Users;
import com.item.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;

@RestController
@CrossOrigin
public class UsersController {
    @Autowired
    private UsersService usersService;

    @GetMapping("/GetInfoApi")
    public Object GetInfoApi(){
        List<Users> list=usersService.GetInfo();
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",list);
        return map;
    }

    @GetMapping("/GetName")
    public Object GetName(HttpServletRequest request,Model model){
        String nickName = request.getParameter("nickName");
        List<Users> list=usersService.SelectName(nickName);
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",list);
        return map;
    }

    /**
     * 添加接口,通路方式post
     * @param request
     * @param model
     * @return
     */
    @PostMapping(value = "/UserAddInfoApi")
    public Object UserAddInfoApi(HttpServletRequest request,Model model){
        String userName = request.getParameter("userName");
        String pwd = request.getParameter("pwd");
        String nickName = request.getParameter("nickName");
        usersService.UsersAddInfo(userName, pwd, nickName);
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }

    /**
     * 單個查詢
     * @param request
     * @param model
     * @return
     */
    @GetMapping("/UsersSelectById")
    public Object UsersSelectById(HttpServletRequest request,Model model){
        String id = request.getParameter("id");
        Users users = usersService.UsersSelectById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",users);
        return map;
    }

    /**
     * 修改api
     * @param request
     * @param model
     * @return
     */
    @PostMapping(value = "/UserUpdateInfoApi")
    public Object UserUpdateInfoApi(HttpServletRequest request,Model model){
        String id = request.getParameter("id");
        String pwd = request.getParameter("pwd");
        usersService.UsersUpdateInfo(pwd,Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }

    /**
     * 删除api
     * @param request
     * @param model
     * @return
     */
    @GetMapping(value = "/UsersDeleteById")
    public Object UsersDeleteById(HttpServletRequest request,Model model){
        String id = request.getParameter("id");
        usersService.UsersDeleteById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }
}      

備注:dao層引入

package com.item;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@MapperScan("com.item.dao")
@SpringBootApplication
public class Action extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Action.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Action.class,args);//一定是被@SpringBootApplication标記的類
    }
}      

9、測試效果:

可以使用postman測試:

畢業季·大學最遺憾的事/沒有完成的事?

效果很明顯,成功了。

StringUtils判斷字元串是否為空

 可以直接看到測試效果,無論是null還是""都是空。

StringUtils依賴包:

<!-- 判斷字元串是否為空 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.8.1</version>
</dependency>      

StringUtils測試編碼:

import org.apache.commons.lang3.StringUtils;

public class Action {
    public static void main(String[] args) {
        String a=null;
        String b="";
        if(StringUtils.isEmpty(a)){
            System.out.println("a空");
        }
        if(StringUtils.isEmpty(b)){
            System.out.println("b空");
        }
    }
}      

StringUtils測試效果:

畢業季·大學最遺憾的事/沒有完成的事?

 springboot04、swagger配置

前言:

springboot的swagger配置與SSM稍微有些不同,SSM對2.9.0以上的相容性很差,但是springboot就可以使用2.9.0以上的包了,其實差別不算太大,除了能對對象直接操作外就是頁面更清爽了。

目錄

​​1、pom依賴​​

​​2、swagger配置檔案​​

​​3、接口api寫法​​

​​4、啟動效果:【http://127.0.0.1:8088/swagger-ui.html】​​

​​5、使用方法​​

​​編輯​​

​​6、可能出現的異常總結:​​

1、pom依賴

<!-- swagger包這裡2.9.2 -->
<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>      

2、swagger配置檔案

這裡單獨建立了一個包【com.item.swagger】來放置swagger的配置檔案

需要注意的是:【com.item.controller】這裡需要改成自己的包位置。

package com.item.swagger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 {
    private static Logger log = LoggerFactory.getLogger(SwaggerConfig.class);
    @Bean
    public Docket createRestApi() {
        log.info("進入到swagger的配置中");
        return new Docket(DocumentationType.SWAGGER_2)
                // 指定建構api文檔的詳細資訊的方法:apiInfo()
                .apiInfo(apiInfo())
                .groupName("紅目香薰")
                .select()
                // 指定要生成api接口的包路徑,這裡把controller作為包路徑,生成controller中的所有接口
                .apis(RequestHandlerSelectors.basePackage("com.item.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 建構api文檔的詳細資訊
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // 設定頁面标題
                .title("Spring Boot內建Swagger2接口總覽")
                // 設定接口描述
                .description("Swagger接口")
                // 設定聯系方式
                .contact(new Contact("測試swagger","http://localhost:8080/",""))
                // 設定版本
                .version("1.0")
                // 建構
                .build();
    }

}      

3、接口api寫法

我寫了一套的注釋方法,一目了然

package com.item.controller;

import com.item.model.Users;
import com.item.service.UsersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
@Api("使用者操作接口")
@RestController
@CrossOrigin
public class UsersController {
    @Autowired
    private UsersService usersService;

    /**
     * 擷取所有資訊
     * @return
     */
    @GetMapping("/GetInfoApi")
    @ApiOperation(value = "擷取資訊",notes = "沒啥留言的")
    public Object GetInfoApi(){
        List<Users> list=usersService.GetInfo();
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",list);
        return map;
    }

    @GetMapping("/GetName")
    @ApiOperation(value = "擷取資訊",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "nickName",required = true,paramType = "query",dataType = "String",value = "通過昵稱模糊查詢")
    })
    public Object GetName(HttpServletRequest request,Model model){
        String nickName = request.getParameter("nickName");
        List<Users> list=usersService.SelectName(nickName);
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",list);
        return map;
    }

    /**
     * 添加資訊
     * @param userName
     * @param pwd
     * @param nickName
     * @return
     */
    @PostMapping(value = "/UserAddInfoApi")
    @ApiOperation(value = "添加",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName",required = true,paramType = "query",dataType = "String",value = "使用者名"),
            @ApiImplicitParam(name = "pwd",required = true,paramType = "query",dataType = "String",value = "密碼"),
            @ApiImplicitParam(name = "nickName",required = true,paramType = "query",dataType = "String",value = "昵稱")
    })
    public Object UserAddInfoApi(String userName,String pwd,String nickName){
        HashMap<String,Object> map=new HashMap<String,Object>();
        if(
                StringUtils.isEmpty(userName)||
                StringUtils.isEmpty(pwd)||
                StringUtils.isEmpty(nickName)
        ){
            map.put("state",false);
            map.put("msg","參數不潤許為空");
            map.put("result","");
            return map;
        }
        usersService.UsersAddInfo(userName, pwd, nickName);
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }

    /**
     * 單個查詢
     * @param id
     * @return
     */
    @GetMapping("/UsersSelectById")
    @ApiOperation(value = "id查詢",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号")
    })
    public Object UsersSelectById(String id){
        Users users = usersService.UsersSelectById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",users);
        return map;
    }

    /**
     * 修改api
     * @param id
     * @param pwd
     * @return
     */
    @PostMapping(value = "/UserUpdateInfoApi")
    @ApiOperation(value = "添加",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号"),
            @ApiImplicitParam(name = "pwd",required = true,paramType = "query",dataType = "String",value = "密碼"),
    })
    public Object UserUpdateInfoApi(String id,String pwd){
        usersService.UsersUpdateInfo(pwd,Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }

    /**
     * 删除api
     * @param id
     * @return
     */
    @GetMapping(value = "/UsersDeleteById")
    @ApiOperation(value = "根據id删除",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号")
    })
    public Object UsersDeleteById(String id){
        usersService.UsersDeleteById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }
}      

4、啟動效果:【​​http://127.0.0.1:8088/swagger-ui.html​​】

這裡為了看着友善,我将服務路徑改為了【/】

# 服務路徑
server.servlet.context-path=/      
畢業季·大學最遺憾的事/沒有完成的事?

5、使用方法

畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?

POST的也類似

畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?

6、可能出現的異常總結:

1、SwaggerConfig的配置檔案中忘記寫注解,就2個注解:

@Configuration
@EnableSwagger2      

2、接口中的注解:

@Api("使用者操作接口")
@ApiOperation(value = "擷取資訊",notes = "沒啥留言的")
@ApiImplicitParams({
      @ApiImplicitParam(name = "nickName",required = true,paramType = "query",dataType = "String",value = "通過昵稱模糊查詢")
})      

3、沒有明确接口的通路類型,導緻出現一堆的同名不同通路類型的接口提示。

使用@GetMapping或者@PostMapping就可以解決此問題。

 springboot05、封裝結果集

不可能一直用map寫資料傳回,很麻煩的,那麼咱們就可以進行一次封裝此次使用。

目錄

​​springboot05、封裝結果集​​

​​建立【com.item.res】包​​

​​注意問題​​

編輯一個SUCCESS類和ERROR類,他們都有state、msg、result,那麼就建立一個公用的父類base。

建立【com.item.res】包

Base:

package com.item.res;

public class BASE {
    private boolean state;
    private String msg;
    private Object result;

    public BASE(boolean state, String msg, Object result) {
        this.state = state;
        this.msg = msg;
        this.result = result;
    }

    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }

    public String getMsg() {
        return msg;
    }

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

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }
}      

ERROR:

package com.item.res;

public class ERROR extends BASE {

    public ERROR(String msg, Object result) {
        super(false, msg, result);
    }
}      

SUCCESS:

package com.item.res;

public class SUCCESS extends BASE {
    public SUCCESS(Object result) {
        super(false, "操作成功", result);
    }
}      

傳回修改:

package com.item.controller;

import com.item.model.Users;
import com.item.res.ERROR;
import com.item.res.SUCCESS;
import com.item.service.UsersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
@Api("使用者操作接口")
@RestController
@CrossOrigin
public class UsersController {
    @Autowired
    private UsersService usersService;

    /**
     * 擷取所有資訊
     * @return
     */
    @GetMapping("/GetInfoApi")
    @ApiOperation(value = "擷取資訊",notes = "沒啥留言的")
    public Object GetInfoApi(){
        List<Users> list=usersService.GetInfo();
        return new SUCCESS(list);
    }

    @GetMapping("/GetName")
    @ApiOperation(value = "擷取資訊",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "nickName",required = true,paramType = "query",dataType = "String",value = "通過昵稱模糊查詢")
    })
    public Object GetName(HttpServletRequest request,Model model){
        String nickName = request.getParameter("nickName");
        List<Users> list=usersService.SelectName(nickName);
        return new SUCCESS(list);
    }

    /**
     * 添加資訊
     * @param userName
     * @param pwd
     * @param nickName
     * @return
     */
    @PostMapping(value = "/UserAddInfoApi")
    @ApiOperation(value = "添加",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName",required = true,paramType = "query",dataType = "String",value = "使用者名"),
            @ApiImplicitParam(name = "pwd",required = true,paramType = "query",dataType = "String",value = "密碼"),
            @ApiImplicitParam(name = "nickName",required = true,paramType = "query",dataType = "String",value = "昵稱")
    })
    public Object UserAddInfoApi(String userName,String pwd,String nickName){
        HashMap<String,Object> map=new HashMap<String,Object>();
        if(
                StringUtils.isEmpty(userName)||
                StringUtils.isEmpty(pwd)||
                StringUtils.isEmpty(nickName)
        ){
            return new ERROR("參數為空","參數錯誤");
        }
        usersService.UsersAddInfo(userName, pwd, nickName);
        return new SUCCESS("添加成功");
    }

    /**
     * 單個查詢
     * @param id
     * @return
     */
    @GetMapping("/UsersSelectById")
    @ApiOperation(value = "id查詢",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号")
    })
    public Object UsersSelectById(String id){
        Users users = usersService.UsersSelectById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result",users);
        return map;
    }

    /**
     * 修改api
     * @param id
     * @param pwd
     * @return
     */
    @PostMapping(value = "/UserUpdateInfoApi")
    @ApiOperation(value = "添加",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号"),
            @ApiImplicitParam(name = "pwd",required = true,paramType = "query",dataType = "String",value = "密碼"),
    })
    public Object UserUpdateInfoApi(String id,String pwd){
        usersService.UsersUpdateInfo(pwd,Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }

    /**
     * 删除api
     * @param id
     * @return
     */
    @GetMapping(value = "/UsersDeleteById")
    @ApiOperation(value = "根據id删除",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",required = true,paramType = "query",dataType = "String",value = "編号")
    })
    public Object UsersDeleteById(String id){
        usersService.UsersDeleteById(Integer.parseInt(id));
        HashMap<String,Object> map=new HashMap<String,Object>();
        map.put("state",true);
        map.put("msg","成功");
        map.put("result","");
        return map;
    }
}      

使用swagger通路測試傳回效果如下:

畢業季·大學最遺憾的事/沒有完成的事?

設定完成。 

注意問題:

每個人的習慣方式均不同,需要看看公司具體用什麼方式:

也可能是這樣傳回:

{

“code”: -9999,

“message”: “Invalid Request”,

“data”:{ }

}

注意:無論是【ERROR】還是【SUCCESS】他們的傳回結果都需要一緻,否則前端在處理的時候就會很麻煩,對是一套解析,錯又是一套解析,很麻煩。

例如:

正确傳回:

{

"state": true,

"message": "通路成功",

"data":

[
    {
      "id": 77,
      "userName": "子玉等于摸魚",
      "pwd": "074FD28EFF0F5ADEA071694061739E55",
      "nickName": "高大上,牛逼吼吼吼吼吼"
    }
  ]
}      

錯誤傳回:

{

"state": false,

"message": "通路失敗",

"data":"失敗"
}      

這就沒法玩了。。。。 會挨罵的。

避免層級過深的URI

/ 在url中表達層級,用于按實體關聯關系進行對象導航,一般根據id導航。

過深的導航容易導緻url膨脹,不易維護,如 GET /zoos/1/areas/3/animals/4,盡量使用查詢參數代替路勁中的實體導航,如GET /animals?zoo=1&area=3。

結果過濾,排序,搜尋

url最好越簡短越好,對結果過濾、排序、搜尋相關的功能都應該通過參數實作。

過濾:例如你想限制GET /tickets 的傳回結果:隻傳回那些open狀态的ticket, GET /tickets?state=open 這裡的state就是過濾參數。

排序:和過濾一樣,一個好的排序參數應該能夠描述排序規則,而不和業務相關。複雜的排序規則應該通過組合實作。排序參數通過 , 分隔,排序參數前加 - 表示降序排列。

 springboot06、log4j2日志配置

目錄

​​前言:​​

​​1、pom配置​​

​​2、log4j2-spring.xml配置檔案​​

​​3、在application.properties中引入log4j2的配置​​

​​4、log4j使用​​

前言:

日志接口(slf4j)

slf4j是對所有日志架構制定的一種規範、标準、接口,并不是一個架構的具體的實作,因為接口并不能獨立使用,需要和具體的日志架構實作配合使用(如log4j、logback)。

接口用于定制規範,可以有多個實作,使用時是面向接口的(導入的包都是slf4j的包而不是具體某個日志架構中的包),即直接和接口互動,不直接使用實作,是以可以任意的更換實作而不用更改代碼中的日志相關代碼。

日志實作(log4j、logback、log4j2)

Log4j:Apache的一個開源項目,可以控制日志資訊輸送的目的地是控制台、檔案、GUI元件等,可以控制每一條日志的輸出格式,這些可以通過一個配置檔案來靈活地進行配置,而不需要修改應用的代碼。雖然已經停止維護了,但目前絕大部分企業都是用的log4j。

LogBack:logback同樣是由log4j的作者設計完成的,擁有更好的特性,用來取代log4j的一個日志架構,是slf4j的原生實作。

Log4j2:Log4j2是log4j 1.x和logback的改進版,據說采用了一些新技術(無鎖異步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍,并解決了一些死鎖的bug,而且配置更加簡單靈活。

1、pom配置

<!-- log4j2所需要的配置 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion><!-- springboot預設是用logback的日志架構的 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId
        </exclusion>
    </exclusions>
</dependency>
<dependency> <!-- 引入log4j2依賴 -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>      

2、log4j2-spring.xml配置檔案

我精簡了配置,隻輸出到控制台。

<?xml version="1.0" encoding="UTF-8"?>
<!--日志級别以及優先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration後面的status,這個用于設定log4j2自身内部的資訊輸出,可以不設定,當設定成trace時,你會看到log4j2内部各種詳細輸出-->
<!--monitorInterval:Log4j能夠自動檢測修改配置 檔案和重新配置本身,設定間隔秒數, 不設定預設5s
-->
<Configuration status="debug">
    <!-- 配置日志資訊輸出 -->
    <Appenders>
        <!-- 輸出到控制台, target屬性一般為SYSTEM_OUT,也可以是 SYSTEM_ERR, -->
        <Console name="Console" target="SYSTEM_OUT">
            <!--配置日志資訊的格式 -->
            <PatternLayout pattern="%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <!-- 定義logger,隻有定義了logger并引入了appender,appender才會有效 -->
    <Loggers>
        <!-- 将業務dao接口所在的包填寫進去,并用在控制台和檔案中輸出 此處配置的是mybatis的輸出 level記得設定為debug -->
        <logger name="com.item.dao.*" level="debug" additivity="false">
            <AppenderRef ref="Console" />
        </logger>
        <Root level="info">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>      

3、在application.properties中引入log4j2的配置

# 引入log4j
logging.config=classpath:log4j2-spring.xml
# 控制台列印sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl      

4、log4j使用

包:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;      

聲明:

private final Logger log = LoggerFactory.getLogger(this.getClass());      

使用:

log.info("通路模糊查詢");      

效果:

畢業季·大學最遺憾的事/沒有完成的事?

 springboot07、task定時任務

定時任務的概述

在項目中開發定時任務應該是一種比較常見的需求,在Java中開發定時任務主要有三種方案:一是使用JDK自帶的Timer,二是使用第三方元件Quartz',三是使用Spring Task。

Timer是JDK自帶的定時任務工具,其簡單易用,但是對于複雜的定時規則無法滿足,在實際項目開發中也很少使用到,Quartz功能強大,但是使用起來相對笨重,而Spring Task則具備了前兩者之間的優點,使用起來簡單,除Spring 相關的包外不需要額外的包,而且支援注解和配置檔案兩種形式。

是以咱們這裡使用springboot的task,相對友善、快捷、高效。

1、啟動類上添加@EnableScheduling

package com.item;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;

@MapperScan("com.item.dao")
@SpringBootApplication
@EnableScheduling
public class Action extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Action.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Action.class,args);
    }
}      

2、建立測試包【com.item.task】

2.1fixedRate定時

package com.item.task;

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

import java.util.Date;

/**
 * 任務類
 */
@Component
public class TaskTest {
    /**
     * 每2秒執行1次
     */
    @Scheduled(fixedRate = 2000)
    public void fixedRateMethod() throws InterruptedException {
        System.out.println("task-fixedRate,每2秒執行1此:" + new Date());
        Thread.sleep(1000);
    }
}      

2.2cron定時

package com.item.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

/**
 * 任務類
 */
@Component
public class TaskCron {
    private SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 在每分鐘的00秒執行
     */
    @Scheduled(cron = "0 * * * * ?")
    public void oneMin() throws InterruptedException {
        System.out.println("cron每分鐘執行:" + simpleDateFormat.format(new Date()));
    }
    /**
     * 每5秒執行
     */
    @Scheduled(cron = "*/5 * * * * ?")
    public void fiveS() throws InterruptedException {
        System.out.println("cron每5秒執行:" + simpleDateFormat.format(new Date()));
    }
}      

Cron表達式

cronExpression表達式有至少6個由空格分隔的時間元素,從左往右,這些元素的定義如下:

秒,分,時,月份中的日期,月份,星期,年份

字段 允許值 允許的特殊字元 

秒 0-59 , - * / 

分 0-59 , - * / 

小時 0-23 , - * / 

日期 1-31 , - * ? / L W C 

月份 1-12 或者 JAN-DEC , - * / 

星期 1-7 或者 SUN-SAT , - * ? / L C # 

年(可選) 留白, 1970-2099 , - * / 

* 表示所有值; 

? 表示未說明的值,即不關心它為何值; 

- 表示一個指定的範圍; 

, 表示附加一個可能值; 

/ 符号前表示開始時間,符号後表示每次遞增的值; 

常用定時:

每隔5秒執行一次任務:  "*/5 * * * * ?"

每隔1分鐘執行一次任務:  "0 */1 * * * ?"

每天23點執行一次任務:  "0 0 23 * * ?"

每天淩晨1點執行一次任務:  "0 0 1 * * ?"

每月1号淩晨1點執行一次任務:  "0 0 1 1 * ?"

每月1号淩晨2點執行一次任務:  "0 0 2 1 * ? *"

每月最後一天23點執行一次任務:  "0 0 23 L * ?"

每周星期天淩晨1點執行一次任務:  "0 0 1 ? * L"

每隔5秒執行一次任務:  "*/5 * * * * ?"
 
每隔1分鐘執行一次任務:  "0 */1 * * * ?"
 
每天23點執行一次任務:  "0 0 23 * * ?"
 
每天淩晨1點執行一次任務:  "0 0 1 * * ?"
 
每月1号淩晨1點執行一次任務:  "0 0 1 1 * ?"
 
每月1号淩晨2點執行一次任務:  "0 0 2 1 * ? *"
 
每月最後一天23點執行一次任務:  "0 0 23 L * ?"
 
每周星期天淩晨1點執行一次任務:  "0 0 1 ? * L"      

效果:

畢業季·大學最遺憾的事/沒有完成的事?

springboot08、攔截器HandlerInterceptor

前言

攔截器這個名詞定義的非常形象,就像飛彈要攻擊目标的時候,可能會被先進的反導系統攔截,此處的反導系統就是一種攔截器。

我們開發的應用,對外暴露的是控制器中定義的 API 方法,我們可以在 API 方法的外圍放置攔截器,所有對 API 的通路都可以通過攔截器進行過濾。

OK,那麼這樣的攔截有什麼意義嗎,其實已經很明顯了,反導系統可以保護目标的安全并識别對目标的攻擊行為。同理,攔截器可以跟蹤對應用的通路行為,對合法通路行為予以放行,對非法通路行為予以拒絕。怎麼樣,是不是很牛,接下來咱們就在 Spring Boot 項目中具體實作下。

1、建立攔截器【com.item.handler】

通過【request】可以擷取任何值

package com.item.handler;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 自定義攔截器類
 */
public class MyInterceptor implements HandlerInterceptor {// 實作HandlerInterceptor接口
  /**
   * (1) preHandle方法是進行處理器攔截用的,顧名思義,該方法将在Controller處理之前進行調用。
   */
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    System.out.println(new Date() + "--preHandle:" + request.getRequestURL());
    StringBuffer url = request.getRequestURL();
    if(url.substring(url.lastIndexOf("/")+1,url.length()).equals("GetName")){
      System.out.println("------模糊查詢方法------");
      String nickName = request.getParameter("nickName");
      System.out.println("擷取的是nickName:"+nickName+",我可以根據擷取的值判斷是否是sql注入等操作");
    }
    return true;
  }

  /**
   * 這個方法隻會在目前這個Interceptor的preHandle方法傳回值為true的時候才會執行。
   */
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {
    System.out.println(new Date() + "--postHandle:" + request.getRequestURL());
  }

  /**
   * 該方法将在postHandle請求完成之後,也就是DispatcherServlet渲染了視圖執行
   */
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
    System.out.println(new Date() + "--afterCompletion:" + request.getRequestURL());
  }
}      

在上面的執行個體中,我們定義了一個攔截器類 MyInterceptor ,通過實作 HandlerInterceptor 接口,該類具備了攔截器的功能。

MyInterceptor 中的方法執行順序為 preHandle – Controller 方法 – postHandle – afterCompletion ,是以攔截器實際上可以對 Controller 方法執行前後進行攔截監控。

最後還有一個非常重要的注意點, preHandle 需要傳回布爾類型的值。 preHandle 傳回 true 時,對控制器方法的請求才能到達控制器,繼而到達 postHandle 和 afterCompletion 方法;如果 preHandle 傳回 false ,後面的方法都不會執行。

2、生效配置【com.item.handler】内建立【WebConfig】

如果想讓配置器生效,還需要通過配置類進行相應配置。

package com.item.handler;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Web配置類
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
  /**
   * 添加Web項目的攔截器
   */
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    // 對所有通路路徑,都通過MyInterceptor類型的攔截器進行攔截
    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
  }
}      

3、攔截器效果: 

畢業季·大學最遺憾的事/沒有完成的事?

4、攔截器作用

主要完成請求參數的解析、将頁面表單參數賦給值棧中相應屬性、執行功能檢驗、程式異常調試等工作,例如:登入校驗、Token驗證等。

springboot09、監控

前言

因為公司開發的項目多、為客戶部署的項目執行個體多。工作中我們都會經常遇到,由于某個客戶的項目突然無法通路,一堆研發、售後部門的同僚火急火燎處理問題的場景。

  • 能夠有一個界面,監控所有關注的項目執行個體運作狀态。
  • 對于某個項目執行個體來說,可以監控該執行個體的各項運作參數,例如記憶體占用情況、磁盤使用情況、資料庫連接配接情況。

利用 Spring Boot Admin 實作可視化監控,此時至少需要兩個項目執行個體,一個是監控的管理端,一個是被監控的用戶端。

注:會與swagger沖突。這個功能是在上線後使用,是以注意關閉swagger。

目錄

​​前言​​

​​1、pom配置​​

​​2、啟動項配置​​

​​3、通路首頁​​

​​4、用戶端pom依賴:​​

​​5、修改用戶端配置​​

1、pom配置

<!-- Spring Boot Admin 管理端依賴項 -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.2.3</version>
</dependency>      

2、啟動項配置

package com.item;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;

@MapperScan("com.item.dao")
@SpringBootApplication
@EnableScheduling
@EnableAdminServer
public class Action extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Action.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(Action.class,args);
    }
}      

3、通路首頁

根據端口号通路就行【​​http://127.0.0.1:8088/​​】

畢業季·大學最遺憾的事/沒有完成的事?

4、用戶端pom依賴:

<!-- Spring Boot Admin監控用戶端依賴 -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.2.3</version>
</dependency>      

5、修改用戶端配置

# 修改端口号避免沖突
server.port=8081
# 配置監控管理端位址
spring.boot.admin.client.url=http://127.0.0.1:8088
# 用戶端的名稱,用于區分不同的用戶端
spring.boot.admin.client.instance.name=CLIENT1
# 配置用戶端展示哪些資訊,*表示展示全部資訊
management.endpoints.web.exposure.include=*      
畢業季·大學最遺憾的事/沒有完成的事?

啟動client_test,可以看到應用是1了,可以多啟動幾個,都能看到

畢業季·大學最遺憾的事/沒有完成的事?

點選進去:

畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?

多弄幾個效果還是很明顯的。

 springboot10、AOP

前言

Spring 最重要的兩個功能,就是依賴注入和面向切面程式設計(AOP)。

AOP 為我們提供了處理問題的全局化視角,使用得當可以極大提高程式設計效率。

Spring Boot 中使用 AOP 與 Spring 中使用 AOP 幾乎沒有什麼差別,隻是建議盡量使用 Java 配置代替 XML 配置。

目錄

​​編輯springboot09、AOP​​

​​前言​​

​​1、pom依賴​​

​​2、AOP控制器【com.item.aop】​​

​​3、測試apo效果​​

​​4、使用 AOP 監控性能​​

1、pom依賴

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

2、AOP控制器【com.item.aop】

package com.item.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * 日志切面
 */
@Component
@Aspect // 标注為切面
public class LogAspect {
  private Logger logger = LoggerFactory.getLogger(this.getClass());

  // 切入點表達式,表示切入點為控制器包中的所有方法
  @Pointcut("within(com.item.controller..*)")
  public void LogAspect() {
  }

  // 切入點之前執行
  @Before("LogAspect()")
  public void doBefore(JoinPoint joinPoint) {
    logger.info("通路時間:{}--通路接口:{}", new Date(), joinPoint.getSignature());
  }
}      

3、測試apo效果

可以根據傳回的路徑進行接口控制

畢業季·大學最遺憾的事/沒有完成的事?

4、使用 AOP 監控性能

在研發項目的性能測試階段,或者項目部署後,我們會希望檢視服務層方法執行的時間。以便精準的了解項目中哪些服務方法執行速度慢,後續可以針對性的進行性能優化。

此時我們就可以使用 AOP 的環繞通知,監控服務方法的執行時間。

package com.item.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 服務層方法切面
 */
@Component
@Aspect // 标注為切面
public class ServiceAspect {
  private Logger logger = LoggerFactory.getLogger(this.getClass());

  // 切入點表達式,表示切入點為服務層包中的所有方法
  @Pointcut("within(com.item.controller..*)")
  public void ServiceAspect() {
  }

  @Around("ServiceAspect()") // 環繞通知
  public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();// 記錄開始時間
    Object result = joinPoint.proceed();
    logger.info("接口層方法:{}--執行時間:{}毫秒", joinPoint.getSignature(), System.currentTimeMillis() - startTime);
    return result;
  }
}      
畢業季·大學最遺憾的事/沒有完成的事?

springboot11、redis

前言

redis可以說是現在最火的非關系型資料庫,主要是它處理資料的能力是真的很強。就說win環境的處理能力一般的機器也能在每秒3萬次以上,已經很厲害了。我們一般的幾萬使用者的APP根本不需要叢集,一個Redis即可搞定幾乎所有的小規模并發性問題了。

資源位址:​​redis服務(windows版)&amp;redis可視化工具.rar_asp.netcoreredis-.Net文檔類資源-CSDN下載下傳​​

目錄

​​1、pom依賴​​

​​2、配置聲明(application.properties中)​​

​​3、編寫配置檔案【com.item.redis】​​

​​4、操作提示​​

​​5、RedisBase編碼(隻包含字元串處理)​​

​​6、建立測試接口【com.item.controller】内​​

​​7、編寫redis層級【com.item.Base】​​

​​8、啟動測試http://127.0.0.1:8088/swagger-ui.htm​​

1、pom依賴

<!-- Redis 依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.1.0</version>
</dependency>      

2、配置聲明(application.properties中)

#---------------------------------
# Redis資料庫索引(預設為0)
spring.redis.database=0 
# Redis伺服器位址
spring.redis.host=localhost
# Redis伺服器連接配接端口
spring.redis.port=6379 
# Redis伺服器連接配接密碼(預設為空)
spring.redis.password=
#連接配接池最大連接配接數(使用負值表示沒有限制)
spring.redis.pool.max-active=8 
# 連接配接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1 
# 連接配接池中的最大空閑連接配接
spring.redis.pool.max-idle=8 
# 連接配接池中的最小空閑連接配接
spring.redis.pool.min-idle=0 
# 連接配接逾時時間(毫秒)
spring.redis.timeout=0
#---------------------------------      

3、編寫配置檔案【com.item.redis】

中間有輸出語句就是為了表現配置成功,可以删掉。

package com.item.redis;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 完成對Redis整合的配置
 */
@Configuration
public class RedisConfig {
    /**
     * 1.建立 JedisPoolConfig 對象。在該對象中完成一些連結池配置
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.jedis.pool")
    public JedisPoolConfig JedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        System.out.println("redis預設值:" + config.getMaxIdle());
        System.out.println("redis預設值:" + config.getMinIdle());
        System.out.println("redis預設值:" + config.getMaxTotal());
        return config;
    }

    /**
     * 2.建立 JedisConnectionFactory 對象,配置Redis連接配接屬性
     *
     * @param config
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis")
    public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig config) {
        System.out.println("redis配置完畢:" + config.getMaxIdle());
        System.out.println("redis配置完畢:" + config.getMinIdle());
        System.out.println("redis配置完畢:" + config.getMaxTotal());
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setPoolConfig(config);//關聯連接配接池的配置對象
        return factory;
    }

    /**
     * 3.建立RedisTemplate,用于執行Redis操作的方法
     *
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //關聯JedisConnectionFactory
        template.setConnectionFactory(factory);
        //為key序列化器
        template.setKeySerializer(new StringRedisSerializer());
        //為value設定序列化器
        template.setValueSerializer(new StringRedisSerializer());

        return template;
    }

}      

4、操作提示

//通過依賴注入使用redis
@Autowired
private RedisTemplate redisTemplate;

redisTemplate.opsForValue();//操作字元串
redisTemplate.opsForHash();//操作hash 
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set      

5、RedisBase編碼(隻包含字元串處理)

package com.item.redis;

import com.item.Base.RedisUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;


public class RedisBase {
    /**
     * 傳回的是Object
     */
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 傳回String
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 添加值
     * @param key
     * @param value
     * @return
     */
    public boolean redisSet(String key,String value){
        key= RedisUrl.url+key;
        stringRedisTemplate.opsForValue().set(key,value);
        String o = stringRedisTemplate.opsForValue().get(key);
        return o==null?false:true;
    }

    /**
     * 存儲帶倒計時的字元串
     * @param key
     * @param value
     * @param second
     * @return
     */
    public boolean redisSetTime(String key,String value,long second){
        key= RedisUrl.url+key;
        stringRedisTemplate.opsForValue().set(key,value,second);
        String s = stringRedisTemplate.opsForValue().get(key);
        return s==null?false:true;
    }

    /**
     * 擷取key的value
     * @param key
     * @return
     */
    public String redisGet(String key){
        key= RedisUrl.url+key;
        return stringRedisTemplate.opsForValue().get(key);
    }



}      

6、建立測試接口【com.item.controller】内

package com.item.controller;


import com.item.model.Users;
import com.item.redis.RedisBase;
import com.item.res.SUCCESS;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api("使用者操作接口")
@RestController
@CrossOrigin
@RequestMapping("Redis/")
public class RedisController extends RedisBase {
    /**
     * 測試Redis添加
     */
    @GetMapping("SetRedis")
    @ApiOperation(value = "添加key_value",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key",required = true,paramType = "query",dataType = "String",value = "redis_key"),
            @ApiImplicitParam(name = "value",required = true,paramType = "query",dataType = "String",value = "redis_value")
    })
    public Object testRedisSet(String key,String value){
        redisSet(key,value);
        return new SUCCESS("寫入成功");
    }

    /**
     * 測試Redis查詢
     */
    @GetMapping("GetRedis")
    @ApiOperation(value = "擷取key資訊",notes = "沒啥留言的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key",required = true,paramType = "query",dataType = "String",value = "redis_key")
    })
    public Object testRedisGet(String key){
        return new SUCCESS(redisGet(key));
    }

}      

7、編寫redis層級【com.item.Base】

package com.item.Base;

public class RedisUrl {
    public static final String url="demo:infos:";
}      

8、啟動測試​​http://127.0.0.1:8088/swagger-ui.htm​​

畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?
畢業季·大學最遺憾的事/沒有完成的事?

能寫入,能查詢,沒問題。