0%

文章字数:647,阅读全文大约需要2分钟

HTTP头中的Content-Security-Policy字段有若干指令,可以设置指定的策略允许的源

指令

  1. default-src: 可以为其它指令提供备选项
  2. child-src:元素加载的嵌套浏览上下文
  3. connect-src指令用于控制允许通过脚本接口加载的链接地址,影响下面的
  • <a> ping
  • Fetch
  • XMLHttpRequest
  • WebSocket
  • EventSource
  1. font-src字体的地址被阻止
    1
    2
    3
    4
    @font-face { 
    font-family: "MyFont";
    src: url("https://not-example.com/font");
    }
  2. frame-src
    <frame>标签和<iframe>指定源的限制
  3. img-srcHTTP 指令指定图像和图标的有效来源
  4. manifest-src manifest是一个资源允许的列表
  5. media-src <audio><video>元素的有效源
  6. object-src
  7. script-src <script>标签
  8. style-src <style>标签
  9. worker-src Worker SharedWorker ServiceWorker

语法

一个或者多个源

1
2
Content-Security-Policy: default-src <source>;
Content-Security-Policy: default-src <source> <source>;

<source>可以是以下之一:

  1. <host-source>域名或者ip地址表示的主机名,外加可选的URL协议名和端口号,允许在主机名和端口的位置使用通配符*

    1
    http://*.example.com
  2. <scheme-source>可以直接指定源(二进制文件,数据等)不推荐使用
    一下浏览器会特意排除blobfilesystem,可以在这里设置

    1
    2
    3
    4
    5
    # data:sssssssss
    data:uris
    mediastream:uris
    blob:uris
    filesystem:uris
  3. 'self'指定与要保护的文件所在的源,包括相同的URL scheme与端口号。必须有单引号。即同源

  4. 'unsafe-inline'允许使用内联资源,script标签,javascript: URL之类的

  5. 'unsafe-eval'允许使用eval()以及相似的函数来创建代码

  6. 'none'不允许任何内容

  7. 'nonce-<base64值>'特定使用一次性加密内联的白名单,服务器必须在每一次传输政策时生成唯一的一次性值,否则有安全问题。

  8. <hash-source>使用sha256, sha384, sha512编码过得内联脚本或样式

  9. strict-dynamic指定对于含有标记脚本(通过附加一个随机数或散列)的信任,应该传播到由该脚本加载的所有脚本。与此同时,任何白名单以及源表达式例如 ‘self’ 或者 ‘unsafe-inline’ 都会被忽略


文章字数:46,阅读全文大约需要1分钟

java后端报错Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

原因

前端使用formData传值,但是后端接收使用的是@RequestBody。这个是json的接收方式
修改成func(@RequestParam Map datas)


文章字数:230,阅读全文大约需要1分钟

Drools是一款java规则引擎,其目的是为了将if..else这样的业务逻辑与业务代码分离。

添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependencies>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.5.0.Final</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

配置文件

新建/src/resources/META-INF/kmodule.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<!-- name任意 packages为resources下drl所在的包 -->
<kbase name="rules" packages="rules">
<!-- ksession名字任意 -->
<ksession name="myAgeSession"/>
</kbase>
</kmodule>

drl文件

1
2
3
4
5
6
7
8
9
10
11
12
//package rules //包名,不必和物理路径一样
import com.learndrools.learndrools.User //导入Bean的完整路径,也可导入静态方法
dialect "mvel"
rule "age" //唯一规则名,可多次执行
//salience 1 //优先级越大越高,如果不设置随机顺序
//no-loop true //规则是否只执行一次,默认false,多次执行
//lock-on-active true //避免因某些Fact对象被修改而使已经执行过的规则再次被激活执行。
when
$user: User(age<15 || age>60) // 声明变量:Bean(规则),变量通常$开头
then
System.out.println($user.getName()+"年龄不符合");
end

执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.learndrools.learndrools;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class LearndroolsApplicationTests {

@Test
public void contextLoads() {
}

private static KieContainer container = null;
private KieSession statefulKieSession = null;

@Test
public void test(){
KieServices kieServices = KieServices.Factory.get();
container = kieServices.getKieClasspathContainer();
statefulKieSession = container.newKieSession("myAgeSession");
User user = new User("zhang san",90);
statefulKieSession.insert(user);
statefulKieSession.fireAllRules();
statefulKieSession.dispose();
}
}

文章字数:311,阅读全文大约需要1分钟

注解ControllerAdvice提供了controller的全局处理功能

  1. @ExceptionHandler:全局异常捕获,捕获到指定异常后处理。通常用作获取异常后统一返回结构化的错误信息

  2. @InitBinder:指定参数名,获取的参数绑定变量前的自定义操作,不如给时间日期增加解析器,构建不同的变量名头部信息。

  3. @ModelAttribute:该方法返回的值可以在controller中接收。

@ExceptionHandler

1
2
3
4
5
6
7
8

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
// 指定需要捕获的异常的Class类型
Class<? extends Throwable>[] value() default {};
}
1
2
3
4
5
6
7
8
9
@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
//捕捉到异常后返回异常界面
@ExceptionHandler(RuntimeException.class)
public ModelAndView runtimeException(RuntimeException e) {
e.printStackTrace();
return new ModelAndView("error");
}
}

@InitBinder

作用于通过@RequestParam,@RequestBody或者@ModelAttribute等注解绑定的参数

1
2
3
4
5
6
7
8
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InitBinder {
// 这里value参数用于指定需要绑定的参数名称,如果不指定,则会对所有的参数进行适配,
// 只有是其指定的类型的参数才会被转换
String[] value() default {};
}
  1. 指定转换器
1
2
3
4
5
6
7
8

@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
@InitBinder
public void globalInitBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
  1. 不同的前缀返回给不同的对象
1
2
3
4
5
6
7
8
9
10
11
12
controller:
@InitBinder(“student”)
public void initUser(WebDataBinder binder){
binder.setFieldDefaultPrefix(“student”)
}
@InitBinder(“teacher”)
public void initAdmin(WebDataBinder binder){
binder.setFieldDefaultPrefix(“teacher”);
}
@RequestMapping("/xx")
… save(Teacher teacher,Student student){
}

@ModelAttribute

接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {

// 该属性与name属性的作用一致,用于指定目标参数的名称
@AliasFor("name")
String value() default "";

@AliasFor("value")
String name() default "";

// 与name属性一起使用,如果指定了binding为false,那么name属性指定名称的属性将不会被处理
boolean binding() default true;
}

使用:

1
2
3
4
5
6
7
@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
@ModelAttribute(value = "message")
public String globalModelAttribute() {
return "valuexxxx";
}
}
1
2
3
4
5
6
@RequestMapping(value = "/demo")
public ModelAndView detail(@ModelAttribute("message") String message) {
//获取到了
System.out.println(message);
return "ok";
}

文章字数:237,阅读全文大约需要1分钟

ES6支持模块化编程,模块内变量,函数外部无法获取。必须模块内使用esport输出,外部使用import接收。输出有普通和默认两种,接收时普通需要{xxx,xx}接收,默认不用。

  • 简单输出

test.js

1
export let name="zhangsan";

index.js

1
2
import {name} from "./test.js";
console.log(name);//输出导入的变量name
  • 多变量

test.js

1
2
3
4
5
6
7
8
9
10
let name="zhangsan";
let addr="fz";
let myfun=function(){
return name+"住在"+addr;
}
export {
name,
addr,
myfun
}

index.js

1
2
3
import {name,addr,myfun} from "./test.js";
console.log(name);
console.log(myfun());
  • 重命名
  1. 模块内部
    test.js
    1
    2
    3
    4
    5
    6
    let myName="zhangsan";
    let myAddr="fz";
    export{
    myName as name,
    myAddr as addr
    }
    index.js
    1
    2
    import {name,addr} from "./test.js";
    console.log(name+"住在"+addr)
  2. 外部
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*-----------------------test1.js-----------------------*/
    export let myName="我来自test1.js";
    /*-----------------------test2.js-----------------------*/
    export let myName="我来自test2.js";
    /*-----------------------index.js-----------------------*/
    import {myName as name1} from "./test1.js";
    import {myName as name2} from "./test2.js";
    console.log(name1);//我来自test1.js
    console.log(name2);//我来自test1.js
  • 导入整个模块

index.js

1
2
3
import * as poeple from "./test.js";
console.log(people.name);
console.log(people.addr);
  • 默认导出
  1. 导出默认方法
    1
    2
    3
    4
    5
    6
    7
    /*---------test.js-------------*/
    export default function(){
    return "default function";
    }
    /*-------index.js---------*/
    import xxxfun from "./test.js";//不需要{},名字任意
    console.log(xxxfun());
    1. 导出默认对象
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      /*-----------test.js---------*/
      export default{//json对象
      defaultFun(){
      return "default fun";
      },
      name : "xxx";
      }
      /*-----------index.js----------*/
      import defaultOb from "./test.js";
      console.log(defaultOb.defaultFun());
      console.log(defaultOb.name);
  2. 混合导出
    1
    2
    3
    4
    5
    6
    7
    /*------------test.js-------------*/
    export default function(){
    return "xx";
    }
    export var name="zzz";
    /*--------------index.js-----------*/
    import defaultFun,{name} from "./test.js";//{}是导出,不加是默认导出。

文章字数:154,阅读全文大约需要1分钟
今天遇到一个spring报错,error creating bean。查了报错的bean,没问题,而且报的也是其他同事写的,从主分支上拉下来的代码。
后来在报错的最后看到一句:

1
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: WhiteListClass column: start_time (should be mapped with insert="false" update="false")

分析

  1. 由于jpa的列名不小心重复了,导致jpa初始化失败
  2. 导致spring初始化失败,所以报了一些莫名其妙的错误。

反思

这次只看最上面的一些报错,觉得莫名其妙,还以为是maven环境的问题。从新拉了代码,更新仓库。
下次要看全报错信息。


文章字数:118,阅读全文大约需要1分钟

此错误是jpa在进行更新和删除操作时没有加事务导致的

解决

加上事务就可以了,Service层或者是Repository层加都可以。

1
2
3
4
@service
@Transaction
class xxxService{
}

Not supported for DML operations

这个错误是因为修改数据需要在Dao的方法上加@Modifying声明方法是修改数据的。

#总结

jpa修改数据需要

  1. 加事务,jpa修改操作必须在事务里
  2. 加注解@Modifying声明是修改操作

文章字数:69,阅读全文大约需要1分钟

Lombok的注解EqualsAndHashCode导致栈空间溢出

排查

  1. StackOverflowError一般是递归之类的多嵌套导致的
  2. EqualsAndHashCode注解了两个类,是一对多关系

解决

手写equalshashCode,多的一方排除循环依赖的属性。


文章字数:38,阅读全文大约需要1分钟

maven clean命令报错

原因

之前编译的程序正在运行

解决

结束程序,或者直接杀掉java进程


文章字数:72,阅读全文大约需要1分钟

ForkJoin框架

java8引入的Stream

Stream内置了ForkJoin,可以直接使用

1
2
3
4
5
public static void main(String[] args) {
int[] a = {0, 1, 2, 3, 4, 5};
Arrays.stream(a).parallel().forEach(v -> System.out.println(Thread.currentThread().getId() + "==" + v));
System.out.println("FockJoin 默认线程池线程数量 = " + (Runtime.getRuntime().availableProcessors() - 1));
}
1
2
3
4
5
6
7
1==3
13==1
1==0
15==4
14==5
13==2
FockJoin 默认线程池线程数量 = 3