微項目:一步一步帶你使用SpringBoot入門(一)

  • 2019 年 10 月 3 日
  • 筆記

最近放假了,休息的時候不忘寫個小項目來玩玩。
如果有需要一起手動做項目的朋友可以和我一起做這個小項目。
做到哪隨心所欲。也就一周的事哈哈。
***

開發環境

  • JDK1.8
  • JetBrain InteliJ

傻瓜式啟動項目

打開newProject 然後單擊Spring Initializr然後一直next

在這裡確定好包名之類的

在這裡不用單擊任何東西,直接next就行

在這裡我們可以看到項目建起來了。

我們直接點啟動,就能把項目跑起來。

OK,至此我們就完成了SpringBoot的搭建。

我要將其開源,因此我們需要將這個項目放到Github上面。

首先share it
然後憑直覺一直往下點就可以了。

項目地址在這:https://github.com/GodofOrange/anonymous

我會持續更新文章。
如果有興趣的同學可以給個star

項目需求

我想趁著國慶做一個匿名傾吐煩惱的APP,其實整個想法實現起來蠻簡單的,但是如果僅僅使用mysql那就沒有什麼意義了,因此我將使用jpa+redis+kafka+ngnix組裝一個高可用性的後端。

整個項目呢,我打算使用敏捷開發方式,一點一點的集成到這個項目裡面。

SpringBoot+JPA做持久層

MYSQL的環境相信大家都會有的,那我這裡直接給出數據表(注意ORM技術不用建表)

id title content update summary hot
BIGINT varchar(255) LONGTEXT TIMESTAMP TEXT BIGINT

資料庫創建腳本:

CREATE DATABASE anonymous DEFAULT CHARSET utf8mb4;

OK,現在資料庫已經建起來了。那麼我們接下來導入JPA的依賴吧。

在pom文件下引入以下文件。

        <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-data-jpa</artifactId>          </dependency>          <dependency>              <groupId>com.alibaba</groupId>              <artifactId>druid-spring-boot-starter</artifactId>              <version>1.1.10</version>          </dependency>          <dependency>              <groupId>mysql</groupId>              <artifactId>mysql-connector-java</artifactId>          </dependency>  

然後修改配置文件。

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/anonymous?serverTimezone=UTC&useSSL=true&allowMultiQueries=true&characterEncoding=utf8  spring.datasource.username=root  spring.datasource.password=123456  spring.jpa.show-sql=true  spring.jpa.database=mysql  spring.jpa.hibernate.ddl-auto=update  spring.jpa.database-platform=org.hibernate.dialect.MySQL57InnoDBDialect

隨後啟動,觀察是否報錯。

如果沒報錯,會正常退出那就一切OK.

下面我們來創建表

新建類Wall.java

package cn.baldorange.anonymous.entity;    import javax.persistence.*;  import java.util.Date;    @Entity(name = "wall")  public class Wall {      public Wall(){        }      public Wall(String title, String content, Date up_time, String summary, String hot) {          this.title = title;          this.content = content;          this.up_time = up_time;          this.summary = summary;          this.hot = hot;      }        @Id      @GeneratedValue(strategy = GenerationType.IDENTITY)      @Column(name = "id",columnDefinition="BIGINT COMMENT '主鍵,自動生成'")      private String id;      @Column(name = "title",columnDefinition="VARCHAR(255)")      private String title;      @Column(name = "content",columnDefinition="LONGTEXT")      private String content;      @Column(name = "up_time",columnDefinition="TIMESTAMP")      private Date up_time;      @Column(name = "summary",columnDefinition="TEXT")      private String summary;      @Column(name = "hot",columnDefinition = "BIGINT")      private String hot;        public String getId() {          return id;      }        public void setId(String id) {          this.id = id;      }        public String getTitle() {          return title;      }        public void setTitle(String title) {          this.title = title;      }        public String getContent() {          return content;      }        public void setContent(String content) {          this.content = content;      }        public Date getUp_time() {          return up_time;      }        public void setUp_time(Date up_time) {          this.up_time = up_time;      }        public String getSummary() {          return summary;      }        public void setSummary(String summary) {          this.summary = summary;      }        public String getHot() {          return hot;      }        public void setHot(String hot) {          this.hot = hot;      }        @Override      public String toString() {          return "Wall{" +                  "id='" + id + ''' +                  ", title='" + title + ''' +                  ", content='" + content + ''' +                  ", up_time=" + up_time +                  ", summary='" + summary + ''' +                  ", hot='" + hot + ''' +                  '}';      }  }  

新建介面

package cn.baldorange.anonymous.repository;    import cn.baldorange.anonymous.entity.Wall;  import org.springframework.data.jpa.repository.JpaRepository;    public interface WallRepo extends JpaRepository<Wall,String> {    }  

SpringTest文件

package cn.baldorange.anonymous;    import cn.baldorange.anonymous.entity.Wall;  import cn.baldorange.anonymous.repository.WallRepo;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.context.SpringBootTest;  import org.springframework.test.context.junit4.SpringRunner;    import java.util.Date;    @RunWith(SpringRunner.class)  @SpringBootTest  public class AnonymousApplicationTests {      @Autowired      WallRepo wallRepo;      @Test      public void contextLoads() {          wallRepo.save(new Wall("測試","文章",new Date(),"摘要","0"));         System.out.println(wallRepo.findById("1"));      }    }  

運行結果如下所示:

到此DAO層的就結束了。

我們Commit後直接推上去

這就完成了一次程式碼提交


下面是關於SpringBoot整合其他項目的解決方法。可作為擴展參考


swagger引入

Swagger是一個介面文檔工具,依照Swagger可以0配置開發介面。不過要注意,Swagger是基於SpringBoot1.47版本開發的,而SpringBoot現在基本都是是2+。
如果要選用restful支援,只能將SpringBoot退出到1+版本。
***

maven引入

<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>

Swagger配置文檔

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.spi.DocumentationType;  import springfox.documentation.spring.web.plugins.Docket;  import springfox.documentation.swagger2.annotations.EnableSwagger2;    @Configuration  @EnableSwagger2  public class swaggerConfig {      @Bean      Docket docket(){          return new Docket(DocumentationType.SWAGGER_2)                  .select()                  .apis(RequestHandlerSelectors.any())                  .paths(PathSelectors.any())                  .build()                  .apiInfo(new ApiInfoBuilder().description("項目").build());      }  }

介面配置

import io.swagger.annotations.Api;  import io.swagger.annotations.ApiOperation;  import org.just.computer.mathproject.Entity.Advertisement;  import org.just.computer.mathproject.Service.AdvertisementService;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.web.bind.annotation.GetMapping;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestParam;  import org.springframework.web.bind.annotation.RestController;    import java.util.List;    @RestController  @Api(tags ="廣告")  @RequestMapping("/Advertisement/")  public class AdvertisementController {      @Autowired      AdvertisementService advertisementService;        @ApiOperation(value ="獲得所有廣告")      @GetMapping("/getAllAdvertisement")      public List<Advertisement> getAllAdvertisement(){          return advertisementService.getAllAdvertisement();      }      @ApiOperation(value = "添加廣告")      @GetMapping("/addAdvertisement")      public Boolean getAllAdvertisement(@RequestParam String img, @RequestParam String href){          try {              advertisementService.addAdvertisement(img,href);              return true;          }catch (Exception e){              return false;          }      }        @ApiOperation(value = "刪除廣告")      @GetMapping("/deleteAdvertisement")      public Boolean deleteAdvertisementById(Integer id){         try{             advertisementService.deleteAdvertisementById(id);             return true;         }catch (Exception e){             return false;         }      }  }  

本地運行後訪問這裡即可訪問
或者到ip:埠/swagger-ui.html
運行結果如下

SpringBoot引入websocket


maven 依賴

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

WebSocketConfig 配置文件

import org.springframework.context.annotation.Configuration;  import org.springframework.messaging.simp.config.MessageBrokerRegistry;  import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;  import org.springframework.web.socket.config.annotation.StompEndpointRegistry;  import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;    @Configuration  @EnableWebSocketMessageBroker  public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {      @Override      public void configureMessageBroker(MessageBrokerRegistry config){          config.enableSimpleBroker("/topic");          config.setApplicationDestinationPrefixes("/app");      }      @Override      public void registerStompEndpoints(StompEndpointRegistry registry){          registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();      }  }  

配置了之後基本上不用做其他的配置了
setAllowedOrigins()為跨域函數

然後是Controller

import org.just.computer.mathproject.Bean.Message;  import org.springframework.messaging.handler.annotation.MessageMapping;  import org.springframework.messaging.handler.annotation.SendTo;  import org.springframework.stereotype.Controller;    import java.security.Principal;  import java.util.Date;    @Controller  public class GreetingController {      @MessageMapping("/hello")      @SendTo("/topic/greetings")      public Message greeting(String content, Principal pl) throws Exception{          Message message = new Message();          message.setContent(content.substring(1,content.length()-1));          message.setData(new Date().toString());          message.setName(pl.getName());          return message;      }  }

這裡的Principal 為SpringSecurity相關知識,目的是通過session獲得用戶名。
到此為止,SpringBoot的配置已經沒了

Vue通過stompClient使用webSocket


package.json

"dependencies": {      "@tinymce/tinymce-vue": "^3.0.1",      "axios": "^0.19.0",      "echarts": "^4.2.1",      "element-ui": "^2.11.1",      "net": "^1.0.2",      "nprogress": "^0.2.0",      "sockjs-client": "^1.4.0",      "stompjs": "^2.3.3",      "tinymce": "^4.8.5",      "tinymce-vue": "^1.0.0",      "vue": "^2.5.2",      "vue-axios": "^2.1.4",      "vue-echarts": "^4.0.3",      "vue-router": "^3.0.1",      "vue-stomp": "0.0.5"    }

一定要填加的有vue-stomp sockjs-client stompjs這三個
想用的地方直接引入。

import SockJS from 'sockjs-client'  import Stomp from 'webstomp-client'

vue中完整程式碼如下

<template>    <div>      <input type="text" v-model="text">      <button @click="sendMessage">發送消息</button>      <div class="bubble">      </div>      <div>        <div v-for="(data,key) in datas" :key="key">          {{data.content}}        </div>      </div>    </div>  </template>  <script>  import SockJS from 'sockjs-client'  import Stomp from 'webstomp-client'  export default {    name: 'ChatRoom',    data () {      return {        text: '',        datas: [],        stompClient: null      }    },    mounted () {      if ('WebSocket' in window) {        this.initWebSocket()      } else {        alert('當前瀏覽器 Not support websocket')      }    },    methods: {      sendMessage () {        this.stompClient.send('/app/hello', JSON.stringify(this.text), {})      },      initWebSocket () {        this.connection()      },      connection () {        const socket = new SockJS(this.$baseUrl + '/chat')        this.stompClient = Stomp.over(socket)        this.stompClient.connect({}, (frame) => {          this.stompClient.subscribe('/topic/greetings', (greeting) => {            console.log(JSON.parse(greeting.body))            this.datas.push(JSON.parse(greeting.body))          })        })      }    }  }  </script>    <style scoped>  </style>  

注意在這行程式碼this.stompClient.send(‘/app/hello’, JSON.stringify(this.text), {}) {}的位置,有的版本可能是相反的。
運行結果如下所示