实现内容: 根据当前请求路径和配置中指定不进行过滤的请求路由信息, 做对应的过滤操作
并且不进行过滤的配置可以通过配置文件或集合直接添加两种方式进行
实现效果:
package com.example.demo.util;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 请求过滤器
*
* @author Cr
* @date 2020-04-21
* */
@Component
public class RequestFilter implements Filter {
/**
* 配置文件在resources下的根节点路径
* */
private static final String configRootPath = "/config/filter";
/**
* 不进行过滤的路由列表
*
* <p>
* 如: /test/main , /policy/query
* 这种全路径的路由
* </p>
*
* */
private static List<String> noNeedFilteringRouteList = new ArrayList<>();
/**
* 不需要过滤的根路由列表
*
* <p>
* 如: /test/main ,/test/index , /policy/query , /policy/add
* 只需要配置: /test , /policy就可以对其下面的所有路由进行过滤
*
* 如: 访问路由为: /test/main
* 我们配置的根路由为: /test2 , 则不会通过.
* 但如果访问的路由为/test2/**,则会通过
*
* </p>
*
* */
private static List<String> noNeedFilteringRootRouteList = new ArrayList<>();
static{
initializeConfig( noNeedFilteringRouteList, configRootPath + "/noNeedFilteringRoute");
initializeConfig( noNeedFilteringRootRouteList, configRootPath + "/noNeedFilteringRootRoute");
/**
* 可以使用配置文件方式和下方直接添加到集合的方式
* noNeedFilteringRouteList.add();
* noNeedFilteringRootRouteList.add();
* */
}
private static void initializeConfig(List<String> list, String path){
String content = FileUtil.readerResourcesDirectory(path);
list.addAll(Arrays.asList(content.split(",")));
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
doFilter((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse, filterChain);
} catch (Exception e) {
e.printStackTrace();
requestFailed((HttpServletResponse) servletResponse, e.getMessage());
}
}
/**
* 请求失败时打印固定格式的错误信息
*
* */
private void requestFailed(HttpServletResponse servletResponse, String errorMessage) {
try (ServletOutputStream out = servletResponse.getOutputStream()){
servletResponse.setHeader("Content-type", "text/html;charset=UTF-8");
out.write(MyResult.error(errorMessage).toString().getBytes("UTF-8"));
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws Exception {
String token = request.getHeader("token");
System.out.println(token);
String requestPath = request.getServletPath();
System.out.println(requestPath);
// 如果当前请求路径是在配置列表中存在的, 则不做过滤处理,直接进行转发
if(noNeedFilteringRouteList.contains(requestPath)
|| noNeedFilteringRootRouteList.stream().anyMatch(x-> requestPath.contains(x))
){
filterChain.doFilter(request, response);
return;
}
// 过滤业务
if(null == token){
throw new Exception("token不能为空");
}
// 过滤业务通过后执行请求
filterChain.doFilter(request, response);
}
}
package com.example.demo.util;
import org.springframework.core.io.ClassPathResource;
import java.io.*;
/**
* 文件工具类
*
* @author Cr
* @date 2020-04-21
*
* */
public class FileUtil {
public static String readerResourcesDirectory(String path){
try {
return reader(new ClassPathResource(path).getInputStream());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String reader(String path){
try {
return reader(new FileInputStream(new File(path)));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String reader(InputStream inputStream){
try {
return reader(new BufferedReader(new InputStreamReader(inputStream, "UTF-8")));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String reader(BufferedReader reader){
StringBuffer content = new StringBuffer();
String line = "";
try {
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return content.toString();
}
}
package com.example.demo.util;
/**
* API接口请求返回的模型类
*
* @author cr
* @date 2019-06-05
*
*/
public class MyResult {
private MyResult() { }
// region 属性区
/**
* 服务名称
*/
private String serviceName = "Filter-Demo";
/**
* API请求的地址
* 例如: /usc-zuul/base/user
*/
private String path;
/**
* 请求状态
*/
private String status;
/**
* 状态码
*/
private String code;
/**
* 说明
*/
private String description;
/**
* 返回的数据
*/
private Object data;
// endregion
// region 返回调用区
/**
* 请求错误
*
* @date 2019-06-05
* @author cr
*/
public static MyResult error() {
return init(null, BaseEnum.STATUS_ERROR.value, BaseEnum.DESCRIPTION_ERROR.value, BaseEnum.CODE_ERROR.value, null);
}
/**
* 请求错误,设置错误说明
*
* @param description 说明
* @date 2019-06-05
* @author cr
*/
public static MyResult error(String description) {
return init(null, BaseEnum.STATUS_ERROR.value, description, BaseEnum.CODE_ERROR.value, null);
}
/**
* 请求错误,设置错误说明和对应的状态码
*
* @param description 说明
* @param code 状态码
* @date 2019-06-05
* @author cr
*/
public static MyResult error(String description, String code) {
return init(null, BaseEnum.STATUS_ERROR.value, description, code, null);
}
/**
* 请求错误,设置说明,状态码, 对应的返回数据
*
* @param description 说明
* @param code 状态码
* @param data 返回的数据
* @date 2019-06-05
* @author cr
*/
public static MyResult error(String description, String code, Object data) {
return init(null, BaseEnum.STATUS_ERROR.value, description, code, data);
}
/**
* 请求错误,记录地址
*
* @date 2019-06-05
* @author cr
*/
public static MyResult errorPath(String path) {
return init(path, BaseEnum.STATUS_ERROR.value, BaseEnum.DESCRIPTION_ERROR.value, BaseEnum.CODE_ERROR.value, null);
}
/**
* 请求错误,记录地址,设置错误说明
*
* @date 2019-06-05
* @author cr
*/
public static MyResult errorPath(String path, String description) {
return init(path, BaseEnum.STATUS_ERROR.value, description, BaseEnum.CODE_ERROR.value, null);
}
/**
* 请求错误,记录地址,设置错误说明和对应的状态码
*
* @param description 说明
* @param code 状态码
* @date 2019-06-05
* @author cr
*/
public static MyResult errorPath(String path, String description, String code) {
return init(path, BaseEnum.STATUS_ERROR.value, description, code, null);
}
/**
* 请求错误,设置说明,状态码, 对应的返回数据
*
* @param description 说明
* @param code 状态码
* @param data 返回的数据
* @date 2019-06-05
* @author cr
*/
public static MyResult errorPath(String path, String description, String code, Object data) {
return init(path, BaseEnum.STATUS_ERROR.value, description, code, data);
}
/**
* 请求成功
*
* @date 2019-06-05
* @author cr
*/
public static MyResult success() {
return init(null, BaseEnum.STATUS_SUCCESS.value, BaseEnum.DESCRIPTION_SUCCESS.value, BaseEnum.CODE_SUCCESS.value, null);
}
/**
* 请求成功
*
* @param data 需要返回的数据
* @date 2019-06-05
* @author cr
*/
public static MyResult success(Object data) {
return init(null, BaseEnum.STATUS_SUCCESS.value, BaseEnum.DESCRIPTION_SUCCESS.value, BaseEnum.CODE_SUCCESS.value, data);
}
/**
* 请求成功
*
* @param data 需要返回的数据
* @param description 说明
* @date 2019-06-05
* @author cr
*/
public static MyResult success(Object data, String description) {
return init(null, BaseEnum.STATUS_SUCCESS.value, description, BaseEnum.CODE_SUCCESS.value, data);
}
/**
* 请求成功
*
* @date 2019-06-05
* @author cr
*/
public static MyResult success(String path) {
return init(path, BaseEnum.STATUS_SUCCESS.value, BaseEnum.DESCRIPTION_SUCCESS.value, BaseEnum.CODE_SUCCESS.value, null);
}
/**
* 请求成功
*
* @param data 需要返回的数据
* @date 2019-06-05
* @author cr
*/
public static MyResult success(String path, Object data) {
return init(path, BaseEnum.STATUS_SUCCESS.value, BaseEnum.DESCRIPTION_SUCCESS.value, BaseEnum.CODE_SUCCESS.value, data);
}
/**
* 请求成功
*
* @param data 需要返回的数据
* @param description 说明
* @date 2019-06-05
* @author cr
*/
public static MyResult success(String path, Object data, String description) {
return init(path, BaseEnum.STATUS_SUCCESS.value, description, BaseEnum.CODE_SUCCESS.value, data);
}
// endregion
// region 链式调法区
public MyResult setPath(String path) {
this.path = path;
return this;
}
public MyResult setStatus(String status) {
this.status = status;
return this;
}
public MyResult setCode(String code) {
this.code = code;
return this;
}
public MyResult setDescription(String description) {
this.description = description;
return this;
}
public MyResult setData(Object data) {
this.data = data;
return this;
}
// endregion
// region get方法区
public String getServiceName() {
return serviceName;
}
public String getPath() {
return path;
}
public String getStatus() {
return status;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
public Object getData() {
return data;
}
// endregion
private static MyResult init(String path, String status, String description, String code, Object data) {
MyResult model = new MyResult();
model.path = path;
model.status = status;
model.description = description;
model.code = code;
model.data = data;
return model;
}
// region 构造函数区
/**
* 基础的自定义返回,暂不确定是否使用
*
* @param path 请求的路由地址
* @param status 状态
* @param code 状态码
* @date 2019-06-05
* @author cr
*/
private MyResult(String path, String status, String code) {
this.path = path;
this.status = status;
this.code = code;
}
/**
* 暂不确定是否使用
*/
private MyResult(String path, String status, String code, String description, Object data) {
this.path = path;
this.status = status;
this.code = code;
this.description = description;
this.data = data;
}
// endregion
@Override
public String toString() {
return "{" +
"serviceName='" + serviceName + '\'' +
", path='" + path + '\'' +
", status='" + status + '\'' +
", code=" + code +
", description='" + description + '\'' +
", data=" + data +
'}';
}
/**
* 基础枚举
*
* @author cr
* @date 2019-06-05
*/
enum BaseEnum {
// 状态
STATUS_SUCCESS("SUCCESS"),
STATUS_ERROR("ERROR"),
// 说明
DESCRIPTION_SUCCESS("请求成功"),
DESCRIPTION_ERROR("请求失败"),
// 状态代码
CODE_SUCCESS("1000"),
CODE_ERROR("1001");
public String value;
BaseEnum(String value) {
this.value = value;
}
}
}