groovy编写spring的controller(三)支持annotation

groovy编写spring的controller(三)支持annotation

自定义扩展spring,让groovy编写的controller支持annotation,参考了比较老的spring论坛上的帖子,当然自己也做了修改。因为帖子的时间比较久远,不晓得新版本的spring是不是早就支持了。不过还是记录一下。

参考文章
http://forum.springsource.org/showthread.php?p=253380

1、扩展spring,自定义了 xmlns:groovy="http://www.sillycat.com/schema/groovy"
handler的代理类ProxyAwareAnnotationMethodHandlerAdapter.java,代码如下:
package com.sillycat.easygroovyplugin.handlers;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
public class ProxyAwareAnnotationMethodHandlerAdapter extends
AnnotationMethodHandlerAdapter {
@Override
public ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
handler = unwrapHandler(handler);
return super.handle(request, response, handler);
}
@Override
public boolean supports(Object handler) {
handler = unwrapHandler(handler);
return super.supports(handler);
}
private Object unwrapHandler(Object handler) {
if (handler instanceof Advised) {
try {
TargetSource targetSource = ((Advised) handler)
.getTargetSource();
return targetSource.getTarget();
} catch (Exception x) {
throw new RuntimeException(x);
}
} else {
return handler;
}
}
}

groovy的namehandler类GroovyNamespaceHandler.java:
package com.sillycat.easygroovyplugin.handlers;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import com.sillycat.easygroovyplugin.parsers.GroovyScanBeanDefinitionParser;
public class GroovyNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("scan",
new GroovyScanBeanDefinitionParser());
}
}
其中的解析XML配置的类GroovyScanBeanDefinitionParser.java:
package com.sillycat.easygroovyplugin.parsers;
import java.io.IOException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.scripting.config.LangNamespaceUtils;
import org.springframework.scripting.groovy.GroovyScriptFactory;
import org.w3c.dom.Element;
import com.sillycat.easygroovyplugin.utils.SystemConfiguration;
public class GroovyScanBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
String pattern = element.getAttribute("source-pattern");
String filepath = SystemConfiguration.getString("groovy.file.path");
pattern = filepath + pattern;
LangNamespaceUtils
.registerScriptFactoryPostProcessorIfNecessary(parserContext
.getRegistry());
try {
Resource[] resources = getResources(parserContext
.getReaderContext().getResourceLoader(), pattern);
for (Resource resource : resources) {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(GroovyScriptFactory.class);
bd.setSource(resource);
ConstructorArgumentValues cav = bd
.getConstructorArgumentValues();
int constructorArgNum = 0;
cav.addIndexedArgumentValue(constructorArgNum++, "file:/"
+ resource.getFile().getAbsolutePath());
String beanName = parserContext.getReaderContext()
.generateBeanName(bd);
parserContext.getRegistry()
.registerBeanDefinition(beanName, bd);
}
} catch (IOException x) {
throw new RuntimeException(x);
}
return null;
}
private Resource[] getResources(ResourceLoader resourceLoader,
String pattern) throws IOException {
if (resourceLoader instanceof ResourcePatternResolver) {
return ((ResourcePatternResolver) resourceLoader)
.getResources(pattern);
} else {
return new Resource[] { resourceLoader.getResource(pattern) };
}
}
}

由于parser在取XML文件里面配置的${groovy.file.path},虽然配置了spring的propertyConfigurer,但是还是解析不了。所以用了同事写的一个
SystemConfiguration.java来取得配置
package com.sillycat.easygroovyplugin.utils;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
public class SystemConfiguration {
private static CompositeConfiguration config;
private static PropertiesConfiguration propertiesConfig;
static {
config = new CompositeConfiguration();
if (propertiesConfig == null) {
try {
propertiesConfig = new PropertiesConfiguration(
"easygroovy.properties");
propertiesConfig
.setReloadingStrategy(new FileChangedReloadingStrategy());
config.addConfiguration(propertiesConfig);
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
}
private SystemConfiguration() {
}
public static String getString(String propertyKey) {
return config.getString(propertyKey);
}
public static String getString(String propertyKey, String defaultValue) {
return config.getString(propertyKey, defaultValue);
}
public static int getInt(String propertyKey) {
return config.getInt(propertyKey);
}
public static int getInt(String key, int defaultValue) {
return config.getInt(key, defaultValue);
}
public static float getFloat(String propertyKey) {
return config.getFloat(propertyKey);
}
public static float getFloat(String propertyKey, float defaultValue) {
return config.getFloat(propertyKey, defaultValue);
}
public static boolean getBoolean(String propertyKey) {
return config.getBoolean(propertyKey);
}
public static boolean getBoolean(String propertyKey, boolean defualtValue) {
return config.getBoolean(propertyKey, defualtValue);
}
public static String[] getStringArray(String propertyKey) {
return config.getStringArray(propertyKey);
}
public static List<String> getStringList(String propertyKey) {
List<String> list = new ArrayList<String>();
String[] strArr = getStringArray(propertyKey);
for (String value : strArr) {
list.add(value);
}
return list;
}
@SuppressWarnings("unchecked")
public static List getList(String propertyKey) {
return config.getList(propertyKey);
}
}
构造jar包的META-INF,在src/main/resouces下新增目录
com.sillycat.easygroovyplugin.handlers 存放文件groovy.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.sillycat.com/schema/groovy"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.sillycat.com/schema/groovy"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines utility elements for groovy script convenience operations
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="scan">
<xsd:annotation>
<xsd:documentation><![CDATA[
Allows for scanning the file system for groovy scripts and defining
dynamic language beans for them in the application context
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="source-pattern" type="xsd:string"
use="required" />
</xsd:complexType>
</xsd:element>
</xsd:schema>

建立目录META-INF
在里面增加文件spring.handlers,内容如下:
http\://www.sillycat.com/schema/groovy=com.sillycat.easygroovyplugin.handlers.GroovyNamespaceHandler
增加文件spring.schemas,内容如下:
http\://www.sillycat.com/schema/groovy/groovy.xsd=com/sillycat/easygroovyplugin/handlers/groovy.xsd
我是使用MAVEN2来管理JAR的,所以用如下pom.xml打包,easygroovyplugin-1.0.jar就OK了。这个就是我们对spring的自定义扩展了。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sillycat.easygroovyplugin</groupId>
<artifactId>easygroovyplugin</artifactId>
<name>easygroovyplugin</name>
<version>1.0</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
</dependency>
</dependencies>
</project>

问题一:
当本地部署的apache不能访问,也就是
http://www.sillycat.com/schema/groovy/groovy.xsd
不能访问的时候,报错如下:
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'groovy:scan'.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)

解决:
修改了easygroovyplugin的jar里面的spring.schemas为不采用META-INF的相对位置,而是从
这个路径(com/sillycat/easygroovyplugin/handlers/groovy.xsd)找,就OK啦。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值