第二章🚦统一封装返回实体

265 阅读4分钟

🧑‍🎓 个人主页:SilenceLamb

📖 本章内容:【统一返回实体

image.png

一、统一返回实体

/**
 * Author: 花棉袄
 * CreateDate: 2022年08月23日
 * Describe: 统一返回实体
 */
public class AjaxResult extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    public static final String SUCCESSFUL = "操作成功";
    public static final String ERROR = "操作失败";
    public static final int SUCCESSFUL_CODE = 200;
    public static final int ERROR_CODE= 500;

    @ApiModelProperty("状态码")
    public static final String CODE_TAG = "code";

    @ApiModelProperty("返回内容")
    public static final String MSG_TAG = "msg";

    @ApiModelProperty("数据对象")
    public static final String DATA_TAG = "data";

    public AjaxResult() {
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code 状态码
     * @param msg  返回内容
     */
    public AjaxResult(int code, String msg) {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code 状态码
     * @param msg  返回内容
     * @param data 数据对象
     */
    public AjaxResult(int code, String msg, Object data) {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data)) {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * 返回成功消息
     *
     * @return 成功消息
     */
    public static AjaxResult success() {
        return AjaxResult.success(SUCCESSFUL);
    }

    /**
     * 返回成功消息
     *
     * @param msg 返回内容
     * @return 成功消息
     */
    public static AjaxResult success(String msg) {
        return AjaxResult.success(msg, null);
    }

    /**
     * 返回成功数据
     *
     * @return 成功消息
     */
    public static AjaxResult success(Object data) {
        return AjaxResult.success(SUCCESSFUL, data);
    }


    /**
     * 返回成功消息
     *
     * @param msg  返回内容
     * @param data 数据对象
     * @return 成功消息
     */
    public static AjaxResult success(String msg, Object data) {
        return new AjaxResult(SUCCESSFUL_CODE, msg, data);
    }

    /**
     * 
     * @param code 状态码
     * @param msg   返回内容
     * @param data  数据对象
     * @return
     */
    public static AjaxResult success(int code, String msg, Object data) {
        return new AjaxResult(code, msg, data);
    }

    /**
     * 返回错误消息
     *
     * @return
     */
    public static AjaxResult error() {
        return AjaxResult.error(ERROR);
    }

    /**
     * 返回错误消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult error(String msg) {
        return AjaxResult.error(msg, null);
    }
    /**
     * 返回错误消息
     *
     * @param code 状态码
     * @param msg  返回内容
     * @return 警告消息
     */
    public static AjaxResult error(int code, String msg) {
        return new AjaxResult(code, msg, null);
    }
    /**
     * 返回错误消息
     *
     * @param msg  返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult error(String msg, Object data) {
        return new AjaxResult(ERROR_CODE, msg, data);
    }



    public static AjaxResult error(int code, String msg, Object data) {
        return new AjaxResult(code, msg, data);
    }

    /**
     * 方便链式调用
     *
     * @param key   键
     * @param value 值
     * @return 数据对象
     */
    @Override
    public AjaxResult put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

二、封装分页查询参数

🍑分页常量

/**
 * @Author: 花棉袄
 * @Date: 2022年08月18日
 * @Describe: 分页常量
 */
public class PageConstant {

    @ApiModelProperty("当前页码")
    public static final String PAGE = "page";

    @ApiModelProperty("每页显示记录数")
    public static final String LIMIT = "limit";

    @ApiModelProperty("排序字段")
    public static final String ORDER_FIELD = "sidx";

    @ApiModelProperty("排序方式")
    public static final String ORDER = "order";

    @ApiModelProperty("升序")
    public static final String ASC = "asc";
}

🍑 SQL过滤

/**
 * @Author: 花棉袄
 * @CreateDate: 2022年08月17日
 * @Describe: SQL过滤
 */
public class SQLFilterUtils {

    /**
     * SQL注入过滤
     *
     * @param str 待验证的字符串
     */
    public static String sqlInject(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        //去掉'|"|;|\字符
        str = StringUtils.replace(str, "'", "");
        str = StringUtils.replace(str, "\"", "");
        str = StringUtils.replace(str, ";", "");
        str = StringUtils.replace(str, "\\", "");
        //转换成小写
        str = str.toLowerCase();

        //非法字符
        String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};

        //判断是否包含非法字符
        for (String keyword : keywords) {
            if (str.contains(keyword)) {
                throw new ServiceException("非法字符异常");
            }
        }

        return str;
    }
}

🍑 封装分页查询参数

/**
 * @Author: 花棉袄
 * @Date: 2022年08月17日
 * @Describe: 封装分页查询参数
 */
public class PageParam<T> {


    public IPage<T> getPage(Map<String, Object> params) {
        return this.getPage(params, null, false);
    }

    public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
        //分页参数
        long curPage = 1;
        long limit = 10;

        if (params.get(PageConstant.PAGE) != null) {
            curPage = Long.parseLong((String) params.get(PageConstant.PAGE));
        }
        if (params.get(PageConstant.LIMIT) != null) {
            limit = Long.parseLong((String) params.get(PageConstant.LIMIT));
        }

        //分页对象
        Page<T> page = new Page<>(curPage, limit);

        //分页参数
        params.put(PageConstant.PAGE, page);

        /**
         *  排序字段:防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
         */
        String orderField = SQLFilterUtils.sqlInject((String) params.get(PageConstant.ORDER_FIELD));

        String order = (String) params.get(PageConstant.ORDER);


        //前端字段排序
        if (StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)) {
            if (PageConstant.ASC.equalsIgnoreCase(order)) {
                return page.addOrder(OrderItem.asc(orderField));
            } else {
                return page.addOrder(OrderItem.desc(orderField));
            }
        }

        //没有排序字段,则不排序
        if (StringUtils.isBlank(defaultOrderField)) {
            return page;
        }

        //默认排序
        if (isAsc) {
            page.addOrder(OrderItem.asc(defaultOrderField));
        } else {
            page.addOrder(OrderItem.desc(defaultOrderField));
        }

        return page;
    }
}

🍑 分页-标准返回结果

/**
 * @Author: 花棉袄
 * @Date: 2022年08月18日
 * @Describe: 分页-标准返回结果
 */
public class PageResult implements Serializable {

	private static final long serialVersionUID = 1L;

	@ApiModelProperty(value = "总记录数")
	private int totalCount;

	@ApiModelProperty(value = "每页记录数")
	private int pageSize;

	@ApiModelProperty(value = "总页数")
	private int totalPage;

	@ApiModelProperty(value = "当前页数")
	private int currPage;

	@ApiModelProperty(value = "列表数据")
	private List<?> list;

	/**
     * 分页
     */
	public PageResult() {
		this.list = list;
		this.totalCount = totalCount;
		this.pageSize = pageSize;
		this.currPage = currPage;
		this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
	}

	/**
	 * 分页
	 * @param page
	 */
	public PageResult(IPage<?> page) {
		this.list = page.getRecords();
		this.totalCount = (int)page.getTotal();
		this.pageSize = (int)page.getSize();
		this.currPage = (int)page.getCurrent();
		this.totalPage = (int)page.getPages();
	}

	public int getTotalCount() {
		return totalCount;
	}

	public void setTotalCount(int totalCount) {
		this.totalCount = totalCount;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getTotalPage() {
		return totalPage;
	}

	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	public int getCurrPage() {
		return currPage;
	}

	public void setCurrPage(int currPage) {
		this.currPage = currPage;
	}

	public List<?> getList() {
		return list;
	}

	public void setList(List<?> list) {
		this.list = list;
	}

}

三、响应控制器建议

/**
 * @Author Michale
 * @CreateDate 2022/9/17
 * @Describe 避免Controller里返回数据每次都要用响应体来包装
 */
@RestControllerAdvice(basePackages = "com.michale.admin.controller")// 注意哦,这里要加上需要扫描的包
public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {


    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {
        // 如果接口返回的类型本身就是ResultVO那就没有必要进行额外的操作,返回false
        return !returnType.getGenericParameterType().equals(AjaxResult.class);
    }


    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // String类型不能直接包装,所以要进行些特别的处理
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVO里后,再转换为json字符串响应给前端
                return objectMapper.writeValueAsString(AjaxResult.success(body));
            } catch (JsonProcessingException e) {
                throw new ServiceException();
            }
        }
        // 将原本的数据包装在ResultVO里
        return AjaxResult.success(body);
    }
}
复制代码
@Anonymous
@GetMapping("/string")
public String string() {
    return "你好啊";
}
复制代码
{
    "msg": "操作成功",
    "code": 200,
    "data": "你好啊"
}

扫码_搜索联合传播样式-标准色版.png

📢💨如果文章对你有帮助【关注👍点赞❤️收藏⭐】