SpringMVC自定义注解实现接口调用

导读:本篇文章讲解 SpringMVC自定义注解实现接口调用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

环境:springboot2.2.10.RELEASE


开发步骤:

  1. 自定义的注解类
@Component
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CustomEndpoint {
}

@CustomEndpoint注解标识自定义的类(Bean)在该注解中添加了@Component注解为了让容器管理我们的类(生成Bean)。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PackMapping {
	// 请求URL
	String[] value() default {};
	// 请求的方法
	RequestMethod[] method() default {};
}

该注解就相当于@RequestMapping注解,定义请求接口。

  1. 自定义HandlerMapping

自定义HandlerMapping的作用是让HandlerMapping与我们自定义的@CustomEndpoint类相关联,简单说就是能够处理标有@CustomEndpoint注解的类。

public class CustomPackRequestHandlerMapping extends RequestMappingHandlerMapping {

  // 该方法是必须重写的,使得自定义的HandlerMapping能够处理标有@CustomEndpoint注解的类
	@Override
	protected boolean isHandler(Class<?> beanType) {
		return AnnotatedElementUtils.hasAnnotation(beanType, CustomEndpoint.class);
	}
	
  // 该方法也必须重写不然你的这个自定义HandlerMapping将轮不到就被(SimpleUrlHandlerMapping)处理了。
	@Override
    public void afterPropertiesSet() {
        super.setOrder(0); // 这里很重要使得我们的HandlerMapping能够排到最前面
        super.afterPropertiesSet();
    }
	
  // 该方法必须重写因为你要针对标有自定义@PackMapping注解的方法能够处理你的请求。
	@Override
	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo requestMappingInfo = createRequestMappingInfo(method) ;
		return requestMappingInfo ;
	}
	
	private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
		PackMapping packMapping = AnnotatedElementUtils.findMergedAnnotation(element, PackMapping.class);
		return (packMapping != null ? builderMapping(packMapping) : null);
	}
	
	private RequestMappingInfo builderMapping(PackMapping packMapping) {
		RequestMappingInfo.Builder builder = RequestMappingInfo
				.paths(packMapping.value())
				.methods(packMapping.method())
				.params(new String[] {})
				.headers(new String[] {})
				.consumes(new String[] {})
				.produces(new String[] {})
				.mappingName("") ;
		return builder.build() ;
	}

}

以上自定义的HandlerMapping重要的方法已经说明了。

  1. 配置HandlerMapping
@Configuration
public class CustomEndpointConfig {
	
	@Bean
	public CustomPackRequestHandlerMapping customPackRequestHandlerMapping() {
		CustomPackRequestHandlerMapping handlerMapping = new CustomPackRequestHandlerMapping() ;
		return handlerMapping ;
	}
	
}
  1. 测试
@CustomEndpoint
@ResponseBody
public class CustomWebController {

	@PackMapping("/custom/index")
	public Object index(String key) {
		return key ;
	}
	
}

 

SpringMVC自定义注解实现接口调用

 

到此开发一个自定义的HandlerMapping就完成了。

真正实际的调用(Controller方法)其实是HandlerAdapter。

AbstractHandlerMethodAdapter类中定义了如下方法,是专门为让子类来实现的,我们可以根据自己的需要作相应的重写。

protected abstract boolean supportsInternal(HandlerMethod handlerMethod);

查看
RequestMappingHandlerAdapter类的实现。

@Override
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}

这里在说下一些核心类之间的关系:

所有的拦截器也是与HandlerMapping关联的:

@Bean
	@SuppressWarnings("deprecation")
	public RequestMappingHandlerMapping requestMappingHandlerMapping(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
		mapping.setOrder(0);
		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
		mapping.setContentNegotiationManager(contentNegotiationManager);
		mapping.setCorsConfigurations(getCorsConfigurations());

		...

		return mapping;
	}

mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));

消息转换与HandlerAdapter相关联

@Bean
	public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcValidator") Validator validator) {

		RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
		adapter.setContentNegotiationManager(contentNegotiationManager);
		adapter.setMessageConverters(getMessageConverters());
		adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
		adapter.setCustomArgumentResolvers(getArgumentResolvers());
		adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

		if (jackson2Present) {
			adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
			adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
		}

		AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();
		configureAsyncSupport(configurer);
		if (configurer.getTaskExecutor() != null) {
			adapter.setTaskExecutor(configurer.getTaskExecutor());
		}
		if (configurer.getTimeout() != null) {
			adapter.setAsyncRequestTimeout(configurer.getTimeout());
		}
		adapter.setCallableInterceptors(configurer.getCallableInterceptors());
		adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

		return adapter;
	}

adapter.setMessageConverters(getMessageConverters());

 

好心人给个关注+转发谢谢啊

SpringBoot项目查看线上日志

 

SpringBoot项目查看线上日志

 

SpringBoot项目查看线上日志

 

SpringBoot项目查看线上日志

SpringMVC自定义注解实现接口调用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80059.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!