如何進行后端開發 (大體邏輯)


項目講解

具體功能如何實現

以下僅僅代表本人觀點(未畢業學生實習中...)


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

json+spring boot+mybatis puls+mysql數據庫

面向接口編程

解耦 , 可拓展 , 提高復用 , 分層開發中 , 上層不用管具體的實現 , 大家都遵守共同的標准 , 使得開發變得容易 , 規范性更好

在一個面向對象的系統中,系統的各種功能是由許許多多的不同對象協作完成的。在這種情況下,各個對象內部是如何實現自己的,對系統設計人員來講就不那么重要了;

而各個對象之間的協作關系則成為系統設計的關鍵。小到不同類之間的通信,大到各模塊之間的交互,在系統設計之初都是要着重考慮的,這也是系統設計的主要工作內容。面向接口編程就是指按照這種思想來編程。


關於接口

接口從更深層次的理解,應是定義(規范,約束)與實現(名實分離的原則)的分離。

接口的本身反映了系統設計人員對系統的抽象理解。

接口應有兩類:

第一類是對一個個體的抽象,它可對應為一個抽象體(abstract class);

第二類是對一個個體某一方面的抽象,即形成一個抽象面(interface);

一個體有可能有多個抽象面。抽象體與抽象面是有區別的。


什么是json:

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連接起來

再看

點進來

DScq3R.md.png

就進到了你的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層。

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

前幾個List定義一些數組

	List categorys = null;
    List useStates = null;
    List departments = null;
    List newname=null;

這里使用了unitl類 實現了一個分頁功能

	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");

代碼分析!

String likeKey = StringUtils.defaultIfEmpty((String) params.get("likeKey"), "name");
//String likeKey =跳轉了一個Utils類.跳轉到defaultIfEmpty里實現isEmpty(str) ? defaultStr : str這個 params.get("這個是在dao層里一會看")

StringUtils 跳轉了一個Utils類

//Utils類功能
public class StringUtils {
public static final String EMPTY = "";
public static final int INDEX_NOT_FOUND = -1;
private static final int PAD_LIMIT = 8192;

public StringUtils() {
}

public static boolean isEmpty(String str) {
    return str == null || str.length() == 0;
}

public static boolean isNotEmpty(String str) {
    return !isEmpty(str);
}

public static boolean isBlank(String str) {
    int strLen;
    if (str != null && (strLen = str.length()) != 0) {
        for(int i = 0; i < strLen; ++i) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }

        return true;
    } else {
        return true;
    }
}

public static String defaultIfEmpty(String str, String defaultStr) {
    return isEmpty(str) ? defaultStr : str;
}

當前源代碼的下一行代碼

String likeValue = (String) params.get("likeValue");
傳過來的在dao層里的參數 ^likeValue^

Dao層

dao層叫數據訪問層,全稱為data access object,屬於一種比較底層,比較基礎的操作,具體到對於某個表、某個實體的增刪改查

dao層代碼

@Mapper
public interface ApparatusInfoDao extends BaseMapper<ApparatusInfoEntity> {
String fileds = "id, category, sn, assetSn, assetClassifySn, assetCategorySn, " +
        " sn5, model, underWarranty, useState, status, name, department, manufacturers," +
        " factorySn, factoryTime, factoryTime, commissioningTime, workTime, maintainenceTime, " +
        " faultTime, initRunTime, currentRunTime, pesponsible, dutyDepartment, position, power" +
        ", info, statusThreshold, remark, principal, createTime, createUser, updateTime, updateUser";
String tableName = "apparatus_info";

@Select("<script> " +
        "select " + fileds + " from " + tableName + " " +
        "<where> " +
        "status = 0  " +
        "and department in " +
        "<foreach item='units' index='index' collection='unit' open='(' separator=',' close=')'> " +
        "#{units} " +
        "</foreach> " +
        "<if test=' likeValue != null and likeValue != \"\" '> " +
        "and ${likeKey} like #{likeValue}" +
        "</if> " +
        "<if test=' categorys != null and categorys.size > 0 '> " +
        "and category in " +
        "<foreach item='category' index='index' collection='categorys' open='(' separator=',' close=')'> " +
        "#{category} " +
        "</foreach> " +
        "</if> " +
        "<if test=' useStates != null and useStates.size > 0 '> " +
        "and useState in " +
        "<foreach item='useState' index='index' collection='useStates' open='(' separator=',' close=')'> " +
        "#{useState}" +
        "</foreach>" +
        "</if> " +
        "<if test=' departments != null and departments.size > 0 '> " +
        "and department in " +
        "<foreach item='department' index='index' collection='departments' open='(' separator=',' close=')'> " +
        "#{department} " +
        "</foreach> " +
        "</if> " +
        "</where>" +
        "limit #{start}, #{limit} " +
        "</script> ")
List<ApparatusInfoEntity> getAllByKey(@Param("likeKey") String likeKey,
                                      @Param("likeValue") String likeValue,
                                      @Param("start") Long start,
                                      @Param("limit") Long limit,
                                      @Param("categorys") List<String> categorys,
                                      @Param("useStates") List<String> useStates,
                                      @Param("departments") List<String> departments,
                                      @Param("unit") List<String> unit);

Dao層代碼解析

@Mapper注解的的作用:

1:為了把mapper這個DAO交給Spring管理 

2:為了不再寫mapper映射文件 

3:為了給mapper接口 自動根據一個添加@Mapper注解的接口生成一個實現類	

String fileds = "id, category, sn, assetSn, assetClassifySn, assetCategorySn, " +
        " sn5, model, underWarranty, useState, status, name, department, manufacturers," +
        " factorySn, factoryTime, factoryTime, commissioningTime, workTime, maintainenceTime, " +
        " faultTime, initRunTime, currentRunTime, pesponsible, dutyDepartment, position, power" +
        ", info, statusThreshold, remark, principal, createTime, createUser, updateTime, updateUser";
String tableName = "apparatus_info";

String fileds=“xxx”;這行代碼就是對數據庫表里的字段進行定義 因為Mybatis的sql語句最好不要寫*號

String tableName =“xxx” 這就是相對應的表名

@Select

Mybatis的注解 字面意思 查詢

Mybatis 像是一個xml語言

@Select("<script> " +
        "select " + fileds + " from " + tableName + " " +
        "<where> " +
        "status = 0  " +
        "and department in " +
        "<foreach item='units' index='index' collection='unit' open='(' separator=',' close=')'> " +
        "#{units} " +
        "</foreach> " +
        "<if test=' likeValue != null and likeValue != \"\" '> " +
        "and ${likeKey} like #{likeValue}" +
        "</if> " +
        "<if test=' categorys != null and categorys.size > 0 '> " +
        "and category in " +
        "<foreach item='category' index='index' collection='categorys' open='(' separator=',' close=')'> " +
        "#{category} " +
        "</foreach> " +
        "</if> " +
        "<if test=' useStates != null and useStates.size > 0 '> " +
        "and useState in " +
        "<foreach item='useState' index='index' collection='useStates' open='(' separator=',' close=')'> " +
        "#{useState}" +
        "</foreach>" +
        "</if> " +
        "<if test=' departments != null and departments.size > 0 '> " +
        "and department in " +
        "<foreach item='department' index='index' collection='departments' open='(' separator=',' close=')'> " +
        "#{department} " +
        "</foreach> " +
        "</if> " +
        "</where>" +
        "limit #{start}, #{limit} " +
        "</script> ")

代碼拆分

"select " + fileds + " from " + tableName + " " +
    "<where> " +
    "status = 0  " +
    "and department in " +
    "<foreach item='units' index='index' collection='unit' open='(' separator=',' close=')'> " +
    "#{units} " +
	"</foreach> " 

select 字段 from 表名 where status=0 和 department

按照 status 和 地點 查詢 存入 #{units}

"<foreach item='units' index='index' collection='unit' open='(' separator=',' close=')'> " +
		"#{units} " +
	"</foreach>

foreach 就是腳本中循環

就是把 循環的把 status 和 地點 查詢結果 存入 #{units}

Mybatis 中的特性

代碼拆分

"<if test=' likeValue != null and likeValue != \"\" '> " +
    "and ${likeKey} like #{likeValue}" +
    "</if> " +
    "<if test=' categorys != null and categorys.size > 0 '> " +
    "and category in " +
    "<foreach item='category' index='index' collection='categorys' open='(' separator=',' close=')'> " +
    "#{category} " +

${likeKey} like #{likeValue}
模糊查詢 與dao層對應

要看這行代碼的話需要回到 impl

<if test=' categorys != null and categorys.size > 0 '> 

這行有基礎都可以看得懂吧

后三行

	"and category in " +
    "<foreach item='category' index='index' collection='categorys' open='(' separator=',' close=')'> " +
    "#{category} " +

這三行

和前幾行一樣
就是把category字段下的數據 循環的存入 #{category} 里

中間代碼這些都差不多

具體不講了

最后

"limit #{start}, #{limit} " 

把limt 存入一個Start 又存入一個Limit


先說注解

@Param

@Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),作為Dao層的注解,作用是用於傳遞參數,從而可以與SQL中的的字段名相對應

傳回參數到 后邊定義得 字符串 或者集合 最后在傳入getAllByKey集合里


可以回到Impl

代碼分析

這這些代碼就是為了實現一個分頁功能


HashMap<String, String> map = JSON.parseObject(json, HashMap.class);

JSON.parseObject

JSON JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串

翻譯就是 后端傳過去得 在前端能顯示出來


impl下的后續代碼

List unit=UserUtils.getUserDepartment();

這里是一個控制權限的代碼

通過后台數據庫給你權限 去查詢你能查詢的數據


List apparatusInfos = apparatusInfoDao.getAllByKey(likeKey, likeValue, start, limit, categorys, useStates, departments, unit);

定義一個apparatusInfos集合
用來存放 后端傳過來的

這是Dao層的代碼傳到impl里likeKey, likeValue, start, limit, categorys, useStates, departments, unit 參數

配合前面一個控制until 實現查詢的權限

繼續分析前面的代碼

看到Long count=xxxDao.getCount();

進入getCount 以下是他的Dao層代碼

		@Select("<script> " +
        "select count(id) from " + tableName + " " +
        "<where> " +
        "status = 0  " +
        "and department in" +
        "<foreach item='units' index='index' collection='unit' open='(' separator=',' close=')'> " +
        "#{units} " +
        "</foreach> " +
        "<if test=' likeValue != null and likeValue != \"\" '> " +
        "and ${likeKey} like #{likeValue}" +
        "</if> " +
        "<if test=' categorys != null and categorys.size > 0 '> " +
        "and category in " +
        "<foreach item='category' index='index' collection='categorys' open='(' separator=',' close=')'> " +
        "#{category} " +
        "</foreach> " +
        "</if> " +
        "<if test=' useStates != null and useStates.size > 0 '> " +
        "and useState in " +
        "<foreach item='useState' index='index' collection='useStates' open='(' separator=',' close=')'> " +
        "#{useState}" +
        "</foreach>" +
        "</if> " +
        "<if test=' departments != null and departments.size > 0 '> " +
        "and department in " +
        "<foreach item='department' index='index' collection='departments' open='(' separator=',' close=')'> " +
        "#{department} " +
        "</foreach> " +
        "</if> " +
        "</where>" +
        "</script> ")
Long getCount(@Param("likeKey") String likeKey,
              @Param("likeValue") String likeValue,
              @Param("categorys") List<String> categorys,
              @Param("useStates") List<String> useStates,
              @Param("departments") List<String> departments,
              @Param("unit") List<String> unit);

前面講過了 具體不講了

這幾行代碼呢 就是把后端傳過來的數據進行分頁 分頁之后進行顯示

把所有的數據呢返回到date集合里


Dao層與Impl層 講解完畢 回到Controller層

public R list(@RequestParam HashMap<String, Object> params)

先說一下這個public R list

R:

public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;

public R() {
	/**
	 * 下面是常見的HTTP狀態碼:
	 * 200 - 請求成功
	 * 301 - 資源(網頁等)被永久轉移到其它URL
	 * 404 - 請求的資源(網頁等)不存在
	 * 500 - 內部服務器錯誤
	 *
	 * 可以參考這樣的設計 錯誤歸類  +++9/【·方便尋找
	 * #1000~1999 區間表示參數錯誤
	 * #2000~2999 區間表示用戶錯誤信息
	 * #3000~3999區間表示接口異常
	 * */
	put("code", 0);//返回一個code狀態碼

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

這個就是 前后交互 后端傳歸來一個狀態值 和信息 必須得有!

附上一個講解較為詳細的文檔

https://www.jianshu.com/p/fa75acba5b07
		轉自簡述作者 碼不動

@RequestParam:將請求參數綁定到你控制器的方法參數上

HashMap<String, Object> date = apparatusInfoService.getAll(params);

這行代碼就是在Service層中定義的接口getAll得到所有參數

Long num = (Long) date.get("num");

定義一個長整型 num 得到num里的參數

List<ApparatusInfoEntity> apparatusInfos = (List<ApparatusInfoEntity>) date.get("apparatusInfos");

這行就是得到apparatusInfos這個參數的所有信息 放到一個新集合里

List<String> useState = sysDdictionariesService.selectNameByKeyWord("使用狀態");

這行有定義了一個新接口 后期運行時候發現少定義的實現狀態 重新定義的
進入到他的Service 看他的IpmlDao

定義了一個這樣的封裝

主要是為了傳遞他的 信息 code 就是使用狀態


List<String> dutyDepartment = UserUtils.getUserDepartment();

一個篩選工具 篩選需要的東西


回到controller

拋出一個異常 看一下能不能 把設備分類名稱 傳遞過來 放到 JSONObiect

這里是對應的service接口定義

這里是對應的Impl下的實現

這里是對應的工具類unitl具體代碼邏輯

翻譯

為了前端交互 json 的定義
在最前邊 什么是json里有寫

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


翻譯人能聽懂的話就是 **我從后端傳到前端的數據能顯示出來前端需要的格式**

最后Controller
這幾行代碼

在本地text時候 顯示我要傳遞的數據

一個前后交互的基本功能 基本邏輯 一般就到此了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM