项目学习心得(一)
SpringBoot 配置文件
1、如果需要在配置文件中配置多个资源,而且资源属于不同的类别时,可以分开定义 .yml 文件
资源 : aliapy 资源、file : 资源等
2、使用
spring:
profiles:
active: dev # 选择加载的配置环境 dev 开发环境、prod 测试环境、test 测试环境 默认规约
include: website,alipay,oss # 导入其他的配置资源
application:
name: novel-front
- 通过 include 可以导入其他后缀的文件前缀是 application-后缀.yml or properties
filter 的应用
1、filter 和 Interceptor 的执行顺序 : 冬季是查干湖的捕鱼季,查干湖渔民心口相传的捕鱼的渔网网口都是 5 DM 的,这样就可以人为的放过那些小鱼 (我们可以理解成这是一种过滤器)。当我们把鱼捕上来之后发现在捕上来的鱼大小都符合要求,但是有一些鱼是生病了的所以需要进行筛选 (我们可以理解成这是一种拦截器)
2、通过 FilterRegistrationBean
@Bean
public FilterRegistrationBean<XssFilter> xssFilterFilterRegistrationBean() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setOrder(Integer.MAX_VALUE);
registration.setName("xssFilter");
Map<String , String> initParameters = new HashMap<>();
initParameters.put("enabled", filterProperties.getEnabled());
List<String> excludesUrl = filterProperties.getExcludesUrl();
initParameters.put("excludesUrl", StrUtil.spliceCollection(excludesUrl));
registration.setInitParameters(initParameters);
return registration;
}
// 1、配置过滤器匹配路径
// 2、声明类型
// 3、设置执行顺序
// 4、设置名称
// 5、配置初始化参数
3、通过继承 Filter 定义我们自己的 Filter
public class XssFilter implements Filter {
private Boolean enabled;
/**
* 排除链接
*/
public List<String> excludesUrls = new ArrayList<>();
private static final String START_SIGN = "^";
// 从我们注册的 FilterRegistrationBean 中获取参数并进行处理
@SneakyThrows
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String parameterEnabled = filterConfig.getInitParameter("enabled");
String parameterExcludesUrls = filterConfig.getInitParameter("excludesUrl");
if (StrUtil.isNotEmpty(parameterExcludesUrls)) {
String[] urls = parameterExcludesUrls.split(",");
excludesUrls.addAll(Arrays.asList(urls));
}
if (StringUtils.isNotEmpty(parameterEnabled)) {
enabled = Boolean.parseBoolean(parameterEnabled);
}
}
// 过滤器执行
@SneakyThrows
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (handleExcludeURL(req)) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest)servletRequest);
filterChain.doFilter(xssRequest,servletResponse);
}
private boolean handleExcludeURL(HttpServletRequest request) {
if (!enabled) {
return true;
}
if (null == excludesUrls || excludesUrls.isEmpty()) {
return false;
}
String url = request.getServletPath();
for (String pattern : excludesUrls) {
if (Pattern.matches((START_SIGN + pattern).intern(), url)) {
return true;
}
}
return false;
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
4、继承 HttpServletRequestWrapper 实现我们的请求参数的 XSS 处理
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
int length = values.length;
String[] escapeValues = new String[length];
for (int i = 0; i < length; i++) {
escapeValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
}
return escapeValues;
}
private String stripXSS(String value) {
if (value != null) {
value = value.replaceAll("", "");
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("<script(.*?)>",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("eval\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("expression\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("onload(.*?)=",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("alert\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("window.location(.*?)=",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("unescape\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("execscript\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("msgbox\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("confirm\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("prompt\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
private String cleanXSS(String value) {
// You'll need to remove the spaces from the html entities below
value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
value = value.replaceAll("'", "& #39;");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
return value;
}
}
定时器问题
1、在 SpringBoot 项目中使用 Scheduled 定时任务时,默认情况下同一时间只能执行一个定时任务
默认情况下,我们的执行器配置的是当线程,当有多个定时任务执行的时候除了第一个定时任务,其他的定时任务会阻塞
2、解决方案,在容器中自定义执行任务
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10); # 10 代表同一时间能够执行的定时器任务
return taskScheduler;
}
枚举类问题
1、枚举类的 INSTANCE 默认都是单例的
2、在枚举类中的属性应该定义为 final 属性
3、枚举类应该用 Enum 结尾
public enum DelEnum {
/**
* 正常状态
*/
NORMAL(0),
/**
* 删除状态
*/
DELETE(1);
private final Integer statusCode;
DelEnum(Integer statusCode) {
this.statusCode = statusCode;
}
public Integer code() {
return this.statusCode;
}
public String strCode() {
return String.valueOf(this.statusCode);
}
@Override
public String toString() {
return strCode();
}
}
4、如果枚举类中有多个属性,可以使用下面操作进行 CODE - > MESSAGE 的映射
public enum SexEnum {
MAN(1 , "男"),
WOMAN(2 , "女");
@Getter
private final Integer code;
@Getter
private final String sex;
SexEnum(Integer code , String sex) {
this.code = code;
this.sex = sex;
}
public static SexEnum getByCode(Integer code) {
return ArrayUtil.firstMatch((each) -> each.getCode().equals(code), SexEnum.values();
}
}