1. 程式人生 > >微專案:一步一步帶你使用SpringBoot入門(一)

微專案:一步一步帶你使用SpringBoot入門(一)

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

開發環境

  • 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), {}) {}的位置,有的版本可能是相反的。
執行結果如下所示