建站四部曲之後端介面篇(SpringBoot+上線)

張風捷特烈發表於2018-12-11
本系列分為四篇:

零、前言

本系列為了總結一下手上的知識,致敬我的2018
本篇的重點在於:搭建一個後端的url介面服務,並執行到伺服器上
本篇總結的技術點:SpringBootmybaits整合mysql簡單操作ResetFul介面檔案上傳跨域處理


一、SpringBoot初始搭建

1、Idea中新建SpringBoot專案(分包如下):

按哪個鍵新建專案,這裡就不廢話了,新手請轉到:SpringBoot-01-之初體驗

專案分包.png


2、pom.xml新增依賴:
<dependencies>
    <!--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>1.3.2</version>
    </dependency>
    <!--web依賴-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
複製程式碼

3.配置application.properties(或application.yml,我喜歡後者)

注意修改的:資料庫名mycode,使用者名稱:username: XXXX,密碼:password: XXXX

spring:
    datasource:
      url: jdbc:mysql://localhost:3306/mycode?useSSL=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&URIEncoding="UTF-8"
      username: root
      password: ****
      driver-class-name: com.mysql.jdbc.Driver

#坑點0 配置mybatis的xml位置
mybatis:
  mapper-locations: classpath:mapper/*.xml
複製程式碼

mark一下踩的兩個坑:

1).好像是MySQL時區的問題,導致連線異常:
>配置時資料庫連線引數新增:`&serverTimezone=Asia/Shanghai`可解決

2).一開始用get測試是否插入成功,但是報錯了,仔細看了看,貌似是從中文的地方:
>配置時資料庫連線引數新增:`&URIEncoding="UTF-8"`
複製程式碼

二、MySQL的簡單總結

1、建庫建表
1).確定想要的單體
{
    "id":"1"
    "type": "繪圖相關",
    "name": "Android關於Canvas你所知道的和不知道的一切",
    "localPath":"I:\Java\Android\Unit\C\app\src\main\java\com\toly1994\c\view\CanvasView.java",
    "jianshuUrl":"https://www.jianshu.com/p/4bc05f646bfe",
    "juejinUrl":"https://juejin.im/post/5be29aa2e51d45228170ff33",
    "imgUrl":"域名:埠/android/Android關於Canvas你所知道的和不知道的一切.png",
    "createTime":"2018-11-05"
}
複製程式碼

2).建立資料庫mycode和表android
//建立資料庫
CREATE DATABASE mycode;
USE mycode;
//建立表
CREATE TABLE android (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(8) NOT NULL,
name VARCHAR(32) NOT NULL,
localPath VARCHAR(120) NOT NULL,
jianshuUrl VARCHAR(120) NOT NULL,
juejinUrl VARCHAR(120) NOT NULL,
imgUrl VARCHAR(120) NOT NULL,
createTime DATE NOT NULL
);
複製程式碼

建立資料庫成功.png


3).為了總結一下聯合查詢,建立表type
CREATE TABLE type(
   id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
   type_idx  VARCHAR(4)   NOT NULL,
   type  VARCHAR(48)  NOT NULL
 );
複製程式碼
4).插入型別資料:
INSERT INTO type(type_idx, type)
VALUES('ABCS', '四大元件'), ('C', '繪圖相關'), ('D', '自定義控制元件'),
('F', 'Fragment'), ('G', '開源計劃'), ('V', '原生View'),
('MD', '材料設計'), ('L', '底層核心'), ('M', '多媒體相關'),
('N', '網路相關'), ('O', '三方框架'), ('P', '手機裝置相關'),
('S', '資料存讀相關'), ('T', '紛雜小技術');
複製程式碼

type.png


2.MySQL語句的簡單回顧
-->插入資料:
insert into android(type,name,localPath,jianshuUrl,juejinUrl,imgUrl,createTime)
values (XX,XX,XX,XX,XX,XX,XX)

-->更新資料:
UPDATE android
SET type=XX,name=XX,localPath=XX,jianshuUrl=XX,juejinUrl=XX,imgUrl=XX,createTime=XX
WHERE id=XX

-->查詢所有+INNER JOIN
<select id="findALL" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx;
</select>

-->根據id查詢
SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
INNER JOIN type AS t ON a.type = t.type_idx
WHERE a.id=XX

-->根據type查詢
SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
INNER JOIN type AS t ON a.type = t.type_idx
 WHERE a.type=XX;


-->根據name部分字元查詢
SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
INNER JOIN type AS t ON a.type = t.type_idx
WHERE name like '%XX%';

-->根據id刪除資料
DELETE FROM android
WHERE id=#{id}
複製程式碼

三、書寫流程+插入測試:

1.檔案簡介

初級搭建.png

1.AndroidProjectApplication.java 啟動檔案,坑點在加掃包範圍  
2.application.yml 配置檔案
3.Note.xml 通過sql語句運算元據庫對映出實體類返給dao
4.NoteDao.java 資料庫操作介面
5.NoteService.java 根據業務邏輯對dao返回的資料進行一定加工
6.Note.java 實體類,用於承接資料庫中的資料
7.NoteController.java 核心操作層,生成可訪問的url介面,向外暴露
複製程式碼

下面以插入資料來演示一下操作流程


2.建立實體類:toly1994.com.android_project.bean.Note.java
public class Note {
    private int id;//id
    private String type;//型別
    private String name;//名稱
    private String localPath;//路徑
    private String jianshuUrl;//簡書地址
    private String juejinUrl;//掘金地址
    private String imgUrl;//掘金地址
    private String createTime;//建立時間
    //構造方法,get、set、toString略
}
複製程式碼

3.對映xml:mapper/Note.xml

根據規範,在相應的位置寫出sql語句就可以了
其中#{type}代表dao中方法傳入的引數

<?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">
<!--坑點2:名稱空間指向對應dao類名-->
<mapper namespace="toly1994.com.android_project.dao.NoteDao">
    <!--坑點3:id為dao中相應方法名-->
    <insert id="insert">
      insert into android(type,name,localPath,jianshuUrl,juejinUrl,imgUrl,createTime)
      values (#{type},#{name},#{localPath},#{jianshuUrl},#{juejinUrl},#{imgUrl},#{createTime})
    </insert>
</mapper>

複製程式碼

4.資料庫操作:toly1994.com.android_project.dao.NoteDao
/**
 * 作者:張風捷特烈
 * 時間:2018/11/19 0019:13:27
 * 郵箱:1981462002@qq.com
 * 說明:dao層---資料庫操作
 */
public interface NoteDao {
    //坑點1 java沒有儲存形參的記錄,所以多引數使用者@Param("name")起名字,不然無法識別
    int insert(@Param("type") String type,
               @Param("name") String name,
               @Param("localPath") String localPath,
               @Param("jianshuUrl") String jianshuUrl,
               @Param("juejinUrl") String juejinUrl,
               @Param("imgUrl") String imgUrl,
               @Param("createTime") String createTime);
}
複製程式碼

5.業務層:toly1994.com.android_project.service.NoteService
/**
 * 作者:張風捷特烈
 * 時間:2018/11/19 0019:13:48
 * 郵箱:1981462002@qq.com
 * 說明:Service層---操作dao
 */
@Service
public class NoteService {
    @Autowired
    private NoteDao mNoteDao;
    @Transactional
    public String insertNote(Note note) {
        mNoteDao.insert(note.getType(), note.getName(),
                note.getLocalPath(), note.getJianshuUrl(),
                note.getJuejinUrl(), note.getImgUrl(),
                note.getCreateTime());
        return "OK";
    }
}
複製程式碼

6.控制層:toly1994.com.android_project.controller.NoteController
/**
 * 作者:張風捷特烈
 * 時間:2018/11/19 0019:13:34
 * 郵箱:1981462002@qq.com
 * 說明:控制層---生成url介面
 */
@RestController
public class NoteController {
    @Autowired
    private NoteService mNoteService;
    
    @GetMapping("/test/insert")
    public String insert() {
        Note note = new Note("C", "Android關於Canvas你所知道的和不知道的一切",
                "I:\\Java\\Android\\Unit\\C\\app\\src\\main\\java\\com\\toly1994\\c\\view\\CanvasView.java"
                , "https://www.jianshu.com/p/4bc05f646bfe", "https://juejin.im/post/5be29aa2e51d45228170ff33",
                "http://localhost:8080/android/Android關於Canvas你所知道的和不知道的一切.png", "null");
        mNoteService.insertNote(note);
        return "ok";
    }
}
複製程式碼

7.啟動類:注意坑點,啟動類,加掃包
@SpringBootApplication
//坑點5:將dao新增掃包範圍
@MapperScan(basePackages = {"toly1994.com.android_project.dao"})
public class AndroidProjectApplication {
    public static void main(String[] args) {
        SpringApplication.run(AndroidProjectApplication.class, args);
    }
}
複製程式碼

在瀏覽器上訪問介面便可以將資料插入資料庫:(這裡用GET先測試一下,後面會做成POST)

插入成功.png


四、實現RESTFUL的api介面(簡單的CRUD)

1.POST新增資料:http://域名:埠/api/android/note

介面統一採用RESTFUL風格:/api/android/XXX,關於RESTFUL風格,詳見:
修改控制器:NoteController,將插入方法改為POST,並在插入後,向訪問者返回插入資訊(json格式)

/**
 * 作者:張風捷特烈
 * 時間:2018/11/19 0019:13:34
 * 郵箱:1981462002@qq.com
 * 說明:控制層---生成url介面
 */
@RestController
@RequestMapping(value = "/api/android")

public class NoteController {

    @Autowired
    private NoteService mNoteService;

    @PostMapping(value = "/note")
    public Note addOne(@ModelAttribute Note note) {
        mNoteService.insertNote(note);
        return note;
    }
}
複製程式碼

使用Postman新建一個測試資料夾進行測試.png

POST插入成功.png


2.PUT修改資料:http://192.168.43.60:8089/api/android/note/[id]
1).mapper/Note.xml:新增SQL語句
<update id="updateById">
    UPDATE android
    SET type=#{type},name=#{name},localPath=#{localPath},jianshuUrl=#{jianshuUrl},juejinUrl=#{juejinUrl},imgUrl=#{imgUrl}
    WHERE id=#{id}
</update>
複製程式碼
2).NoteDao:新增方法介面
/**
 * 通過id修改一條記錄
 *
 * @param id
 * @return
 */
void updateById(@Param("id") int id,
                @Param("type") String type,
                @Param("name") String name,
                @Param("localPath") String localPath,
                @Param("jianshuUrl") String jianshuUrl,
                @Param("juejinUrl") String juejinUrl,
                @Param("imgUrl") String imgUrl,
                @Param("createTime") String createTime);
複製程式碼
3).NoteService:新增Service層方法
@Transactional
public Note updateNote(int id, Note note) {
    mNoteDao.updateById(id,
            note.getType(),
            note.getName(),
            note.getLocalPath(),
            note.getJianshuUrl(),
            note.getJuejinUrl(),
            note.getImgUrl(),
            note.getCreateTime());
    return note;
}
複製程式碼
4).NoteController:新增url訪問介面
@PutMapping(value = "/note/{id}")
public Note updateById(@PathVariable("id") Integer id, @ModelAttribute Note note) {
    mNoteService.updateNote(id,note);
    return note;
}
複製程式碼

PUT修改成功.png


3.查詢資料:

經過上面幾個,應該熟悉寫法了:
先在dao新增方法,再寫SQL,再將dao用Service過渡一下給Controller

//DAO
/**
 * 查詢所有
 * @return
 */
List<Note> findALL();

//SQL語句
<select id="findALL" resultType="toly1994.com.android_project.bean.Note">
    SELECT*FROM android
</select>

//Service
public List<Note> findAll() {
    return mNoteDao.findALL();
}

//Controller
@GetMapping(value = "/note")
public List<Note> findAll() {
    return mNoteService.findAll();
}
複製程式碼

get請求所有.png


4.查詢單個(以id欄位為例,其他欄位類似)
//DAO
/**
 * 根據id查詢
 * @return
 */
Note findById(@Param("id") int id);

//SQL語句
<select id="findById" resultType="toly1994.com.android_project.bean.Note">
    SELECT*FROM android
    WHERE id=#{id}
</select>

//Service
public Note findById(int id){
    return mNoteDao.findById(id);
}

//Controller
@GetMapping(value = "/note/{id}")
public Note findById(@PathVariable("id") Integer id) {
    return mNoteService.findById(id);
}
複製程式碼

根據id查詢.png


5.刪除單個資料(以id欄位為例,其他欄位類似)
//DAO
/**
 * 根據id刪除
 * @param id
 */
void deleteById(@Param("id") int id);

//SQL語句
<delete id="deleteById">
    DELETE FROM android
    WHERE id=#{id}
</delete>

//Service
@Transactional
public int deleteById(int id){
    mNoteDao.deleteById(id);
    return id;
}

//Controller
@DeleteMapping(value = "/note/{id}")
public int deleteById(@PathVariable("id") Integer id) {
    return mNoteService.deleteById(id);
}
複製程式碼

根據id刪除.png


三、資料返回形式優化統一與異常捕捉

統一返回.png


1.結果統一返回形式
//成功的json:
{
    "code": 200,
    "msg": "操作成功",
    "data": {
        "id": 2,
        "type": "B",
        "name": "BASE",
        "localPath": "c",
        "jianshuUrl": "http://jianshu",
        "juejinUrl": "http://juejin",
        "imgUrl": "imgUrl",
        "create": null
    }
}

//失敗的json:
{
    "code": 500,
    "msg": "/ by zero",
    "data": null
}
複製程式碼

統一資料返回格式.png


2.統一格式實現:
/**
 * 作者:張風捷特烈
 * 時間:2018/5/25:15:30
 * 郵箱:1981462002@qq.com
 * 說明:格式化請求返回值
 */
public class ResultBean<T> {
    private int code;
    private String msg;
    private T data;

    public ResultBean(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    //get、set、toString省略
}
複製程式碼
3.使用列舉類統一錯誤碼與錯誤資訊維護

用來維護一些錯誤列舉,可自定義,在捕獲異常時對應丟擲,以便管理
如預設情況查詢一個資料庫沒有的id是不會報錯的,這時可以自定義一個id未知異常,在Service層捕獲一下

自定義異常.png

/**
 * 作者:張風捷特烈
 * 時間:2018/5/25:17:36
 * 郵箱:1981462002@qq.com
 * 說明:使用列舉類統一錯誤碼與錯誤資訊維護
 */
public enum ResultEnum {
    SUCCESS(200, "操作成功"),
    EXCEPTION(500, "起它異常"),
    NOT_FOUND_ID(102, "未知id");
    private int code;
    private String msg;
    ResultEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}
複製程式碼
/**
 * 作者:張風捷特烈
 * 時間:2018/5/25:17:14
 * 郵箱:1981462002@qq.com
 * 說明:id未知異常
 */
public class NotFoundIdException extends RuntimeException {
    private int code;
    private static String msg = ResultEnum.NOT_FOUND_ID.getMsg();
    public NotFoundIdException() {
        super(msg);
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}

複製程式碼
//Service中捕獲異常
public Note findById(int id) {
    Note byId = mNoteDao.findById(id);
    if (byId == null) {
        throw new NotFoundIdException();
    }
    return byId;
}
複製程式碼

4.結果處理類

使用該類將所有結果轉化為ResultBean物件,實現返回值的統一

/**
 * 作者:張風捷特烈
 * 時間:2018/5/30:18:37
 * 郵箱:1981462002@qq.com
 * 說明:結果處理類
 */
public class ResultHandler {
    /**
     * 成功時將object物件轉化為ResultBean物件
     *
     * @param o
     * @return
     */
    public static ResultBean ok(Object o) {
        return new ResultBean(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), o);
    }

    /**
     * 使用列舉列舉錯誤型別
     *
     * @param error
     * @return
     */
    public static ResultBean error(ResultEnum error) {
        return new ResultBean(error.getCode(), error.getMsg(), null);
    }

    public static ResultBean error(String e) {
        return new ResultBean(ResultEnum.EXCEPTION.getCode(), e, null);
    }
}
複製程式碼

5.異常的捕獲:

@ExceptionHandler和@ControllerAdvice會讓所有的異常走這裡,用ResultHandler統一處理
這裡可以為專案自定義一些異常

/**
 * 異常捕獲類
 */
@ControllerAdvice
public class ExceptionHandle {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultBean handle(Exception e) {
        return ResultHandler.error(e.getMessage());
    }
}

複製程式碼

6.將Controller中的所有返回結果都包裹成ResultBean
@RestController
@RequestMapping(value = "/api/android")

public class NoteController {

    @Autowired
    private NoteService mNoteService;

    @PostMapping(value = "/note")
    public ResultBean addOne(@ModelAttribute Note note) {
        mNoteService.insertNote(note);
        return ResultHandler.ok(note);
    }

    @PutMapping(value = "/note/{id}")
    public ResultBean updateById(@PathVariable("id") Integer id, @ModelAttribute Note note) {
        mNoteService.updateNote(id, note);
        return ResultHandler.ok(note);
    }

    @GetMapping(value = "/note")
    public ResultBean findAll() {
        return ResultHandler.ok(mNoteService.findAll());
    }

    @GetMapping(value = "/note/{id}")
    public ResultBean findById(@PathVariable("id") Integer id) {
        return ResultHandler.ok(mNoteService.findById(id));
    }

    @DeleteMapping(value = "/note/{id}")
    public ResultBean deleteById(@PathVariable("id") Integer id) {
        return ResultHandler.ok(mNoteService.deleteById(id));
    }
}

複製程式碼

五:優化與補充

1.請求總結

總的來說介面有這些:(域名是http://192.168.43.60,埠是:8089 自行修改)

查詢:GET請求
查詢所有:http://192.168.43.60:8089/api/android/note
查詢id=1: http://192.168.43.60:8089/api/android/note/1
查詢type=C: http://192.168.43.60:8089/api/android/note/type/C
查詢名字有View的:http://192.168.43.60:8089/api/android/note/name/View

插入:POST請求
插入資料:http://192.168.43.60:8089/api/android/note

修改:PUT請求
修改id=1的資料:http://192.168.43.60:8089/api/android/note/1

刪除:DELETE請求
刪除id=1的資料:http://192.168.43.60:8089/api/android/note/1
複製程式碼

2、使用內聯查詢和模糊查詢的SQL對映如下:

dao、Service、Controller操作類似,就不貼了

<select id="findALL" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
</select>

<select id="findByType" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.type=#{type}
</select>

<select id="findById" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.id=#{id}
</select>

<select id="findByName" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   where name LIKE concat(concat('%',#{name}),'%')
</select>
複製程式碼

查詢.png

3.伺服器資源的訪問
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //在F:/SpringBootFiles/Image/下如果有一張 Excalibar.jpg的圖片,那麼:
        //【1】訪問:http://localhost:8080/imgs/Excalibar.jpg 可以訪問到
        //【2】html 中 <img src="imgs/Excalibar.jpg">
        registry.addResourceHandler("/imgs/**").addResourceLocations("file:F:/SpringBootFiles/imgs/");
        registry.addResourceHandler("/mp3/**").addResourceLocations("file:F:/SpringBootFiles/mp3/");
        registry.addResourceHandler("/file/**").addResourceLocations("file:F:/SpringBootFiles/file/");
    }
}
複製程式碼

訪問伺服器上的檔案.png


4.檔案的上傳介面: UploadController.java
表單上傳:http://192.168.43.60:8089/api/android/upload
寫流上傳:http://192.168.43.60:8089/api/android/postfile

//注意,SpringBoot中表單上傳有限定大小2M,修改方式:
spring:
    servlet:
      multipart:
        max-file-size: 10MB
        max-request-size: 100MB
複製程式碼

@RestController
@RequestMapping(value = "/api/android")
public class UploadController {
    /**
     * 表單上傳:多檔案上傳(包括一個)
     *
     * @param files 上傳的檔案
     * @return 上傳反饋資訊
     */
    @PostMapping(value = "/upload")
    public @ResponseBody
    ResultBean uploadImg(@RequestParam("file") List<MultipartFile> files) {
        StringBuilder result = new StringBuilder();
        for (MultipartFile file : files) {
            if (file.isEmpty()) {
                return ResultHandler.error("Upload Error");
            }
            String fileName = file.getOriginalFilename();//獲取名字
            String path = "F:/SpringBootFiles/imgs/";
            File dest = new File(path + "/" + fileName);
            if (!dest.getParentFile().exists()) { //判斷檔案父目錄是否存在
                dest.getParentFile().mkdir();
            }
            try {
                file.transferTo(dest); //儲存檔案
                result.append(fileName).append("上傳成功!\n");
            } catch (IllegalStateException | IOException e) {
                e.printStackTrace();
                result.append(fileName).append("上傳失敗!\n");
            }
        }
        return ResultHandler.ok(result.toString());
    }
    /**
     * 通過流寫入伺服器
     * @param name
     * @param request
     * @return
     */
    @PostMapping(value = "/postfile")
    public @ResponseBody
    ResultBean postFile(@RequestParam(value = "name") String name, HttpServletRequest request) {
        String result = "";
        ServletInputStream is = null;
        FileOutputStream fos = null;
        try {
            File file = new File("F:/SpringBootFiles/imgs", name);
            fos = new FileOutputStream(file);
            is = request.getInputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            result = "SUCCESS";
        } catch (IOException e) {
            e.printStackTrace();
            result = "ERROR";
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResultHandler.ok(result);
    }
}
複製程式碼

上傳檔案.png


4.跨域的處理

跨域問題主要就是請求頭的問題,詳細分析可見:SpringBoot-12-之Ajax跨域訪問全解析

AndroidProjectApplication
@SpringBootApplication
//坑點5:將dao新增掃包範圍
@MapperScan(basePackages = {"toly1994.com.android_project.dao"})
public class AndroidProjectApplication {

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

    @Bean
    public FilterRegistrationBean registerFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.addUrlPatterns("/*");//所有請求都經過這個Filter
        bean.setFilter(new CrosFilter());//設定過濾器
        return bean;
    }
}
複製程式碼
toly1994.com.android_project.config.CrosFilter
/**
 * 作者:張風捷特烈
 * 時間:2018/7/22:21:44
 * 郵箱:1981462002@qq.com
 * 說明:解決跨域問題...加頭
 */
public class CrosFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse rep = (HttpServletResponse) servletResponse;

        HttpServletRequest req = (HttpServletRequest) servletRequest;

        String origin = req.getHeader("Origin");
        if (!StringUtils.isEmpty(origin)) {
            rep.addHeader("Access-Control-Allow-Origin", origin);
        }
        //動態新增自定義頭
        String headers = req.getHeader("Access-Control-Request-Headers");
        if (!StringUtils.isEmpty(headers)) {
            System.out.println(headers);
            rep.addHeader("Access-Control-Allow-Headers", headers);
        }

        //允許8081訪問:
//        rep.addHeader("Access-Control-Allow-Origin", "*");
//        rep.addHeader("Access-Control-Allow-Origin", "http://localhost:8081");
        //允許訪問方法GET
        rep.addHeader("Access-Control-Allow-Methods", "GET");
        rep.addHeader("Access-Control-Allow-Methods", "POST");
//        rep.addHeader("Access-Control-Allow-Headers", "Content-Type");
        rep.addHeader("Access-Control-Max-Age", "3600");//一小時內快取預檢請求
        rep.addHeader("Access-Control-Allow-Credentials", "true");//允許cookie

        filterChain.doFilter(servletRequest, rep);
    }

    @Override
    public void destroy() {

    }
}
複製程式碼

四、本地SpringBoot專案部署到伺服器上執行(使用騰訊雲)

1.打包:

我將埠改為了8089(因為我的伺服器開了8089埠)

mvn -Dmaven.test.skip -U clean install
複製程式碼

2.資料庫的備份與恢復

本地備份,服務端恢復

備份:mysqldump -uroot -p mycode >D:\\backupSql\\android.sql
還原:mysql -u root -p mycode< D:\\backupSql\\android.sql
複製程式碼

資料庫恢復.png

備份資料庫.png


3.上線

拷貝.png

執行:

F:\>java -jar F:\android_project-0.0.1-SNAPSHOT.jar
複製程式碼

4.測試url介面api
1)新增:POST:www.toly1994.com:8089/api/android…

線上插入成功.png

2)查詢:www.toly1994.com:8089/api/android…

查詢成功.png

3)訪問圖片

線上訪問圖片.png

至此後端的資料庫簡單操作及RESTFUl的api介面就已經實現了,雖然比較簡單
後期有需要可以再增加其他的url,訪問介面有資料了,後端自此告一段落。


2018-12-12補充:新增分頁查詢:

偏移0,一頁20條資料:http://192.168.43.60:8089/api/android/note/0/20

<select id="findByType" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,info,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   WHERE a.type=#{type}
   limit #{offset},#{limit}
</select>
複製程式碼

分類查詢分頁:http://192.168.43.60:8089/api/android/note/type/ABCS/0/4

<select id="findByName" resultType="toly1994.com.android_project.bean.Note">
   SELECT a.id,name,t.type,localPath,jianshuUrl,juejinUrl,imgUrl,info,createTime FROM android AS a
   INNER JOIN type AS t ON a.type = t.type_idx
   where name LIKE concat(concat('%',#{name}),'%')
   limit #{offset},#{limit}
</select>
複製程式碼

下篇:建站四部曲之Python爬蟲+資料準備篇(selenium)


後記:捷文規範

1.本文成長記錄及勘誤表
專案原始碼 日期 備註
V0.1 2018-12-11 建站四部曲之後端介面篇(SpringBoot+上線)
V0.2 2018-12-12 分頁查詢的處理,增加info欄位
2.更多關於我
筆名 QQ 微信 愛好
張風捷特烈 1981462002 zdl1994328 語言
我的github 我的簡書 我的掘金 個人網站
3.宣告

1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大程式設計愛好者共同交流
3----個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
4----看到這裡,我在此感謝你的喜歡與支援


icon_wx_200.png

相關文章