webmvc和webflux作为spring framework的两个重要模块,代表了两个IO模型,阻塞式和非阻塞式。SpringWebflux是SpringFramework5.0添加的新功能。
webmvc是基于web servlet的阻塞式模型(一般称为oio),一个请求到达服务器后会单独分配一个线程去处理请求,如果请求包含IO操作,线程在IO操作结束之前一直处于阻塞等待状态,这样线程在等待IO操作结束的时间就浪费了。Web on Servlet Stack
webflux是基于web reactor的非阻塞模型(一般称为nio),webflx是反应式编程,反应式编程是关于非阻塞应用程序,它们是异步和事件驱动的,需要少量线程垂直扩展(即在JVM内)而不是水平扩展(即通过集群)。反应式应用的一个关键方面是背压的概念,这是一种确保生产者不会压倒消费者的机制。例如,当HTTP连接太慢时,在从数据库扩展到HTTP响应的反应组件的管道中,数据存储库也可以减速或完全停止,直到网络容量释放。比如,当请求到达服务器后也会分配一个线程去处理请求,如果请求包含IO操作,线程在IO操作结束之前不再是处于阻塞等待状态,而是去处理其他事情,等到IO操作结束之后,再通知(得益于系统的机制)线程继续处理请求。它也自持函数式编程来定义路由端点处理请求,通过使用 CompletableFuturefrom Java 8通过lambda表达式组成后续操作。Web on Reactive Stack
总结: struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的,在Servlet3.1之后才有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上,因此它的运行环境的可选择行要比传统web框架多的多。SpringMVC采用命令式编程方,而WebFlux则是基于异步响应式编程。 SpringWebFlux并不会提高程序的运行速度(相对于SpringMVC来说),而是在有限的资源下提高系统的伸缩性,相对于提高程序的高并发。
1.依赖关系
//spring mvc 依赖 | |
<dependencies> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-web</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-security</artifactId> | |
</dependency> | |
</dependencies> | |
//spring webflux 依赖 | |
<dependencies> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-security</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-webflux</artifactId> | |
</dependency> | |
</dependencies> |
springboot-webflux
springboot-web
2.服务器配置
webmvc使用实现WebMvcConfigurer接口,详细SpringBoot---WebMvcConfigurer详解_zhangpower1993的博客-CSDN博客_webmvcconfigurer
import org.springframework.context.annotation.Configuration; | |
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |
@Configuration | |
@EnableWebMvc //使用注解@EnableWebMvc | |
public class MyWebConnfig implements WebMvcConfigurer { | |
// addInterceptors:拦截器 | |
// addViewControllers:页面跳转 | |
// addResourceHandlers:静态资源 | |
// configureDefaultServletHandling:默认静态资源处理器 | |
// configureViewResolvers:视图解析器 | |
// configureContentNegotiation:配置内容裁决的一些参数 | |
// addCorsMappings:跨域 | |
// configureMessageConverters:信息转换器 | |
} |
webflux实现WebFluxConfigurer 接口
import org.springframework.context.annotation.Configuration; | |
import org.springframework.web.reactive.config.EnableWebFlux; | |
import org.springframework.web.reactive.config.WebFluxConfigurer; | |
@Configuration | |
@EnableWebFlux //使用注解@EnableWebFlux | |
public class MyWebConnfig implements WebFluxConfigurer { | |
// addResourceHandlers:静态资源 | |
// addCorsMappings:跨域 | |
} |
3.认证配置
Spring MVC的Security是通过Servlet的Filter实现的,而WebFlux的响应式Security是基于WebFilter实现的,由一些列的WebFilter形成的过滤器链。
3.1 Spring MVC的Security
webmvc-认证依赖于用户数据服务,需要实现UserDetailsService接口
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |
import org.springframework.security.core.Authentication; | |
import org.springframework.security.core.AuthenticationException; | |
import org.springframework.security.core.userdetails.UserDetails; | |
import org.springframework.security.core.userdetails.UserDetailsService; | |
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |
import org.springframework.security.web.AuthenticationEntryPoint; | |
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter implements | |
AuthenticationEntryPoint, //未验证回调 | |
AuthenticationSuccessHandler, //验证成功回调 | |
AuthenticationFailureHandler, //验证失败回调 | |
LogoutSuccessHandler { | |
@Override | |
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { | |
} | |
@Override | |
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { | |
} | |
@Override | |
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | |
} | |
@Override | |
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | |
} | |
@Override | |
protected void configure(HttpSecurity http) throws Exception { | |
http.csrf().disable().authorizeRequests().antMatchers("/swagger*/**", "/webjars/**", "/v2/api-docs").permitAll(); | |
} | |
/** | |
* 认证的服务 | |
* @param auth | |
* @throws Exception | |
*/ | |
@Override | |
protected void configure(AuthenticationManagerBuilder auth) throws Exception { | |
auth.userDetailsService(new UserDetailsService() { | |
@Override | |
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { | |
return null; | |
} | |
}); | |
} | |
} |
3.2 Spring Webflux的Security
webflux-认证依赖于用户数据服务,需实现ReactiveUserDetailsService
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; | |
import org.springframework.security.config.web.server.ServerHttpSecurity; | |
import org.springframework.security.core.Authentication; | |
import org.springframework.security.core.AuthenticationException; | |
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; | |
import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService; | |
import org.springframework.security.core.userdetails.User; | |
import org.springframework.security.core.userdetails.UserDetails; | |
import org.springframework.security.web.server.SecurityWebFilterChain; | |
import org.springframework.security.web.server.ServerAuthenticationEntryPoint; | |
import org.springframework.security.web.server.WebFilterExchange; | |
import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler; | |
import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; | |
import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; | |
import org.springframework.web.server.ServerWebExchange; | |
import org.springframework.web.server.WebFilter; | |
import org.springframework.web.server.WebFilterChain; | |
import reactor.core.publisher.Mono; | |
@Configuration | |
@EnableWebFluxSecurity | |
public class MyWebFluxSecurityConfig implements WebFilter, //拦截器 | |
ServerLogoutSuccessHandler, //登出成功回调 | |
ServerAuthenticationEntryPoint, //验证入口 | |
ServerAuthenticationFailureHandler, //验证成功回调 | |
ServerAuthenticationSuccessHandler { | |
@Override | |
public Mono<Void> commence(ServerWebExchange serverWebExchange, AuthenticationException e) { | |
return null; | |
} | |
@Override | |
public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException e) { | |
return null; | |
} | |
@Override | |
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { | |
return null; | |
} | |
@Override | |
public Mono<Void> onLogoutSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { | |
return null; | |
} | |
@Override | |
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { | |
return null; | |
} | |
@Bean | |
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { | |
http | |
.authorizeExchange() | |
.anyExchange().authenticated() | |
.and() | |
.httpBasic().and() | |
.formLogin(); | |
return http.build(); | |
} | |
@Bean | |
public ReactiveUserDetailsPasswordService cuseactiveUserDetailsPasswordService() { | |
UserDetails user = User.withDefaultPasswordEncoder() | |
.username("user") | |
.password("user") | |
.roles("USER") | |
.build(); | |
return new MapReactiveUserDetailsService(user); | |
} | |
} |
UserDetailsPasswordService 运行在 Servlet也就是webmvc上,ReactiveUserDetailsPasswordService 运行在WebFlux
4.Session配置
webmvc使用@EnableRedisHttpSession
webflux使用@EnableRedisWebSession、
5.swagger配置
webmvc使用@EnableSwagger2
webflux使用@EnableSwagger2WebFlux