栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

软件工程应用与实践(15)——请求与响应

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

软件工程应用与实践(15)——请求与响应

2021SC@SDUSC

文章目录
    • 一、概述
    • 二、源码分析
      • 2.1 响应
      • 2.2 请求
    • 三、总结

一、概述

在老年健康知识图谱系统中,后端与前端的交互是很重要的,在前端向后端发送请求的过程中,后端需要向前端返回响应的数据,而本篇博客将重点针对本项目中关于请求与响应的部分做相关分析。

经过小组讨论,决定由我分析关于响应和请求的部分,关于这块内容,在项目中的源码主要涉及一下几个部分

在前端中,有封装好的,发送请求的js文件,这些js文件中封装了一个个请求的函数,在前端vue页面中可以调用。

而在后端,则对请求包装了相应的相应对象,这些相应对象发送到前端之后,前端会根据不同的响应对象给出不同的处理。而在后端处理的过程中,可能会遇到一些异常情况,而老年健康知识图谱系统中,又对异常情况进行了相应的处理。

在下面的源码分析中,我会对这些部分做进一步分析。

二、源码分析 2.1 响应

为了更好地理解请求与响应的交互关系,我决定先阅读响应部分的源码,之后再理解请求部分的源码。

首先我们可以看到,在项目中,定义了三个文件夹,这三个文件夹分别描述了

  • 后端处理前端请求时可能遇到的异常
  • 后端处理异常
  • 返回给前端的具体的响应信息

    1.响应信息

我们首先阅读响应信息部分的源码

首先我们可以看到,在对应的文件夹中,有一个baseResponse类

在这个类中,描述了如下信息

  • 两个属性,相应的状态码和具体的信息
  • 有参构造,无参构造及相应的get和set方法
public class baseResponse {

    private int statusCode = 200;
    private String message;

    public baseResponse(int status, String message) {
        this.statusCode = status;
        this.message = message;
    }

    public baseResponse() {
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }
}

可以知道,这个类的主要作用是,用于描述正常执行时的响应状态。

接下来我们看到下一个类TableResultResponse,从类名上可以知道,这个类主要用于返回与表格相关的相应数据

  • 使用一个TableData对象存储表格数据
  • 在内部类TableData中,一个List类型的变量存储了表格每一行的数据,而另一个total变量则存储了表格的行数
public class TableResultResponse extends baseResponse {

    TableData data;

    public TableResultResponse(long total, List rows) {
        this.data = new TableData(total, rows);
    }

    public TableResultResponse() {
        this.data = new TableData();
    }

    TableResultResponse total(int total) {
        this.data.setTotal(total);
        return this;
    }

    TableResultResponse total(List rows) {
        this.data.setRows(rows);
        return this;
    }

    public TableData getData() {
        return data;
    }

    public void setData(TableData data) {
        this.data = data;
    }

    class TableData {
        long total;
        List rows;

        public TableData(long total, List rows) {
            this.total = total;
            this.rows = rows;
        }

        public TableData() {
        }

        public long getTotal() {
            return total;
        }

        public void setTotal(long total) {
            this.total = total;
        }

        public List getRows() {
            return rows;
        }

        public void setRows(List rows) {
            this.rows = rows;
        }
    }
}

本项目通过将表格数据的返回封装成一个对象,并在该类中使用了范型的技术,从而提高了利用效率,这是值得借鉴的。

接下来我们看到下一个类ObjectRestResponse,这个类主要用于返回对象类型的数据

  • 使用一个范型变量data存储对象的数据
  • 建立了相关的构造方法,get和set方法用于赋值
public class ObjectRestResponse extends baseResponse {

    T data;
    
    public ObjectRestResponse data(T data) {
        this.setData(data);
        return this;
    }
    public T getData() {
        return data;
    }

    public ObjectRestResponse setData(T data) {
        this.data = data;
        return this;
    }
}

本类与上面的类作用相似,只不过上面的类用于返回表格数据,而本类用于返回对象类型的数据

此外,这两个类都继承了上面的baseResponse类,所以我们可以知道,对与baseResponse类来说,他存在三种形式,第一种是原生的形式,第二种是返回表格数据的形式,第三种是返回对象类型数据的形式

接下来我们关注返回错误信息的类

关于错误信息的类,本项目中主要有两个

第一个是TokenForbiddenResponse类,同样继承了baseResponse类,在这个类中,直接调用父类的构造方法,传入对应的状态码和消息。

public class TokenForbiddenResponse  extends baseResponse {
    public TokenForbiddenResponse(String message) {
        super(RestCodeConstants.TOKEN_FORBIDDEN_CODE, message);
    }
}

第二个类与上面的类类似,同样返回了一个错误码

public class TokenErrorResponse extends baseResponse {
    public TokenErrorResponse(String message) {
        super(RestCodeConstants.TOKEN_ERROR_CODE, message);
    }
}

而错误码在项目中同样有定义,定义为类中的静态变量,并且设置为常量,不可修改

public class RestCodeConstants {
    public static final int TOKEN_ERROR_CODE = 40101;
    public static final int TOKEN_FORBIDDEN_CODE = 40301;
}

2.异常类定义及处理

在本项目中,对后端可能发生的异常进行了相关的处理,经过小组讨论,将由我的另一个队友对异常处理部分做详尽的描述,这里我只对异常处理做简单的介绍。

本项目的异常处理与之前的上面的响应处理类似,都先定义了一个basexxx作为基类,之后对该基类进行拓展,最终完善整个功能

在异常处理这一部分,本项目同样使用了一个基类,即baseException,这个类首先继承了RuntimeException,并定义了相关的状态码,及set和get方法

public class baseException extends RuntimeException {

    private int status = 200;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public baseException() {
    }

    public baseException(String message,int status) {
        super(message);
        this.status = status;
    }

    public baseException(String message) {
        super(message);
    }

    public baseException(String message, Throwable cause) {
        super(message, cause);
    }

    public baseException(Throwable cause) {
        super(cause);
    }

    public baseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

而之后的其他类,也利用上面提到的,同样的方法继承了该base异常类,从而达到对各个异常进行处理的作用

以下的代码就是具体的例子

public class UserInvalidException extends baseException {
    public UserInvalidException(String message) {
        super(message, CommonConstants.EX_USER_PASS_INVALID_CODE);
    }
}
public class UserTokenException extends baseException {
    public UserTokenException(String message) {
        super(message, CommonConstants.EX_USER_INVALID_CODE);
    }
}

关于本项目的异常处理,主要由下面的这个类完成,使用@ExceptionHandler注解,在括号中传入对应的异常类,用于指定处理对应异常类的方法。针对不同的异常,进行不同的处理。

@ControllerAdvice("com.sdu.nurse")
@ResponseBody
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(ClientTokenException.class)
    public baseResponse clientTokenExceptionHandler(HttpServletResponse response, ClientTokenException ex) {
        response.setStatus(403);
        logger.error(ex.getMessage(),ex);
        return new baseResponse(ex.getStatus(), ex.getMessage());
    }

    @ExceptionHandler(UserTokenException.class)
    public baseResponse userTokenExceptionHandler(HttpServletResponse response, UserTokenException ex) {
        response.setStatus(401);
        logger.error(ex.getMessage(),ex);
        return new baseResponse(ex.getStatus(), ex.getMessage());
    }

    @ExceptionHandler(UserInvalidException.class)
    public baseResponse userInvalidExceptionHandler(HttpServletResponse response, UserInvalidException ex) {
        response.setStatus(200);
        logger.error(ex.getMessage(),ex);
        return new baseResponse(ex.getStatus(), ex.getMessage());
    }

    @ExceptionHandler(baseException.class)
    public baseResponse baseExceptionHandler(HttpServletResponse response, baseException ex) {
        logger.error(ex.getMessage(),ex);
        response.setStatus(500);
        return new baseResponse(ex.getStatus(), ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public baseResponse otherExceptionHandler(HttpServletResponse response, Exception ex) {
        response.setStatus(500);
        logger.error(ex.getMessage(),ex);
        return new baseResponse(CommonConstants.EX_OTHER_CODE, ex.getMessage());
    }
}

在本类中,还注入了日志对象,用这个日志对象输出对应的日志。

2.2 请求

在看完了响应的部分,接下来我们关注项目中关于“请求”的部分。

在本项目中,关于请求的部分比较简单,在之前的博客中我也略有提及,在这里详细说明一下

本项目中的请求封装在api包下的js文件中,以用户请求为例,代码如下,首先我们可以看到,js的开始部分,引入了axios的fetch,下面的四种请求,返回的都是一个fetch对象。

以get请求为例,传入一个query对象,直接调用fetch,指定对应对应的url,指定method,指定params(get请求所带的参数)。

而在post请求中,将要传递给后端接口的参数写在data中。

import fetch from '@/plugin/axios'

export function page (query) {
  return fetch({
    url: '/api/nurse/user/page',
    method: 'get',
    params: query
  })
}

export function addObj (obj) {
  return fetch({
    url: '/api/nurse/user',
    method: 'post',
    data: obj
  })
}

export function getObj (id) {
  return fetch({
    url: '/api/nurse/user/' + id,
    method: 'get'
  })
}

export function delObj (id) {
  return fetch({
    url: '/api/nurse/user/' + id,
    method: 'delete'
  })
}

export function putObj (id, obj) {
  return fetch({
    url: '/api/nurse/user/' + id,
    method: 'put',
    data: obj
  })
}

在具体的页面中,该项目中调用了上面封装好的请求代码,在按下确认按钮后,执行then方法,then方法中调用了delObj方法,而该方法封装在js代码中。

handleDelete (row) {
   this.$/confirm/i('此操作将永久删除, 是否继续?', '提示', {
     /confirm/iButtonText: '确定',
     cancelButtonText: '取消',
     type: 'warning'
   })
     .then(() => {
       delObj(row.id)
         .then(() => {
           this.$notify({
             title: '成功',
             message: '删除成功',
             type: 'success',
             duration: 2000
           })
           const index = this.list.indexOf(row)
           this.list.splice(index, 1)
         })
     })
 }
三、总结

在本次阅读源码的过程中,我主要分析了老年健康知识图谱系统中关于请求和响应的内容。在本次阅读源码的过程中,我体会到了该项目在请求封装和异常类封装的巧妙之处,在这个过程中也感谢老师和小组成员对我的帮助,本学期的软件工程应用与实践的源码分析就分析到这里,之后还有一篇博客用于总结。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/679017.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号