idea創建springBoot項目


v1.0.0

最普通SpringWeb版本,只有一空的項目

如圖,如果我們勾選Spring Web了,意味着這是一個springWeb項目,畢竟Spring又不是只可以做web端。
我們來對比下,勾選與否的區別。

勾選嗎? resources目錄 pom.xml
- spring-boot-starter
多出空文件夾templates、static spring-boot-starter-web

也就是說,springWeb項目會多出一些存放頁面相關的文件結構,並且依賴也升級到spring-boot-starter-web。
spring-boot-starter-web包含spring-boot-starter,並再此基礎上多出了一些web相關的其它模塊。

1.0.1

增加了如下功能,
逆向代碼生成

pom變化

相比v1.0.0最基本得空框架而言,這需在pom增加如下依賴:

<!--這是逆向工程所所需依賴,一共5個包 start-->
<dependency><!-- 鏈接數據庫驅動: 在idea初始化項目中,選了sql>mysql drive就會有此項,mybatis和逆向都需要 -->
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency> <!-- mybatis-plus(springBoot版)-->
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.0</version>
</dependency>
<dependency><!--mybatis-plus代碼生成器,3.5之后獨立出來了(這個生成代碼后就可以刪除了,畢竟只用一次)-->
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency> <!--模板引擎:使用代碼生成器時必須要的模板引擎依賴。-->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency><!--SpringFox 3.0.0(swagger2支持):這個可選。逆向工具是否開啟,自己是否需要2個條件決定  https://blog.csdn.net/fygkchina/article/details/109316824 start-->
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

解釋一下:
mysql-connector-java 是mybatis和mybatis generator都要用到的連接數據庫驅動包。
mybatis-plus 就是mybatis的升級版本,是一款優秀的基於java的持久層框架。業務涉及到操作數據庫or逆向生成都需要此包。
mybatis-plus-generator 逆向代碼生成工具包,生成完代碼后,就可以刪掉它了。
spring-boot-starter-freemarker 后端得模板語言包,這個如果你用了逆向生成,則必須要使用這個包。 至於逆向為啥要用模板,我也不知道,沒有百度到。
springfox-boot-starter swagger2包,用來生成接口api工具的 逆向生成配置如果開啟此功能,則需要下載此依賴,可選。

swagger2處理

swagger2因為升級到了3.0.0,所以和現有的spring2.6.x不兼容,Failed to start bean 'documentationPluginsBootstrapper'
百度到一些 資料 , 需要做額外適配, application.yml文件增加如下代碼:

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

然后再啟動類上增加@EnableOpenApi注解

@EnableOpenApi
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SbDemoApplication.class, args);
    }
}

mybatis generator處理

逆向工程時候,需要增加一個逆向配置類 utils\CodeGenerator.java

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;

public class CodeGenerator {
    public static String projectPath = System.getProperty("user.dir");
    public static String dateBaseUrl = "jdbc:mysql://xxx:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false";
    public static void main(String[] args) {
        FastAutoGenerator.create(dateBaseUrl, "root", "*****")
                .globalConfig(builder -> {
                    builder.author("丁少華") // 設置作者
                            .enableSwagger() // 開啟 swagger 模式(非必須,如果開啟,需要在依賴添加swagger以及啟動類加注解)
                            .fileOverride() // 覆蓋已生成文件
                            .outputDir(projectPath+"/src/main/java/"); // 指定輸出目錄
                })
                .packageConfig(builder -> {
                    builder.parent("com.dshvv.demo") // 設置父包名 我這里沒有
                            .moduleName("") // 設置父包模塊名 我這里沒有
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath+"/src/main/resources/mapper/")); // 設置mapperXml生成路徑
                })
                .strategyConfig(builder -> {
                    builder.addInclude("blog") // 設置需要生成的表名
                            .addTablePrefix(); // 設置過濾表前綴. 我的表沒有前綴
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默認的是Velocity引擎模板
                .execute();
    }
}

然后運行這個類的main方法,代碼就生成了

mybatis配置

如果此時直接啟動項目,則會報錯,提示缺少數據庫配置。原來mybatis generator的配置文件和mybatis不能公用
此時在application.yml文件配置一下數據庫就行:

spring:
  datasource:  # 這個配置是給mybatis用的,不是給mybatis-generator用的
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xxx:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: 'xxx'

此時在啟動項目即可。
不過,可能還會發現如下報錯Unsatisfied dependency expressed through field 'baseMapper'
意思是掃描不到mapper文件,我們在啟動類上指定掃描路徑的注解@MapperScan("com.dshvv.sbdemo.mapper")即可

@MapperScan("com.dshvv.sbdemo.mapper")
@SpringBootApplication
public class SbDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SbDemoApplication.class, args);
    }
}

freemarker的配置

1、在application.yml文件增加如下配置:

spring:
  freemarker:
    enabled: true
    charset: UTF-8 #編碼
    suffix: .html #后綴名
    content-type: text/html
    prefer-file-system-access: true
    template-loader-path: classpath:/templates/ #模板位置

2、resources\templates\index.html新增一個頁面,內容隨意
3、新增一個控制器類,寫入路由

package com.dshvv.demo.controller;

import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@RequestMapping
@RestController
public class OtherController {
  @ApiOperation(value = "后端服務起始頁", notes = "用於用查看后端服務是否啟動", produces = "text/html")
  @GetMapping("/")
  public ModelAndView Home() {
    return new ModelAndView("index");
  }
}

重啟,即可訪問

controller優化

后端返回格式是統一的,如有status、data、msg等等,所以我們需要做一個規范。
1、pom里增加一個依賴

<!--Json序列化工具,編寫JsonResult類用到了-->
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-commons</artifactId>
</dependency>

2、新建一個格式化返回值的類
\utils\JsonResult.java內容如下:

package com.dshvv.demo.utils;

import org.junit.platform.commons.util.ToStringBuilder;
import java.io.Serializable;
import java.util.Objects;

public class JsonResult implements Serializable {

    private static final long serialVersionUID = 5598308977637490090L;

    private int status;

    private String message;

    private Object data;

    public int getStatus() {
        return status;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

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

    public Object getData() {
        return data;
    }

    public static JsonResult success() {
        return success(null);
    }

    public static JsonResult success(Object data) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setStatus(200);
        jsonResult.setMessage("SUCCESS");
        if (data != null) {
            jsonResult.setData(data);
        }
        return jsonResult;
    }

    public static JsonResult failed() {
        return failed("FAILED");
    }

    public static JsonResult failed(String message) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setStatus(500);
        jsonResult.setMessage(message);
        return jsonResult;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof JsonResult)) {
            return false;
        }
        JsonResult result = (JsonResult) o;
        return status == result.status &&
                Objects.equals(message, result.message) &&
                Objects.equals(data, result.data);
    }

    @Override
    public int hashCode() {
        return Objects.hash(status, message, data);
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this)
                .append("status", status)
                .append("message", message)
                .append("data", data)
                .toString();
    }

}

3、如何使用?
建一個路由,嘗試使用

package com.dshvv.demo.controller;

import com.dshvv.demo.utils.JsonResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@RequestMapping
@RestController
public class OtherController {
  @ApiOperation(value = "測試接口", notes = "用於測試后台是否可被訪問", produces = "application/json")
  @GetMapping("/test")
  public JsonResult Login() {
    return JsonResult.success();
  }
}

重啟訪問即可

v1.0.2

增加登陸授權

添加依賴

采取的是Sa-Token 權限認證.

<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.28.0</version>
</dependency>

如果用默認推薦的給每個控制器方法添加鑒權功能,顯然不合適,所以我們通過全局攔截器來處理整個項目的
增加一個攔截器文件interceptor/SaTokenConfigure.java

package com.dshvv.blogserver.interceptor;

import cn.dev33.satoken.interceptor.SaRouteInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * <p>
 *  SaToken全局攔截器,校驗登錄
 *  參考 https://www.cnblogs.com/yunchu/p/14304900.html、
 *  參考 https://www.cnblogs.com/yunchu/p/14362461.html (重點)
 * </p>
 *
 * @author 丁少華
 * @since 2022-01-07
 */

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注冊攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊Sa-Token的路由攔截器
        registry.addInterceptor(new SaRouteInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login","/reg")
                .excludePathPatterns("/swagger**/**", "/v3/**", "/doc.html","/webjars/**"); //排除swagger設置
    }
}

對SaToken插件進行配置

其實這個是非必需,因為不配置都有默認值,但是為了為了學習,和實驗,還是配置一下吧,
application.yml增加如下配置

sa-token:
  token-name: satoken # token名稱 (同時也是cookie名稱)
  timeout: 5 # token有效期,單位s 默認30天, -1代表永不過期

驗證配置結果

如何看SaToken是否生效呢?
當然是寫一個控制器,啟動項目,用postMan測試接口啦。

package com.dshvv.blogserver.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.dshvv.blogserver.service.IUserService;
import com.dshvv.blogserver.utils.JsonResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;

@RequestMapping
@RestController
public class OtherController {
    @ApiOperation(value = "測試接口", notes = "用於測試后台是否可被訪問", produces = "application/json")
    @GetMapping("/test")
    public JsonResult doTest() {
        return JsonResult.success();
    }

    // 登錄
    @ApiOperation(value = "登錄接口", notes = "用於用戶登錄", produces = "application/json")
    @PostMapping("/login")
    public SaResult doLogin(@RequestBody Map<String, Object> user) {
        String name = (String) user.get("name");
        String pwd = (String) user.get("pwd");
        // 此處僅作模擬示例,真實項目需要從數據庫中查詢數據進行比對
        if("yan".equals(name) && "yh@0020".equals(pwd)) {
            StpUtil.login(10001);
            return SaResult.ok("登錄成功");
        }
        return SaResult.error("登錄失敗");
    }
}

除此之外在啟動項目的時候,啟動類可以打印輸出當前SaToken正在使用的配置項,用來確認application.yml配置是否生效

@SpringBootApplication
public class DemoServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoServerApplication.class, args);
        System.out.println("啟動成功:Sa-Token配置如下:" + SaManager.getConfig());
    }
}

v1.0.3

增加全局跨域處理
同樣,偷懶也不想用@CrossOrigin一個個的去注解類來解決跨域,所以同樣的用攔截器
增加處理跨域的全局攔截器類interceptor/CorsConfigurer.java

package com.dshvv.blogserver.interceptor;

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

/**
 * <p>
 *  跨域處理 
 *  參考: http://www.telami.cn/2019/springboot-resolve-cors/
 * </p>
 *
 * @author 丁少華
 * @since 2022-01-07
 */
@Configuration
public class CorsConfigurer implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

v1.0.4

全局異常處理
這個很實用,比如登陸超時啊啥的
新增處理異常類exception/GlobalExceptionHandler.java

package com.dshvv.blogserver.exception;

import cn.dev33.satoken.exception.NotLoginException;
import com.dshvv.blogserver.utils.JsonResult;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLIntegrityConstraintViolationException;

//ExceptionHandler的處理順序是由異常匹配度來決定的,且我們也無法通過其他途徑指定順序(其實也沒有必要)

/**
 * 全局異常處理器
 */
@ControllerAdvice // @ControllerAdvice將當前類標識為異常處理的組件
@RestController
public class GlobalExceptionHandler {

    @ExceptionHandler(NotLoginException.class)
    @ResponseStatus(HttpStatus.OK)
    protected JsonResult handleException(HttpServletRequest request, NotLoginException ex) {
        JsonResult result = new JsonResult();
        result.setCode(401);
        result.setMsg("用戶未登錄或已過期,請重新登錄");
        return result;
    }

    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonResult handleException(HttpServletRequest req, DuplicateKeyException ex) {
        JsonResult result = new JsonResult();
        result.setCode(1);
        result.setMsg("郵箱已經被注冊");
        return result;
    }

    @ExceptionHandler(Exception.class)  // @ExceptionHandler用於設置所標識方法處理的異常 參數代表異常類型
    @ResponseStatus(HttpStatus.OK)
    public JsonResult handleException(HttpServletRequest req, Exception ex) {
        ex.printStackTrace();
        JsonResult result = new JsonResult();
        result.setCode(1);
        result.setMsg("系統錯誤");
        return result;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM