Web后端开发案例
一、准备工作
-
需求 & 环境
- 环境搭建:后端工程与数据库环境的准备
- Spring boot工程,选择依赖。(web,mybatis,mysql,lombok)
- 在配置文件中引入配置信息,准备对应的实体类
- 三层架构的基础代码(controller,service,mapper)
- 准备mapper,service,controller基础结构、接口
-
开发规范
-
案例基于当前最为主流的前后端分离开发模式进行开发。
-
在正式开发之前会定义一个接口文档,前端和后端开发人员需要遵守这一份开发文档进行开发接口。
-
接口文档是由后端人员根据原型和需求开发的。
-
前端后端在交互的时候使用Restful风格的接口
- REST:表述性状态转换,是一种软件架构风格
-
- 通过URL来定位资源
- 通过HTTP动词描述操作
- REST是风格,是约定方式,不是规定,可以打破。
- 描述功能模块通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。如:users、emps、books…
-
- REST:表述性状态转换,是一种软件架构风格
-
统一响应结果:Result
-
@Data @NoArgsConstructor @AllArgsConstructor public class Result{ private Integer code; //响应码 private String msg; //请求信息 描述字符串 private Object data; //返回的数据 public static Result success(){ return new Result(1,"success",null); } public static Result success(Object data){ return new Result(1,"success",data); } public static Result error(String msg){ return new Result(0,msg,null); } }
-
开发流程:
- 查看页面原型,明确需求
- 定义表结构和接口文档
- 阅读接口文档
- 思路分析
- 接口开发
- 接口测试
- 前后端联调
-
二、部门管理开发
查询:
- 浏览接口文档,明确要求。
- 前端发送请求之后会请求到controllor这个方法
- controllor调用service接口中的方法获取数据
- service调用mapper接口中的方法获取数据
删除:
- 请求路径是/depts/
- 使用注解@PathVariable来得到请求的路径
- 请求方式是DELETE,所以使用@DeleteMapping
新增部门:
- 将请求的表单数据封装为一个对象
- 使用@RequestBody注解
- @RequestBody Dept dept
- 在service层中补全时间信息
- 使用@RequestBody注解
三、员工管理开发
分页查询:
-
-
查看api规则发现,返回的json数据中有total和rows两个字段,那我们可以新建一个PageBean类作为分页查询的返回对象
-
注意:在查询时,因为mapper中的形参不是对象或者单个参数,所以需要手动指定每个参数的字段名
-
使用@Param注解来指定对应的字段名。
@Select("select * from emp limit #{start},#{pageSize}") List<Emp> pageSelect(@Param("start") Integer start, @Param("pageSize") Integer pageSize);
注意:分页查询时,limit后的两个参数为起始位置和查询单页数量。
-
-
分页查询插件:PageHelper
- 引入依赖
- 使用:
- PageHelper.startPage(pageNum,pageSize);
- List<Emp> list = empMapper.lkist();
- Page<Emp> page = (Page<Emp>) list;
条件分页查询
- 要使用动态SQL实现,因为SQL语句比较复杂,所以使用XML方式配置
- 注意这里的name可能传入空字符串,需要再加一个判断条件以确保不会是空字符串
批量删除员工
- 接受的参数使用逗号分割,并使用动态sql来执行删除语句
新增员工
-
-
@PostMapping public Result save(@RequestBody Emp emp){ log.info("新增员工:{}",emp); empService.save(emp); return Result.success(); }
-
//新增员工方法 void save(Emp emp);
-
//实现类: @Override public void save(Emp emp){ LocalDateTime time = LocalDateTime.now(); emp.setCreateTime(time); emp.setUpdateTime(time); empMapper.insert(); }
-
//新增员工 @Insert("insert into emp(username,name,gender,image,job,entrydate,dept_id,create_time,update_time) values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})") void insert(Emp emp);
-
文件上传
-
简介:
- 文件上传是指将本地的图片,视频,音频等文件上传到服务器,提供给用户浏览或下载的过程。
- 文件上传在项目中的应用非常广泛,我们经常发微博,发微信朋友圈都用到了文件上传功能。
-
前端程序:
-
- 必须定义form表单,其中一个类型为file
- 提交方式必须是post方式
- 必须指定编码格式,在form表单的属性中添加enctype=“multipart/form-data”
-
-
后端程序:
-
- 可以使用spring boot提供的接受文件api
@RestController public class UploadController{ @PostMapping("/upload") public Result upload(String username, Integer age, MultipartFile image){ return success(); } }
-
形参名和form表单中的name属性保持一致。
-
请求响应完毕后临时文件会被删除,所以需要保存上传的文件。
本地存储
- 在服务器端,接受到上传上来的文件之后,将文件存储在本地服务器的磁盘中。
- spring中已经自带一个方法:transferTo(new File(“path”))
-
这里的path就是存储的文件位置,文件名可以使用前端传递的文件名
- 获取原始文件名:getOriginalFilename()
-
注意:文件夹目录必须存在
-
-
-
云存储
-
阿里云OSS
- 阿里云对象存储OSS,是一款海量、安全、低成本、高可靠的云存储服务,使用OSS,您可以通过网络随时存储和调用包括文本,图片,音频和视频在内的各种文件。
-
通用思路:
- 准备工作 -> 参考官方SDK编写入门程序 -> 集成使用
-
阿里云入门:
-
官方示例代码:Java简单上传 (aliyun.com)
-
package com.heimamagdemo; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.PutObjectResult; import java.io.FileInputStream; import java.io.InputStream; public class UploadDemo { public static void main(String[] args) throws Exception { // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 String accessKeyId = "yourAccessKeyId"; String accessKeySecret = "yourAccessKeySecret"; // 填写Bucket名称,例如examplebucket。 String bucketName = "examplebucket"; // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 String objectName = "exampledir/exampleobject.txt"; // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。 // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。 String filePath= "D:\\localpath\\examplefile.txt"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { InputStream inputStream = new FileInputStream(filePath); // 创建PutObjectRequest对象。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream); // 设置该属性可以返回response。如果不设置,则返回的response为空。 putObjectRequest.setProcess("true"); // 创建PutObject请求。 PutObjectResult result = ossClient.putObject(putObjectRequest); // 如果上传成功,则返回200。 System.out.println(result.getResponse().getStatusCode()); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
-
-
可以定义一个工具类来方便使用。
-
package com.heimamagdemo.utils; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.model.*; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.net.URL; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.List; @Component public class AliOSSUtil { // private static final String endpoint = AliOSSConfig.getInstance().getEndpoint(); // private static final String accessKeyId = AliOSSConfig.getInstance().getAccessKeyId(); // private static final String accessKeySecret = AliOSSConfig.getInstance().getAccessKeySecret(); // private static final String bucketName = AliOSSConfig.getInstance().getBucketName(); private static final String endpoint = "oss-cn-beijing.aliyuncs.com"; private static final String accessKeyId="LTAI5tGjByv5NXuywUAnrLiy"; private static final String accessKeySecret="EP1CXYMWmeZO5igK7hMd9rZbYTBj99"; private static final String bucketName="web-myapp"; /** * 将文件上传到阿里OSS * * @param sourceFilePathName 本地文件 * @param aimFilePathName 在阿里OSS中保存的可以包含路径的文件名 * @return 返回上传后文件的访问路径 * @throws FileNotFoundException */ public static String upload(String sourceFilePathName, String aimFilePathName) throws FileNotFoundException { FileInputStream is = new FileInputStream(sourceFilePathName); if (aimFilePathName.startsWith("/")) { aimFilePathName = aimFilePathName.substring(1); } // 如果需要上传时设置存储类型与访问权限,请参考以下示例代码。 ObjectMetadata metadata = new ObjectMetadata(); int indexOfLastDot = aimFilePathName.lastIndexOf("."); String suffix = aimFilePathName.substring(indexOfLastDot); metadata.setContentType(getContentType(suffix)); //避免文件覆盖 aimFilePathName = aimFilePathName.substring(0, indexOfLastDot) + System.currentTimeMillis() + suffix; PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, aimFilePathName, is); //避免访问时将图片下载下来 putObjectRequest.setMetadata(metadata); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ossClient.putObject(putObjectRequest); Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100); URL url = ossClient.generatePresignedUrl(bucketName, aimFilePathName, expiration); // 关闭ossClient ossClient.shutdown(); return url.toString(); } /** * 网络实现上传头像到OSS * * @param multipartFile * @return */ public static String upload(MultipartFile multipartFile) throws IOException { // 获取上传的文件的输入流 InputStream inputStream = multipartFile.getInputStream(); // 获取文件名称 String fileName = multipartFile.getOriginalFilename(); // 避免文件覆盖 int i = fileName.lastIndexOf("."); String suffix = fileName.substring(i); fileName = fileName.substring(0, i) + System.currentTimeMillis() + suffix; // 把文件按照日期进行分类 // 获取当前日期 String datePath = DateTimeFormatter.ISO_DATE.format(LocalDate.now()); // 拼接fileName fileName = datePath + "/" + fileName; // 如果需要上传时设置存储类型与访问权限 ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf(".")))); // 上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream); putObjectRequest.setMetadata(metadata); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ossClient.putObject(putObjectRequest); //文件访问路径 Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100); URL url = ossClient.generatePresignedUrl(bucketName, fileName, expiration); // 关闭ossClient ossClient.shutdown(); // 把上传到oss的路径返回 return url.toString(); } /** * 返回contentType * * @param FileNameExtension * @return */ private static String getContentType(String FileNameExtension) { if (FileNameExtension.equalsIgnoreCase(".bmp")) { return "image/bmp"; } if (FileNameExtension.equalsIgnoreCase(".gif")) { return "image/gif"; } if (FileNameExtension.equalsIgnoreCase(".jpeg") || FileNameExtension.equalsIgnoreCase(".jpg") || FileNameExtension.equalsIgnoreCase(".png") ) { return "image/jpg"; } return "image/jpg"; } /** * 列举 指定路径下所有的文件的文件名 * 如果要列出根路径下的所有文件,path= "" * * @param path * @return */ public static List<String> listFileName(String path) { List<String> res = new ArrayList<>(); // 构造ListObjectsRequest请求。 ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // 设置prefix参数来获取fun目录下的所有文件。 listObjectsRequest.setPrefix(path); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 列出文件。 ObjectListing listing = ossClient.listObjects(listObjectsRequest); // 遍历所有文件 for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { System.out.println(objectSummary.getKey()); } // 关闭OSSClient。 ossClient.shutdown(); return res; } /** * 列举文件下所有的文件url信息 */ public static List<String> listFileUrl(String path) { List<String> res = new ArrayList<>(); // 构造ListObjectsRequest请求 ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName); // 设置prefix参数来获取fun目录下的所有文件。 listObjectsRequest.setPrefix(path); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 列出文件。 ObjectListing listing = ossClient.listObjects(listObjectsRequest); // 遍历所有文件。 for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { //文件访问路径 Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100); URL url = ossClient.generatePresignedUrl(bucketName, objectSummary.getKey(), expiration); res.add(url.toString()); } // 关闭OSSClient。 ossClient.shutdown(); return res; } /** * 判断文件是否存在 * * @param objectName * @return */ public static boolean isFileExist(String objectName) { OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); boolean res = ossClient.doesObjectExist(bucketName, objectName); return res; } /** * 通过文件名下载文件 * * @param objectName 要下载的文件名 * @param localFileName 本地要创建的文件名 */ public static void downloadFile(String objectName, String localFileName) { OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。 ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(localFileName)); // 关闭OSSClient。 ossClient.shutdown(); } /** * 删除文件或目录 * * @param objectName */ public static void delelteFile(String objectName) { OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ossClient.deleteObject(bucketName, objectName); ossClient.shutdown(); } /** * 批量删除文件或目录 * * @param keys */ public static void deleteFiles(List<String> keys) { OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 删除文件。 DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys)); java.util.List<String> deletedObjects = deleteObjectsResult.getDeletedObjects(); ossClient.shutdown(); } /** * 创建文件夹 * * @param folder * @return */ public static String createFolder(String folder) { // 文件夹名 final String keySuffixWithSlash = folder; OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 判断文件夹是否存在,不存在则创建 if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) { // 创建文件夹 ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0])); // 得到文件夹名 OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash); String fileDir = object.getKey(); ossClient.shutdown(); return fileDir; } return keySuffixWithSlash; } }
-
修改员工信息
- 点击修改后的数据回显。
- 修改员工。
配置文件
-
参数配置化:
-
可以在springboot的配置文件中自定义配置的字段。
-
然后通过注解@Value(“${字段名}”)来注入参数。
-
@Value("${aliyun.oss.endpoint}") private static String endpoint; @Value("${aliyun.oss.accessKeyId}") private static String accessKeyId; @Value("${aliyun.oss.accessKeySecret}") private static String accessKeySecret; @Value("${aliyun.oss.bucketName}") private static String bucketName;
-
-
-
yaml配置文件:
-
server: port: 8081 address: 127.0.0.1
-
-
-
-
@ConfigurationProperties注解:
- 可以自动将配置参数载入到对象的属性中
- 属性名必须和参数名一致
- 必须为实体类中的参数提供get/set方法
- 这个类必须由AOC管理。
- 可以自动将配置参数载入到对象的属性中
基础登录功能
-
登录功能
-
查询用户信息
-
SELECT COUNT(id) FROM emp WHERE username = #{} and password = #{}
-
-
-
-
-
登录校验
- 在我们收到浏览器请求后,先对用户进行校验。
- 实现思路:
- 首先http是无状态协议,每一次请求都是独立的
- 我们可以在登录成功之后存储一个登录标记。
- 假设员工已经登录了,我们就执行正常的业务操作,否则返回错误信息。
- 前端拿到错误信息之后自动跳转到登录界面。
- 我们可以通过同一拦截技术来完成对浏览器所有的请求进行拦截。
- 在调用login接口时,如果登录成功则进行标记
- 如果通过拦截时能够验证标记则放行
- 如果不能通过验证则返回错误信息。
- 登录标记:
- 用户在登录成功之后,每一次请求中,都能获取到该标记。
- 统一拦截:
- Servlet中提供的:Filter
- Spring中提供的:Interceptor
登录校验
-
会话技术
- 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接。会话结束。在一次会话中可以包含多次请求和响应。
- 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一会话的多次请求间共享数据。
- 会话跟踪技术:
- 客户端会话跟踪技术:Cookie
- 服务端会话跟踪技术:Session
- 令牌技术(当前最主流)
- 会话跟踪方案对比:
- Cookie:
- Session:
- 令牌技术:
- Cookie:
-
JWT令牌
- 全称:JSON Web Token
- 定义了一种简洁的,自包含的格式,用于在通讯双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。
- 组成:
- 场景:登录认证。
- 登录成功后,生成令牌
- 后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,再处理。
- 生成JWT令牌:
- 解析JWT令牌:
-
登录后下发令牌:
- 引入JWT令牌操作工具类
- 登录成功后,调用工具生成JWT令牌,并返回。
- 可以使用JWTUtils库来完成这个操作
-
过滤器Filter
-
概念:
- Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一
- 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
- 过滤器一般完成一些通用的操作,如登录校验、统一编码处理、敏感字符处理等。
-
快速入门:
-
-
-
定义Filter:
- 定义一个类,实现Filter接口,并重写所有的方法。(javax.servlet包下)
-
配置Filter:
- Filter类上加上@WebFilter注解,配置拦截资源的路径。
- 引导类上加@ServletComponentScan注解,开启Servlet组件支持。
-
-
放行
-
filterChain.doFilter(servletRequest, servletResponse);
-
-
-
详解
- 执行流程
- doFilter:
- 放行前逻辑
- 放行
- 放行后逻辑
- 放行后访问对应资源,还会返回过滤器中,过滤器中的代码继续运行。
- doFilter:
- 拦截路径
- 拦截具体路径
- /login
- 目录拦截
- /emps/*
- 拦截所有
- /*
- 拦截具体路径
- 过滤器链
- 在一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链。
- 顺序:
- 注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。
- 登录校验:
- 执行流程
-
-
拦截器Interceptor
-
简介&快速入门
-
概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。
-
作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
-
快速入门:
- 定义拦截器,实现HandlerInterceptor接口,并重写所有方法
- 注册拦截器
-
详解
-
拦截路径
- addPathPatterns设置需要拦截的路径
- excludePathPatterns设置不需要拦截的路径
- /*:一级路径
- /**:多级路径
- /depts/*:下一级
- /depts/**:任意下一级或多级
-
执行流程
-
-
-
-
-
通过注解校验Token
-
@interface
package com.heimamagdemo.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TokenCheck { }
-
class
package com.heimamagdemo.aspect; import com.hanzoy.utils.JWTUtils; import com.heimamagdemo.pojo.Result; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Component @Aspect @Slf4j public class TokenCheck { @Autowired private JWTUtils jwtUtils; @Pointcut("@annotation(com.heimamagdemo.annotation.TokenCheck)") public void tokenCheckAspect() { } @Around("tokenCheckAspect()") public Object aroundTokenCheck(ProceedingJoinPoint joinPoint)throws Throwable { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); // 从请求头中获取token String token = request.getHeader("Token"); // 校验token是否有效 if (!StringUtils.hasLength(token) || !jwtUtils.checkToken(token)) { //请求ip log.warn("IP:{} TokenCheck: token isinvalid!",request.getRemoteHost()); // 返回Result.error()对象 return Result.error("NOT_LOGIN"); } // 执行被增强的方法,并获取其返回值 // 对返回值进行处理 // ... return joinPoint.proceed(); } }
-
异常处理
-
当遇到错误时,返回的数据为错误信息的封装,并不符合开发规范,所以前端不能解析出这个数据。
-
程序在开发过程中不可避免的会遇到异常现象。
-
出现异常,该如何处理?
-
方案一:在controller中使用try…catch处理
-
方案二:使用全局异常处理器(简单,优雅,推荐)
-
-
如何定义全局异常处理器
-
定义一个类,使用@RestControllerAdvice
-
在方法上加上@ExceptionHandler(Exception.class)参数为捕获的异常类型
package com.heimamagdemo.exception; import com.heimamagdemo.pojo.Result; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * 全局异常处理器 * @author pqcmm */ @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理所有异常 * @param e 异常 * @return Result */ @ExceptionHandler(Exception.class) public Result error(Exception e){ e.printStackTrace(); return Result.error("对不起,操作失败!"); } }
-
API接口开发文档
1. 部门管理
1.1 部门列表查询
1.1.1 基本信息
请求路径:/depts
请求方式:GET
接口描述:该接口用于部门列表数据查询
1.1.2 请求参数
无
1.1.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object[ ] | 非必须 | 返回的数据 |
|- id | number | 非必须 | id |
|- name | string | 非必须 | 部门名称 |
|- createTime | string | 非必须 | 创建时间 |
|- updateTime | string | 非必须 | 修改时间 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": [
{
"id": 1,
"name": "学工部",
"createTime": "2022-09-01T23:06:29",
"updateTime": "2022-09-01T23:06:29"
},
{
"id": 2,
"name": "教研部",
"createTime": "2022-09-01T23:06:29",
"updateTime": "2022-09-01T23:06:29"
}
]
}
1.2 删除部门
1.2.1 基本信息
请求路径:/depts/
请求方式:DELETE
接口描述:该接口用于根据ID删除部门数据
1.2.2 请求参数
参数格式:路径参数
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
id | number | 必须 | 部门ID |
请求参数样例:
/depts/1
1.2.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
1.3 添加部门
1.3.1 基本信息
请求路径:/depts
请求方式:POST
接口描述:该接口用于添加部门数据
1.3.2 请求参数
格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
name | string | 必须 | 部门名称 |
请求参数样例:
{
"name": "教研部"
}
1.3.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
1.4 根据ID查询
1.4.1 基本信息
请求路径:/depts/
请求方式:GET
接口描述:该接口用于根据ID查询部门数据
1.4.2 请求参数
参数格式:路径参数
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
id | number | 必须 | 部门ID |
请求参数样例:
/depts/1
1.4.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
|- id | number | 非必须 | id |
|- name | string | 非必须 | 部门名称 |
|- createTime | string | 非必须 | 创建时间 |
|- updateTime | string | 非必须 | 修改时间 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": {
"id": 1,
"name": "学工部",
"createTime": "2022-09-01T23:06:29",
"updateTime": "2022-09-01T23:06:29"
}
}
1.5 修改部门
1.5.1 基本信息
请求路径:/depts
请求方式:PUT
接口描述:该接口用于修改部门数据
1.5.2 请求参数
格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
id | number | 必须 | 部门ID |
name | string | 必须 | 部门名称 |
请求参数样例:
{
"id": 1,
"name": "教研部"
}
1.5.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
2. 员工管理
2.1 员工列表查询
2.1.1 基本信息
请求路径:/emps
请求方式:GET
接口描述:该接口用于员工列表数据的条件分页查询
2.1.2 请求参数
参数格式:queryString
参数说明:
参数名称 | 是否必须 | 示例 | 备注 |
---|---|---|---|
name | 否 | 张 | 姓名 |
gender | 否 | 1 | 性别 , 1 男 , 2 女 |
begin | 否 | 2010-01-01 | 范围匹配的开始时间(入职日期) |
end | 否 | 2020-01-01 | 范围匹配的结束时间(入职日期) |
page | 是 | 1 | 分页查询的页码,如果未指定,默认为1 |
pageSize | 是 | 10 | 分页查询的每页记录数,如果未指定,默认为10 |
请求数据样例:
/emps?name=张&gender=1&begin=2007-09-01&end=2022-09-01&page=1&pageSize=10
2.1.3 响应数据
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
code | number | 必须 | 响应码, 1 成功 , 0 失败 | ||
msg | string | 非必须 | 提示信息 | ||
data | object | 必须 | 返回的数据 | ||
|- total | number | 必须 | 总记录数 | ||
|- rows | object [] | 必须 | 数据列表 | item 类型: object | |
|- id | number | 非必须 | id | ||
|- username | string | 非必须 | 用户名 | ||
|- name | string | 非必须 | 姓名 | ||
|- password | string | 非必须 | 密码 | ||
|- entrydate | string | 非必须 | 入职日期 | ||
|- gender | number | 非必须 | 性别 , 1 男 ; 2 女 | ||
|- image | string | 非必须 | 图像 | ||
|- job | number | 非必须 | 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师 | ||
|- deptId | number | 非必须 | 部门id | ||
|- createTime | string | 非必须 | 创建时间 | ||
|- updateTime | string | 非必须 | 更新时间 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": {
"total": 2,
"rows": [
{
"id": 1,
"username": "jinyong",
"password": "123456",
"name": "金庸",
"gender": 1,
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-53B.jpg",
"job": 2,
"entrydate": "2015-01-01",
"deptId": 2,
"createTime": "2022-09-01T23:06:30",
"updateTime": "2022-09-02T00:29:04"
},
{
"id": 2,
"username": "zhangwuji",
"password": "123456",
"name": "张无忌",
"gender": 1,
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-53B.jpg",
"job": 2,
"entrydate": "2015-01-01",
"deptId": 2,
"createTime": "2022-09-01T23:06:30",
"updateTime": "2022-09-02T00:29:04"
}
]
}
}
2.2 删除员工
2.2.1 基本信息
请求路径:/emps/
请求方式:DELETE
接口描述:该接口用于批量删除员工的数据信息
2.2.2 请求参数
参数格式:路径参数
参数说明:
参数名 | 类型 | 示例 | 是否必须 | 备注 |
---|---|---|---|---|
ids | 数组 array | 1,2,3 | 必须 | 员工的id数组 |
请求参数样例:
/emps/1,2,3
2.2.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
2.3 添加员工
2.3.1 基本信息
请求路径:/emps
请求方式:POST
接口描述:该接口用于添加员工的信息
2.3.2 请求参数
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 备注 |
---|---|---|---|
username | string | 必须 | 用户名 |
name | string | 必须 | 姓名 |
gender | number | 必须 | 性别, 说明: 1 男, 2 女 |
image | string | 非必须 | 图像 |
deptId | number | 非必须 | 部门id |
entrydate | string | 非必须 | 入职日期 |
job | number | 非必须 | 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师 |
请求数据样例:
{
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-03-07-37-38222.jpg",
"username": "linpingzhi",
"name": "林平之",
"gender": 1,
"job": 1,
"entrydate": "2022-09-18",
"deptId": 1
}
2.3.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
2.4 根据ID查询
2.4.1 基本信息
请求路径:/emps/
请求方式:GET
接口描述:该接口用于根据主键ID查询员工的信息
2.4.2 请求参数
参数格式:路径参数
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
id | number | 必须 | 部门ID |
请求参数样例:
/emps/1
2.4.3 响应数据
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
code | number | 必须 | 响应码, 1 成功 , 0 失败 | ||
msg | string | 非必须 | 提示信息 | ||
data | object | 必须 | 返回的数据 | ||
|- id | number | 非必须 | id | ||
|- username | string | 非必须 | 用户名 | ||
|- name | string | 非必须 | 姓名 | ||
|- password | string | 非必须 | 密码 | ||
|- entrydate | string | 非必须 | 入职日期 | ||
|- gender | number | 非必须 | 性别 , 1 男 ; 2 女 | ||
|- image | string | 非必须 | 图像 | ||
|- job | number | 非必须 | 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师 | ||
|- deptId | number | 非必须 | 部门id | ||
|- createTime | string | 非必须 | 创建时间 | ||
|- updateTime | string | 非必须 | 更新时间 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": {
"id": 2,
"username": "zhangwuji",
"password": "123456",
"name": "张无忌",
"gender": 1,
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-53B.jpg",
"job": 2,
"entrydate": "2015-01-01",
"deptId": 2,
"createTime": "2022-09-01T23:06:30",
"updateTime": "2022-09-02T00:29:04"
}
}
2.5 修改员工
2.5.1 基本信息
请求路径:/emps
请求方式:PUT
接口描述:该接口用于修改员工的数据信息
2.5.2 请求参数
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 备注 |
---|---|---|---|
id | number | 必须 | id |
username | string | 必须 | 用户名 |
name | string | 必须 | 姓名 |
gender | number | 必须 | 性别, 说明: 1 男, 2 女 |
image | string | 非必须 | 图像 |
deptId | number | 非必须 | 部门id |
entrydate | string | 非必须 | 入职日期 |
job | number | 非必须 | 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师 |
请求数据样例:
{
"id": 1,
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-03-07-37-38222.jpg",
"username": "linpingzhi",
"name": "林平之",
"gender": 1,
"job": 1,
"entrydate": "2022-09-18",
"deptId": 1
}
2.5.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据 |
响应数据样例:
{
"code":1,
"msg":"success",
"data":null
}
2.6 文件上传
2.6.1 基本信息
请求路径:/upload
请求方式:POST
接口描述:上传图片接口
2.6.2 请求参数
参数格式:multipart/form-data
参数说明:
参数名称 | 参数类型 | 是否必须 | 示例 | 备注 |
---|---|---|---|---|
image | file | 是 |
2.6.3 响应数据
参数格式:application/json
参数说明:
参数名 | 类型 | 是否必须 | 备注 |
---|---|---|---|
code | number | 必须 | 响应码,1 代表成功,0 代表失败 |
msg | string | 非必须 | 提示信息 |
data | object | 非必须 | 返回的数据,上传图片的访问路径 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-0400.jpg"
}
3. 其他接口
3.1 登录
3.1.1 基本信息
请求路径:/login
请求方式:POST
接口描述:该接口用于员工登录Tlias智能学习辅助系统,登录完毕后,系统下发JWT令牌。
3.1.2 请求参数
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 备注 |
---|---|---|---|
username | string | 必须 | 用户名 |
password | string | 必须 | 密码 |
请求数据样例:
{
"username": "jinyong",
"password": "123456"
}
3.1.3 响应数据
参数格式:application/json
参数说明:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
code | number | 必须 | 响应码, 1 成功 ; 0 失败 | ||
msg | string | 非必须 | 提示信息 | ||
data | string | 必须 | 返回的数据 , jwt令牌 |
响应数据样例:
{
"code": 1,
"msg": "success",
"data": "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6YeR5bq4IiwiaWQiOjEsInVzZXJuYW1lIjoiamlueW9uZyIsImV4cCI6MTY2MjIwNzA0OH0.KkUc_CXJZJ8Dd063eImx4H9Ojfrr6XMJ-yVzaWCVZCo"
}
3.1.4 备注说明
用户登录成功后,系统会自动下发JWT令牌,然后在后续的每次请求中,都需要在请求头header中携带到服务端,请求头的名称为 token ,值为 登录时下发的JWT令牌。
如果检测到用户未登录,则会返回如下固定错误信息:
{ "code": 0, "msg": "NOT_LOGIN", "data": null }