【譯】關於Rust模組的清晰解釋
專案講解
具體功能如何實現
需要到的技術(純後端開發)
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專案主要分為一下三層
- contorller
- servise
- 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註解
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
- @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層。
service層
service下有兩個
一個叫做xxxxService
另一個叫xxxxServiceImpl
Service 是介面
Impl 是實現
xxxService 程式碼
public interface ApparatusInfoService extends IService<ApparatusInfoEntity> {
//獲取所有資料列表,支援條件搜尋和分頁
HashMap<String,Object> getAll(Map<String, Object> params);
}
上面是controller裡的程式碼
下面是service裡的程式碼
注意是怎麼連線在一起的 命名與取名
當你在這裡寫好一個介面以後你的同級目錄下的xxxImpl就會報錯
因為實現可以沒有方法 但一定要實現。
xxxserviceImpl 程式碼
@Service("apparatusInfoService")
public class ApparatusInfoServiceImpl extends ServiceImpl<ApparatusInfoDao, ApparatusInfoEntity> implements ApparatusInfoService {
@Resource
private ApparatusInfoDao apparatusInfoDao;
public HashMap<String, Object> getAll(Map<String, Object> params) {
HashMap<String, Object> date = new HashMap<>();
List categorys = null;
List useStates = null;
List departments = null;
String likeKey = StringUtils.defaultIfEmpty((String) params.get("likeKey"), "name");
String likeValue = (String) params.get("likeValue");
likeValue = "%" + likeValue + "%";
//分頁引數
Long curPage = 0L;
Long limit = 10L;
if (params.get(Constant.PAGE) != null) {
curPage = Long.parseLong((String) params.get(Constant.PAGE)) - 1L;
}
if (params.get(Constant.LIMIT) != null) {
limit = Long.parseLong((String) params.get(Constant.LIMIT));
}
Long start = curPage * limit;
String json = (String) params.get("preciseValue");
if (!StringUtils.isEmpty(json)) {
HashMap<String, String> map = JSON.parseObject(json, HashMap.class);
Set<String> keys = map.keySet();
for (String key : keys) {
switch (key) {
case "category":
String categorysString = map.get(key);
if (StringUtils.isEmpty(categorysString)) {
break;
}
categorys = Arrays.asList(categorysString.split(","));
break;
case "usestate":
String useStatesString = map.get(key);
if (StringUtils.isEmpty(useStatesString)) {
break;
}
useStates = Arrays.asList(useStatesString.split(","));
break;
case "department":
String departmentsString = map.get(key);
if (StringUtils.isEmpty(departmentsString)) {
break;
}
departments = Arrays.asList(departmentsString.split(","));
break;
}
}
}
List<String> unit = UserUtils.getUserDepartment();
List<ApparatusInfoEntity> apparatusInfos = apparatusInfoDao.getAllByKey(likeKey, likeValue, start, limit, categorys, useStates, departments, unit);
Long count = apparatusInfoDao.getCount(likeKey, likeValue, categorys, useStates, departments, unit);
date.put("apparatusInfos", apparatusInfos);
date.put("num", count);
return date;
}
}
程式碼分析!
註解:@service :一般用於修飾service層的元件
翻譯:連線service與controller
註解:@Resource :這個註解屬於J2EE,預設安裝名稱進行裝配,名稱可以通過name屬性進行指定,如果沒有指定name屬性,當註解寫在欄位上時,預設取欄位名進行安裝名稱查詢,如果註解寫在setter方法上預設取屬性名進行裝配。當找不到與名稱匹配的bean時才按照型別進行裝配。但是需要注意的是,如果name屬性一旦指定,就只會按照名稱進行裝配。
翻譯:不用寫setter方法,減少了與spring的耦合
private ApparatusInfoDao apparatusInfoDao;
直觀的就是用在了這行程式碼
要注意同樣的程式碼在不同的層如和耦合在一起的
繼續分析Impl程式碼 我把實現的第一程式碼整個copy