1. 程式人生 > 實用技巧 >Java NIO(四)開發基於幀的ping-pong伺服器

Java NIO(四)開發基於幀的ping-pong伺服器

專案講解

具體功能如何實現


需要到的技術(純後端開發)

josn+spring boot+mybatis puls+mysql資料庫

什麼是josn:

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。

翻譯人能聽懂的話就是 我從後端傳到前端的資料能顯示出來前端需要的格式


什麼是spring boot:

從最根本上來講,Spring Boot就是一些庫的集合,它能夠被任意專案的構建系統所使用。

翻譯成人能聽懂的話就是spring boot 就是一個框架

特點: 自動裝配控制反轉


什麼是Mybatis:

MyBatis 是一款優秀的持久層框架,它支援自定義 SQL、儲存過程以及高階對映。
MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。
MyBatis 可以通過簡單的 XML 或註解來配置和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。

翻譯成人能聽懂的話就是Mybatis就是一個高階的JDBC

在翻譯就是java語言怎麼和資料庫連線

這就是Mybatis!


什麼是mysql資料庫:

不想說...


一個java web專案主要分為一下三層

  1. contorller
  2. servise
  3. dao

流程圖:


controller層

  • 最重要的一點就是提供api介面與前端互動

以下是我擷取的片段程式碼(controller層)具體的一個前端互動實現

@Api(tags = "裝置臺賬-裝置列表")
@RestController
@RequestMapping("/ledger")
@Slf4j
public class LedgerController {
@Autowired
private ApparatusInfoService apparatusInfoService;

@Autowired
private SysDdictionariesService sysDdictionariesService;

@Autowired
private ApparatusProcessService apparatusProcessService;

@Autowired
private ApparatusStatsService apparatusStatsService;
@SysLog("建立裝置")
@ApiOperation("建立")
@PostMapping("/apparatus")
@RequiresPermissions("ledger:apparatusinfo:save")
public R create(@RequestBody ApparatusInfoDTO apparatusInfoDTO) {
    String categoryName = apparatusInfoDTO.getCategoryName();
    if (StringUtils.isEmpty(categoryName) ||
            StringUtils.isEmpty(apparatusInfoDTO.getSn()) ||
            StringUtils.isEmpty(apparatusInfoDTO.getUsestate())) {
        log.error("faield to ledger create, 必要引數為空");
        return R.ok("建立失敗,請填寫完整資訊");
    }
    boolean b = apparatusInfoService.createCheckSn(apparatusInfoDTO.getSn());
    if (!b) {
        log.error("faield to ledger create, 裝置編碼已存在");
        return R.error("裝置編碼已存在");
    }
    JSONObject infoTemplate = null;
    String statsInfo = null;
    try {
        statsInfo = JsonUtils.getStrToJson(categoryName, "realtime");
    } catch (Exception e) {
        log.error("faield to ledger create statsInfo", e);
        return R.error("建立失敗");
    }
    ApparatusStatsEntity status = new ApparatusStatsEntity();

    String infoString = apparatusInfoDTO.getInfoString();
    if (StringUtils.isEmpty(infoString)) {
        try {
            infoTemplate = apparatusInfoService.getInfoTemplate(categoryName, "static");

            apparatusInfoDTO.setInfo(infoTemplate);
        } catch (Exception e) {
            log.error("faield to ledger create infoTemplate", e);
            return R.error("建立失敗");
        }
    } else {
        JSONObject info = JSONObject.parseObject(infoString);
        apparatusInfoDTO.setInfo(info);
    }
    SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
    apparatusInfoDTO.setCreatetime(new Date());
    JSONObject statusTemplate = (JSONObject) JSONObject.parse(statsInfo);
    apparatusInfoDTO.setStatusthreshold(statusTemplate);
    apparatusInfoDTO.setCreateuser(user.getUsername());
    ApparatusInfoEntity apparatusInfo = ApparatusInfoDTO.getInfoEntity(apparatusInfoDTO);
    try {
        apparatusInfoService.save(apparatusInfo);
        Long infoid = apparatusInfoService.selectInfoid(apparatusInfoDTO.getSn());
        status.setInfoid(infoid);
        status.setInfo(statsInfo);
        status.setCreatetime(new Date());
        status.setCreateuser(user.getUsername());
        apparatusStatsService.createStatus(status);
        log.info("ledger create, infoEntity:{}, apparatusInfoDTO:{}", apparatusInfo, apparatusInfoDTO);
        return R.ok("建立成功");
    } catch (Exception e) {
        log.error("faield to ledger create createStatus", e);
        return R.error("建立失敗");
     }
   }
}

//Class R 返回狀態碼與資訊
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;

public R() {
	put("code", 0);
	put("msg", "success");
}

public static R error() {
	return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知異常,請聯絡管理員");
}

public static R error(String msg) {
	return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}

public static R error(int code, String msg) {
	R r = new R();
	r.put("code", code);
	r.put("msg", msg);
	return r;
}

public static R ok(String msg) {
	R r = new R();
	r.put("msg", msg);
	return r;
}

public static R ok(Map<String, Object> map) {
	R r = new R();
	r.putAll(map);
	return r;
}

public static R ok() {
	return new R();
}

public R put(String key, Object value) {
	super.put(key, value);
	return this;
}

}

程式開頭 有這4個註解

註解:spring 4.0特性 幫助開發

分析一下這4個註解

@Api(tags = "裝置臺賬-裝置列表")這是個swagerr註解
表示標識這個類是swagger的資源

@RestController

@RestController註解是@Controller和@ResponseBody的合集,表示這是個控制器bean,並且是將函式的返回值直 接填入HTTP響應體中,是REST風格的控制器。

翻譯一下就是 後臺返回資料用這個


@RequestMapping(/ledger)

@RequestMapping:提供路由資訊,負責URL到Controller中的具體函式的對映。

就是相當於返回對映到這個url下 http://localhost :8080/xxx/ledger


@Slf4j

log的註解 列印日誌到哪裡的註解 (java程式碼規範有寫:log可以設定級別,可以控制輸出到哪裡,容易區分是在程式碼的什麼地方列印的,而System.out.print則不行。而且,System.out.print的速度很慢。所以,除非是有意的,否則,都要用log。至少在提交到svn之前把System.out.print換成log。--來源gittab)


再往下看程式碼


@Autowired

@Autowired 註釋,它可以對類成員變數、方法及建構函式進行標註,完成自動裝配的工作。 通過 @Autowired的使用來消除 set ,get方法

翻譯一下就是 把你的Controller與service連線起來

再看

點進來

就進到了你的Service
extends繼承
IService<> 一個方法
ApparatusStatsEntity 這個是其他類中的class程式碼具體就是把資料庫有的欄位定義出來

Entity中具體程式碼

package cn.galaiot.modules.ledger.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
	* @author zhangtong
	* @date 2020-09-04 14:06:29
 */
@Data  //註解 有了這個就不需要get set方法了
@TableName(value = "apparatus_process", autoResultMap = true)
public class ApparatusProcessEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
     * 主鍵id
 */
@TableId
private Long id;
/**
     * 裝置id
 */
private Long infoid;
/**
 * 操作時間
 */
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
private Date operationtime;
/**
 * 管理內容
 */
private String managecontent;
/**
 * 實施方式
 */
private String implement;
/**
 * 實施方
 */
private String executor;
/**
 * 費用
 */
private Double expense;
;
/**
 * 完好待用時間
 */
private Long readyforusetime;
/**
 * 運轉時間
 */
private Long runningtime;
/**
 * 故障時間
 */
private Long faulttime;
/**
 *正常保養時間
 */
private Long normalmaintenancetime;
/**
 * 維保時間
 */
private String maintenancetime;
/**
 * 備註
 */
private String remark;
/**
 * 值班人
 */
private String inspector;
/**
 * 開始維保時間
 */
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
private Date starttime;
/**
 * 維保結束時間
 */
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
private Date endtime;
/**
 * 責任人
 */
private String responsible;
/**
 * 任務描述
 */
private String description;
/**
 * 配套裝置
 */
private String equipment;
/**
 * 詳細資訊
 */
@TableField(typeHandler = FastjsonTypeHandler.class)
private String info;
/**
 * 建立時間
 */
private Date createtime;
/**
 * 建立人
 */
private String createuser;
/**
 * 修改時間
 */
private Date updatetime;
/**
 * 修改人
 */
private String updateuser;
/**
 * 裝置狀態, -1表示刪除, 0表示正常
 */
private Integer status;
}

暫且不談Entity包是個什麼東西


繼續上面程式碼

又是4個註解

@SysLog
與上面 @Slf4j對應 寫出log列印到哪裡

@ApiOperation
首先@ApiOperation註解不是Spring自帶的,它是是swagger裡的
註解@ApiOperation是用來構建Api文件的
@ApiOperation(value = “介面說明”, httpMethod = “介面請求方式”, response =
“介面返回引數型別”, notes = “介面釋出說明”;其他引數可參考原始碼;

提到swagger不得不提到RESTful風格

RESTFUL是一種網路應用程式的設計風格和開發方式,基於HTTP,可以使用XML格式定義或JSON格式定義。RESTFUL適用於移動網際網路廠商作為業務使能介面的場景,實現第三方OTT呼叫行動網路資源的功能,動作型別為新增、變更、刪除所呼叫資源。

一個@ApiOperation的通用寫法 下面是舉例

@ApiOperation(value="建立使用者", notes="根據User物件建立使用者")
@ApiImplicitParam(name = "user", value = "使用者詳細實體user", required = true, dataType = "User")
@RequestMapping(value="", method=RequestMethod.POST)
public String postUser(@RequestBody User user) {
    users.put(user.getId(), user);
    return "success";
}

下一個的@PostMapping註解

  1. @PostMapping
  2. @PutMapping
  3. @DeleteMapping
  4. @PatchMapping
  5. @GetMapping

為什麼這麼寫:

@PostMapping("/apparatus")

這裡的和Swagger上顯示的一樣就行

什麼是@PostMapping:

對映一個POST請求 處理post請求

等價於@RequestMapping(value = "/user/login",method = RequestMethod.POST)

Spring官方文件說:

@GetMapping是一個組合註解,是@RequestMapping(method = RequestMethod.GET)的縮寫。該註解將HTTP Get 對映到 特定的處理方法上。

@PostMapping 是一個組合註解,是@RequestMapping(method = RequestMethod.POST)的縮寫。該註解將HTTP Post 對映到 特定的處理方法上。


到public R create(@RequestBody ApparatusInfoDTO apparatusInfoDTO)

@ResponseBody:表示該方法的返回結果直接寫入HTTP response body中,一般在非同步獲取資料時使用,用於構建RESTful的api。在使用@RequestMapping後,返回值通常解析為跳轉路徑,加上@responsebody後返回結果不會被解析為跳轉路徑,而是直接寫入HTTP response body中。

比如非同步獲取json資料,加上@responsebody後,會直接返回json資料。該註解一般會配合@RequestMapping一起使用。

點選ApparatusInfoDTO 跳轉到public class ApparatusInfoDTO extends ApparatusInfoEntity


寫到這裡可以緩一緩了 不要急來到service層

至於為什麼 就因為這個程式裡的第一行程式碼~

HashMap<String, Object> date = apparatusInfoService.getAll(params);
分析程式碼
HashMap<String,Object> date 定義一個hashmap集合 名字為 date
apparatusInfoService.getAll(params)
apparatusInfoService.得到所有 引數

這就是重點了 因為apparatusInfoService在這!

這裡實現了Controller層互動service層。