1.问题背景说明以及原因分析2.自定义函数接口
2.1自定义函数式接口:有参有返回值
2.2自定义函数式接口:无参无返回值
2.3自定义函数式接口:有参无返回值
2.4自定义函数式接口:无参有返回值
3.java中::常用的使用方式
3.1类名::静态方法名
3.2对象名::非静态方法名
3.3类名::new(无参构造)
3.4类名::new(有参构造)
1.问题背景说明以及原因分析
问题来源与处理spring security跨域问题的配置信息,好奇
requestMatchers(CorsUtils::isPreFlightRequest)
为什么可以这样写.
ResourceServerConfiguration
配置信息
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceS
erverConfigurerAdapter {
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable().cors()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and().authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.and().authorizeRequests().requestMatchers((httpServletRequest)->CorsUtils.isPreFlightRequest(httpServletRequest)).permitAll()
.and().requestMatchers().anyRequest()
.and().anonymous()
.and().authorizeRequests()
.antMatchers(
"/webjars/**",
"/swagger/**",
"/captcha.jpg").permitAll()
.and()
.authorizeRequests()
.antMatchers("/**").authenticated();//配置所有访问控制,必须认证过后才可以访问
}
CorsUtils.java
中isPreFlightRequest
源码:
public abstract class CorsUtils {
// 省略部分代码
public static boolean isPreFlightRequest(HttpServletRequest request) {
return HttpMethod.OPTIONS.matches(request.getMethod()) && request.getHeader("Origin") != null && request.getHeader("Access-Control-Request-Method") != null;
}
}
AbstractRequestMatcherRegistry
中requestMatchers
源码:
public C requestMatchers(RequestMatcher... requestMatchers) {
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
return this.chainRequestMatchers(Arrays.asList(requestMatchers));
}
RequestMatcher
源码:
public interface RequestMatcher {
boolean matches(HttpServletRequest var1);
default RequestMatcher.MatchResult matcher(HttpServletRequest request) {
boolean match = this.matches(request);
return new RequestMatcher.MatchResult(match, Collections.emptyMap());
}
public static class MatchResult {
private final boolean match;
private final Map<String, String> variables;
}
AbstractRequestMatcherRegistry
中requestMatchers
接收的参数为RequestMatcher
的可变参数上数组.CorsUtils::isPreFlightRequest
中::这种写法是jdk8新特性中的lambda表达式写法,然后去查看RequestMatcher
接口,没有标注@FunctionalInterface注解,为什么也能生效?如果你也有这样的疑问请往下看.
首先想一下什么是函数式接口以及@FunctionalInterface作用
函数式接口:有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
@FunctionalInterface注解作用:用于校验是否符合函数式接口要求.不符合要求会有错误提示.
也就是说@FunctionalInterface有或是没有只要符合定义要求都算是函数式接口,这个是之前认知的一个误区.好回到RequestMatcher
源码接口中,只有matches
一个抽象方法,另外属性的是一个非抽象方法和内部类.完全符合函数式接口定义.所以支持函数式接口写法,下面自己实现几种类型的函数式接口。
2.自定义函数接口
2.1自定义函数式接口:有参有返回值
public interface PersonaInterfaceOne<P,R> {
// 有参有返回值,P表示参数,R表示返回结果,类似于Java.lang.Function
R test(P param);
}
jdk8自带function接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T var1);
default <V> Function<V, R> compose(Function<? super V, ? extends T> var1) {
Objects.requireNonNull(var1);
return (var2) -> {
return this.apply(var1.apply(var2));
};
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> var1) {
Objects.requireNonNull(var1);
return (var2) -> {
return var1.apply(this.apply(var2));
};
}
static <T> Function<T, T> identity() {
return (var0) -> {
return var0;
};
}
}
2.2自定义函数式接口:无参无返回值
public interface PersonaInterfaceTwo {
// 无参无返回值,类似于:java.lang.Runnable
void test();
}
jdk8自带Runnable接口
@FunctionalInterface
public interface Runnable {
void run();
}
2.3自定义函数式接口:有参无返回值
public interface PersonaInterfaceThree<P,A> {
// 有参无返回值,P为参数1,A为参数2;类似于java.util.function.Consumer,但此接口仅支持一个参数
void test(P param1,A param2);
}
jdk8自带consumer接口
@FunctionalInterface
public interface Consumer<T> {
void accept(T var1);
default Consumer<T> andThen(Consumer<? super T> var1) {
Objects.requireNonNull(var1);
return (var2) -> {
this.accept(var2);
var1.accept(var2);
};
}
}
2.4自定义函数式接口:无参有返回值
public interface PersonaInterfaceFour<R> {
// 无参有返回值,R为返回值,类似于:java.lang.until。Supplier
R test();
}
jdk8自带Supplier接口
@FunctionalInterface
public interface Supplier<T> {
T get();
}
3.java中::常用的使用方式
3.1类名::静态方法名
public class TestPersonalInterface {
public static String methodOne(int param){
return "methodOne excute"+param;
}
public static void main(String[] args) {
// 类名::静态方法名
// 自定义函数式接口
PersonaInterfaceOne<Integer, String> methodOne = TestPersonalInterface::methodOne;
String returnMsg = methodOne.test(2);
System.out.println(returnMsg); // 输出:methodOne excute2
// jdk8自带Function实现
// Function<Integer, String> methodOne = TestPersonalInterface::methodOne;
// String returnMsg = methodOne.apply(2);
// System.out.println(returnMsg);
}
}
3.2对象名::非静态方法名
public class TestPersonalInterface {
public String methodTwo(int param){
return "methodTwo excute"+param;
}
public static void main(String[] args) {
// 对象:: 非静态方法名
// 自定义函数式接口
PersonaInterfaceOne<Integer, String> methodTwo = new TestPersonalInterface()::methodTwo;
System.out.println(methodTwo.test(3)); // 输出:methodTwo excute3
// jdk8自带Function实现
// Function<Integer, String> methodTwo = new TestPersonalInterface()::methodTwo;
// System.out.println(methodTwo.apply(3)); // 输出:methodTwo excute3
}
}
3.3类名::new(无参构造)
public class TestPersonalInterface {
public TestPersonalInterface() {
System.out.println("无参构造执行");
}
public static void main(String[] args) {
// 类名:: new
// 自定义函数式接口
PersonaInterfaceTwo constructInfo = TestPersonalInterface::new;
constructInfo.test(); // 输出:无参构造执行
// Runnable constructInfo = TestPersonalInterface::new;
// constructInfo.run(); // 输出:无参构造执行
}
}
3.4类名::new(有参构造)
public class TestPersonalInterface {
public TestPersonalInterface(String name,Integer age) {
System.out.println("有参构造执行:"+name+"--"+age);
}
public static void main(String[] args) {
// 有参无返回值
PersonaInterfaceThree<String,Integer> constructWithArgs = TestPersonalInterface::new;
constructWithArgs.test("jack",123); // 输出:有参构造执行:jack--123
}
}