`
mengqingyu
  • 浏览: 333788 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Spring扩展点

阅读更多
Spring扩展点

1.IOC生成类全名

<!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="cn.com.demo.**.controller" 
	name-generator="cn.com.demo.framework.spring.context.annotation.FullNameBeanNameGenerator"  use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>


public class FullNameBeanNameGenerator extends AnnotationBeanNameGenerator{

	@Override
	protected String buildDefaultBeanName(BeanDefinition definition) {
		return definition.getBeanClassName();
	}

}



2.转换生成映射的URL大小写

<!-- 通过 @Controller 和 @RequestMapping 从url定位到类的方法, 自定义CoC实现, 不要再配置annotation-driven -->
<bean class="cn.com.demo.framework.web.springmvc.support.CocRequestMappingHandlerMapping">
	<property name="basePackage" value="cn.com.demo" />
</bean>


public class CocRequestMappingHandlerMapping extends RequestMappingHandlerMapping{
	
	/** Controller类的后缀 */
	private static final String CONTROLLER_SUFFIX = "Controller";
	
	/** 映射url路径的根 */
	private String basePackage;
	
	//父类的属性
	private boolean useSuffixPatternMatch = true;
	private boolean useTrailingSlashMatch = true;
	private final List<String> fileExtensions = new ArrayList<String>();
	
	/**
	 * Look for handler methods in a handler.
	 * @param handler the bean name of a handler or a handler instance
	 */
	protected void detectHandlerMethods(final Object handler) {
		//Assert.notNull(this.basePackage, "must config basePackage!");
		super.detectHandlerMethods(handler);
	}
	
	/**
	 * 这个只改了createRequestMappingInfo的调用,增加了参数
	 * Uses method and type-level @{@link RequestMapping} annotations to create
	 * the RequestMappingInfo.
	 *
	 * @return the created RequestMappingInfo, or {@code null} if the method
	 * does not have a {@code @RequestMapping} annotation.
	 *
	 * @see #getCustomMethodCondition(Method)
	 * @see #getCustomTypeCondition(Class)
	 */
	@Override
	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo info = null;
		RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
		if (methodAnnotation != null) {
			RequestCondition<?> methodCondition = getCustomMethodCondition(method);
			info = createRequestMappingInfo(methodAnnotation, methodCondition, method, handlerType);
			RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
			if (typeAnnotation != null) {
				RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
				info = createRequestMappingInfo(typeAnnotation, typeCondition, method, handlerType).combine(info);
			}
			
		}
		return info;
	}
	
	/**
	 * 将父类同名方法加入controller的类型和方法参数
	 */
	private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition, Method method, Class<?> handlerType) {
		
		String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());
		
		//@RequestMapping没有配置value, 加入coc部分
		if( patterns.length==0 ){
			StringBuilder p = new StringBuilder();
			if (this.basePackage != null) {
				String packageName = ClassUtils.getPackageName(handlerType);
				if (packageName.startsWith(this.basePackage)) {
					String subPackage = packageName.substring(this.basePackage.length()).replace('.', '/');
					if( subPackage.endsWith("/controller") ){
						//去掉/backup/controller的 /controller
						subPackage = subPackage.substring(0,subPackage.indexOf("/controller"));
					}
					p.append(subPackage.toLowerCase());
					p.append("/");
				}
			}
			
			//类名去掉后缀小写
			String className = handlerType.getSimpleName();
			className = (className.endsWith(CONTROLLER_SUFFIX) ?
					className.substring(0, className.lastIndexOf(CONTROLLER_SUFFIX)) : className);
			
			p.append(className.toLowerCase()).append("/");//类名小写
			p.append(method.getName().toLowerCase());//方法名小写
			patterns = new String[]{p.toString()};
		}
		
		return new RequestMappingInfo(
				new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
						this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions),
				new RequestMethodsRequestCondition(annotation.method()),
				new ParamsRequestCondition(annotation.params()),
				new HeadersRequestCondition(annotation.headers()),
				new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
				new ProducesRequestCondition(annotation.produces(), annotation.headers(), getContentNegotiationManager()),
				customCondition);
	}

	//----------------------set get
	public void setBasePackage(String basePackage) {
		this.basePackage = basePackage;
	}

	public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
		this.useSuffixPatternMatch = useSuffixPatternMatch;
	}

	public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {
		this.useTrailingSlashMatch = useTrailingSlashMatch;
	}
	
	
}



3.参数自定义类型转换

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
	<property name="webBindingInitializer">
		<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
			<property name="conversionService">
				<bean class="org.springframework.context.support.ConversionServiceFactoryBean">
					<property name="converters">
						<list>
							<bean class="cn.com.demo.framework.spring.core.convert.converter.StringToDateConverter"/>
						</list>
					</property>
				</bean>
			</property>
		</bean>
	</property>
	<property name="customArgumentResolvers">
		<list>
			<bean class="cn.com.demo.framework.web.springmvc.support.method.support.crud.CrudHandlerMethodArgumentResolver"/>
		</list>
	</property>
	<property name="messageConverters">
		<list>
			<bean class="org.springframework.http.converter.StringHttpMessageConverter">
				<constructor-arg value="UTF-8" />
			</bean>
			<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
				<property name="objectMapper">
					<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
						<property name="serializers">
							<array>
								<bean class="cn.com.demo.canyin.common.springmvc.converter.json.LongToStringJsonSerializer" />
							</array>
						</property>
						<property name="dateFormat">
							<bean class="java.text.SimpleDateFormat">
								<constructor-arg value="yyyy-MM-dd'T'HH:mm:ss.SSS" />
							</bean>
						</property>
					</bean>
				</property>
			</bean>
			<bean class="org.springframework.http.converter.ResourceHttpMessageConverter" />
		</list>
	</property>
</bean>


public class StringToDateConverter implements Converter<String, Date>{
	
	@Override
	public Date convert(String source) {
		
		if( source==null || source.length()==0 )
			return null;
		
		int length = source.length();
		
		switch (length) {
			case 5:
				return parse("HH:mm", source);
			case 10:
				return parse("yyyy-MM-dd", source);
				
			case 19:
			case 21:
			case 22:
				return parse("yyyy-MM-dd HH:mm:ss", source);
				
			case 23:
				return parse("yyyy-MM-dd'T'HH:mm:ss.SSS", source);
			case 28:
			try {
				return new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy", Locale.US).parse(source);
			} catch (ParseException e) {
				throw new RuntimeException("时间转换格式异常,datestr:" + source, e);
			}
			default:
				throw new RuntimeException("Unsupport Date Format: " + source);
		}
	}
	
	/**
	 * 解析date
	 */
	private Date parse(String format, String date){
		try {
			return new SimpleDateFormat(format).parse(date);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
}

public class CrudHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver{

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		Class<?> paramType = parameter.getParameterType();
		return QueryParam.class.isAssignableFrom(paramType);
	}

	@Override
	public Object resolveArgument(MethodParameter parameter,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
			WebDataBinderFactory binderFactory) throws Exception {
		
		Class<?> paramType = parameter.getParameterType();
		
		//查询参数
		QueryParam p = parseQueryParam(parameter, webRequest);
		return p;
	}
	
	/**
	 * <b>功能描述:</b>解析查询参数<br>
	 */
	@SuppressWarnings("serial")
	private QueryParam parseQueryParam(MethodParameter parameter, NativeWebRequest webRequest){
		QueryParam p = new QueryParam();
		//分页参数
		p.setStart(getInteger(webRequest, "start"));
		p.setLimit(getInteger(webRequest, "limit"));
		String sort = webRequest.getParameter("sort");
		if(StringUtils.isNotBlank(sort)){
			SortExpression[] orderBy = JsonConverterUtils.getJc().fromJson(sort, SortExpression[].class);
			DefaultConvertName dcn = new DefaultConvertName();
			orderBy[0].setProperty(dcn.convertToColumnName(orderBy[0].getProperty()));
			p.setSort(orderBy[0].toSqlString());
		}
		return p;
	}
	
	/**
	 * 获取整数参数
	 */
	private Integer getInteger(NativeWebRequest webRequest, String name){
		String p = webRequest.getParameter(name);
		
		if( p==null || p.length()==0 )
			return null;
		
		return Integer.valueOf(p);
	}
	
	/**
	 * 如果是get方法, 编码参数
	 */
	private String encodeParameter(NativeWebRequest webRequest, String paramName){
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		String p = webRequest.getParameter(paramName);
		if( "GET".equalsIgnoreCase(request.getMethod())){
			return RequestUtil.encodeParameter(p);
		}
		return p;
	}
	
}

public class LongToStringJsonSerializer extends JsonSerializer<Long> {
	
	@Override
	public Class<Long> handledType() {
		return Long.class;
	}

	@Override
	public void serialize(Long value, JsonGenerator jgen, SerializerProvider provider) 
			throws IOException, JsonProcessingException {
		jgen.writeString(value.toString());
	}
	
}



4.自定义异常拦截器

<!-- mvc exception handler -->
<bean id="handlerExceptionResolver" class="cn.com.demo.framework.enterprise.spring.web.ProjectHandlerExceptionResolver"></bean>


public class ProjectHandlerExceptionResolver implements HandlerExceptionResolver{
	
	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	/** json 转换 */
	@Resource private JsonConverter jsonConverter;

	@Resource private LogManageService logManageService;
	
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, 
				Object handler, Exception ex) {
		
		return null;
	}

	/**
	 * <b>功能描述:</b>
	 * 是否ExtForm的StandardSubmit模式<br>
	 * 前台需要额外传入X-Requested-With的参数来说明本次提交为StandardSubmit
	 */
	private boolean isExtFormStandardSubmit(HttpServletRequest request){
		return request.getParameter("X-Requested-With")!=null;
	}
}


分享到:
评论

相关推荐

    spring扩展点测试示例代码

    这个压缩包提供的"spring扩展点测试示例代码"是一个实例,帮助我们理解如何在实践中利用Spring的扩展点进行自定义功能的实现。 首先,Spring的核心设计理念之一就是“依赖注入”(Dependency Injection,DI),它...

    Spring常用注解和扩展点

    Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点,Spring常用注解和扩展点

    史上最全spring以及扩展功能jar

    3. **Spring AOP**:面向切面编程模块,允许我们定义“切面”,这些切面可以在程序运行时插入到其他对象的执行流程中,实现如日志、事务管理等跨切面关注点。 4. **Spring MVC**:模型-视图-控制器架构,是Spring...

    spring-扩展点-namespacehandler(Spring自定义标签)

    在Spring框架中,扩展点是允许用户自定义行为的关键组件,而`NamespaceHandler`就是其中的一个重要扩展点,主要用于处理自定义的XML命名空间。当我们需要在Spring配置文件中引入自定义标签时,`NamespaceHandler`起...

    spring扩展原理1

    本文主要探讨Spring扩展原理,特别是`BeanFactoryPostProcessor`、`BeanDefinitionRegistryPostProcessor`以及`ApplicationListener`这三种核心扩展点。 首先,`BeanFactoryPostProcessor`是Spring IOC容器中的一种...

    4.Spring应用扩展.pptx

    《Spring应用扩展》 在Spring框架中,应用扩展是一个重要的概念,它涉及到Spring的灵活性和可配置性。扩展Spring的应用通常包括对配置的拓展、Bean的作用域管理以及依赖注入的实现方式。以下将详细讲解这些知识点。...

    Spring3.0.5扩展支持AOP获取HttpServletResponse

    在Spring 3.0.5版本中,Spring扩展了对AOP的支持,特别是在处理HTTP响应时,可以通过AOP来获取`HttpServletResponse`对象。`HttpServletResponse`是Servlet API中的核心接口,它用于封装服务器向客户端发送的响应...

    对spring做java注解扩展

    本文将深入探讨如何在Spring框架中利用Java注解进行扩展,以提升代码的可读性和可维护性。 首先,我们需要了解Java注解(Annotation)。注解是Java语言的一种元数据,它提供了在编译时或运行时对代码进行信息附加的...

    Springboot启动扩展点超详细教程小结

    Springboot启动扩展点是Spring框架的核心思想,容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片。Springboot更是封装了Spring,遵循约定大于配置,加上自动装配的机制。很多时候我们...

    Spring中的Context你真的懂了吗

    扩展点集合存放 Spring 扩展点(主要是 BeanFactoryPostProcessor、BeanPostProcessor)接口的 list 集合。 除了了解 Spring Context 的组成部分外,我们还需要了解它的生命周期。Spring Context 的生命周期主要...

    Spring+LDAP实现单点登录

    Spring框架与LDAP(轻量级目录访问协议)的结合使用,可以实现高效的单点登录(Single Sign-On,简称SSO)系统。SSO允许用户在多个应用系统中只需要登录一次,即可访问所有相互信任的应用系统,提高了用户体验并简化...

    Spring5.pdf

    Spring Boot是Spring框架的一个重要扩展,它提供了一种快速配置的方式来简化新Spring应用的初始搭建以及开发过程。它包含了一系列默认配置来帮助开发者快速开始项目,并且支持自动配置特性,能够自动配置Spring应用...

    Spring Cloud Gateway 整合 Spring Security 统一登录认证鉴权

    在微服务架构中,Spring Security 可以帮助我们保护每个微服务的入口点,确保只有经过验证的用户才能访问受保护的资源。 整合Spring Security到Spring Cloud Gateway的过程通常包括以下步骤: 1. **配置Redis**:...

    spring类库 spring类库

    7. **Spring Aspects**:此模块提供了AOP的扩展,支持自定义切面和通知类型,增强了Spring的面向切面编程能力。 8. **Spring WebFlux**:对于反应式编程,Spring WebFlux提供了非阻塞的Web开发模型,适用于高并发和...

    Spring容器扩展机制的实现原理

    BeanFactoryPostProcessor接口是Spring提供的一种扩展点,它允许在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做一些额外的操作,例如修改bean定义的某些属性或者增加其他信息等。...

    Spring技术内幕:深入解析Spring架构与设计原理[汇编].pdf

    * AOP(Aspect-Oriented Programming): Spring使用AOP来实现面向方面的编程,提高系统的可维护性和可扩展性。 2. Spring核心概念 Spring的核心概念包括: * Bean:Spring中的Bean是指一个 Java对象,Bean可以...

    spring攻略 第2版

    另外,Spring Cloud扩展了Spring Boot的功能,提供了服务发现、负载均衡、配置中心等一系列微服务相关的工具,为构建大规模分布式系统提供了便利。 Spring框架还包含对消息处理的支持,如Spring AMQP,它提供了对...

    Spring 揭秘 全面 深入了解Spring

    《Spring 揭秘:全面深入了解Spring》是一本旨在帮助开发者深入理解并熟练掌握Spring框架的权威指南。...通过阅读这本书,你将能够深入理解Spring的内部机制,更好地利用Spring来构建高效、可扩展的企业级应用。

    spring_in_action-sixth-edition.pdf

    下面是对 Spring Framework 的详细知识点总结: 1. 什么是 Spring? Spring 是一个基于 Java 的开源框架,提供了一个通用的编程模型和配置机制,帮助开发者快速构建企业级应用程序。Spring 的主要特点是轻量级、...

Global site tag (gtag.js) - Google Analytics