WebMvcConfigurer是springMvc提供的一个可以扩展的配置springmvc的,那么在springboot中如何使用呢?
springboot官网提到WebMvcConfigurer是配置跨域Cors引出的:
官方实例:
@Configuration(proxyBeanMethods = false)
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
从官方给出的实例可以看出,我们只需要返回WebMvcConfigurer对象将其注册到spring中即可,
那么我们就来看一下WebMvcConfigurer的源码,看下那些是我们可以操作的。
package org.springframework.web.servlet.config.annotation;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
public interface WebMvcConfigurer {
/**
* HandlerMappings路径匹配选项,
* 也就是可以自己定义路径的匹配规则
*/
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
default void addInterceptors(InterceptorRegistry registry) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
1、configurePathMatch路径匹配规则
package com.osy.config;
import com.osy.annotation.AdminController;
import com.osy.annotation.AppController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration
public class WebMvcConfiguration {
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 是否存在尾\来进行匹配 /user和/user/等效的,同样可以进行匹配
configurer.setUseTrailingSlashMatch(true);
// 这个配置需要传入一个UrlPathHelper对象,UrlPathHelper是一个处理url地址的帮助类,
// 他里面有一些优化url的方法
// 比如:getSanitizedPath,就是将// 换成/ 所以我们在输入地址栏的时候,//也是没有问题的,
// 这里使用springmvc默认的就可以了,如果想要深入了解,那么我们后续在深入
UrlPathHelper urlPathHelper = new UrlPathHelper();
configurer.setUrlPathHelper(urlPathHelper);
// 路径匹配器 PathMatcher是一个接口,springmvc默认使用的是AntPathMatcher
// 这里也就不深入了,使用springmvc默认的就可以,如果想要深入了解,那么我们后续在深入,查看AntPathMatcher的源码
// configurer.setPathMatcher();
// 配置路径前缀
// 下面这样写的意思是:对含有AdminController注解的controller添加/admin地址前缀
configurer.addPathPrefix("admin", c -> c.isAnnotationPresent(AdminController.class));
configurer.addPathPrefix("app", c -> c.isAnnotationPresent(AppController.class));
// 当然这里也不一定非得用注解来实现:也可以用分包:
// configurer.addPathPrefix("app", c -> c.getPackage().getName().contains("com.osy.controller.admin"));
// configurer.addPathPrefix("app", c -> c.getPackage().getName().contains("com.osy.controller.app"));
}
};
}
}
这里我们就来测试一下setUseTrailingSlashMatch和addPathPrefix吧
创建实体类:
package com.osy.entity;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建注解annotation包:
创建相对应的注解:当然这里也不一定非得用注解来实现:
package com.osy.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface AdminController {
}
package com.osy.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface AppController {
}
在controller包下面创建admin包和app包:一般不同端的数据接口都会分开的。然后再对应的包下创建IndexController.java
admin包下面的:
package com.osy.controller.admin;
import com.osy.annotation.AdminController;
import com.osy.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@AdminController
@RestController("adminIndexController")
public class IndexController {
@GetMapping("getUser")
public User getUser(){
User user = new User();
user.setName("我是admin用户");
return user;
}
}
app包下面的:
package com.osy.controller.app;
import com.osy.annotation.AppController;
import com.osy.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@AppController
@RestController("appIndexController")
public class IndexController {
@GetMapping("getUser")
public User getUser(){
User user = new User();
user.setName("我是app用户");
return user;
}
}
注意:RestController后面打上名称,使用为IndexController在注入spring的时候,会重复,报错,加上名称就不重复了,原因:spring注入的时候,如果不给出名称,那么他就以类名首字母小写来定义的。
然后我们访问:
http://localhost:8080/admin/getUser
结果:{“name”:“我是admin用户”}
http://localhost:8080/app/getUser
{“name”:“我是app用户”}
如果单独访问http://localhost:8080/getUser是404,无法放访问到的,所以可见,这个是有用的。
然后又测试一下http://localhost:8080/app/getUser/
最后得到的结果也是**{“name”:“我是app用户”}**,所以都是有效果的。