test2

项目讲解

具体功能如何实现


需要到的技术(纯后端开发)

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项目主要分为一下三层

test2

  1. contorller
  2. servise
  3. dao

流程图:

test2


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

}

test2

程序开头 有这4个注解

注解:spring 4.0特性 帮助开发

分析一下这4个注解

@Api(tags = "设备台账-设备列表")这是个swagerr注解
表示标识这个类是swagger的资源

test2

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


再往下看代码


test2

@Autowired

@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法

翻译一下就是 把你的Controller与service连接起来

再看

test2

点进来

test2

就进到了你的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包是个什么东西


继续上面代码
test2

又是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")

test2

这里的和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在这!

test2

这里实现了Controller层交互service层。

service层

test2

service下有两个

一个叫做xxxxService

另一个叫xxxxServiceImpl

Service 是接口

Impl 是实现


xxxService 代码

public interface ApparatusInfoService extends IService<ApparatusInfoEntity> {
//获取所有数据列表,支持条件搜索和分页
HashMap<String,Object> getAll(Map<String, Object> params);
}

test2

上面是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;

直观的就是用在了这行代码

要注意同样的代码在不同的层如和耦合在一起的

test2

继续分析Impl代码 我把实现的第一代码整个copy

test2

前几个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^
上一篇:SSH配置—Linux下实现免密码登录


下一篇:05-Java中的String类