kda*_*bir 5 java groovy spring-mvc
我在src/main/groovy /中有这个...
package com.mycompany.web;
// imports....
@Controller
class GroovyController {
@RequestMapping("/status_groovy")
public @ResponseBody String getStatus() {
return "Hello World from groovy!";
}
}
Run Code Online (Sandbox Code Playgroud)
使用maven 3和spring 3.1(里程碑).Spring MVC非常适合java控制器,一切都设置得很好.groovy类编译得很好,可以在classes目录中找到java控制器类.
我在java(JavaController)中用相同的包编写了类似的控制器,但是在src/main/java下,它被spring和map正确选中,当我点击url时,我可以在屏幕上看到响应.
package com.mycompany.web;
// imports....
@Controller
class JavaController {
@RequestMapping("/status")
public @ResponseBody String getStatus() {
return "Hello World!";
}
}
Run Code Online (Sandbox Code Playgroud)
Jetty通常在日志中没有错误,但在我看不到groovy url被映射,而我可以看到java.
2011-09-23 16:05:50,412 [main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/status],methods=[],params=[],headers=[],consumes=[],produces=[]}" onto public java.lang.String com.mycompany.web.JavaController.getStatus()
Run Code Online (Sandbox Code Playgroud)
所有设置都很好,因为应用程序的其他部分正常工作与注释(组件扫描等),只是我不能得到映射的URL GroovyController
任何人都可以解释为了Controller在常规工作中写下需要做些什么吗?
PS:我正在避免使用GroovyServlet来运行脚本,因为它涉及bean注入和url路径映射时有很大的缺点.
尽管Ben(我与之合作)充分尊重,但问题不在于Spring正在创建一个cglib代理.相反,它正在创建一个动态JDK(或基于接口的)代理.这种创建代理的方法只能实现在目标实现的接口中声明的方法.实际上,您希望 Spring创建一个cglib代理,该代理创建一个代理,该代理是目标对象的子类,因此可以重新创建其所有公共方法.除非另外指定,否则Spring将在目标对象未实现任何接口时创建cglib代理,否则创建基于接口的代理.由于所有Groovy对象都实现了GroovyObject,因此即使您没有在Groovy控制器中显式实现任何接口,也会获得基于接口的代理.Ben的解决方案是正确的,因为如果您使用所有控制器方法创建一个接口,您将获得预期的行为.另一种方法是创建一个BeanFactoryPostProcessor,它指示Spring为实现GroovyObject和只有GroovyObject的类创建cglib代理.这是代码:
/**
* Finds all objects in the bean factory that implement GroovyObject and only GroovyObject, and sets the
* AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE value to true. This will, in the case when a proxy
* is necessary, force the creation of a CGLIB subclass proxy, rather than a dynamic JDK proxy, which
* would create a useless proxy that only implements the methods of GroovyObject.
*
* @author caleb
*/
public class GroovyObjectTargetClassPreservingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(GroovyObjectTargetClassPreservingBeanFactoryPostProcessor.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanDefName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanDefName);
//ignore abstract definitions (parent beans)
if (bd.isAbstract())
continue;
String className = bd.getBeanClassName();
//ignore definitions with null class names
if (className == null)
continue;
Class<?> beanClass;
try {
beanClass = ClassUtils.forName(className, beanFactory.getBeanClassLoader());
}
catch (ClassNotFoundException e) {
throw new CannotLoadBeanClassException(bd.getResourceDescription(), beanDefName, bd.getBeanClassName(), e);
}
catch (LinkageError e) {
throw new CannotLoadBeanClassException(bd.getResourceDescription(), beanDefName, bd.getBeanClassName(), e);
}
Class<?>[] interfaces = beanClass.getInterfaces();
if (interfaces.length == 1 && interfaces[0] == GroovyObject.class) {
logger.debug("Setting attribute {} to true for bean {}", AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, beanDefName);
bd.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, true);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
只需在您的上下文中包含此类型的bean,瞧!您可以使用Groovy控制器而无需定义接口.
不幸的是,如果您想在 Groovy 中运行它,您必须为您的 Controller 类创建一个接口并注释方法定义。Spring 使用 Cglib 为您的类创建一个代理。但是,如果不为控制器创建自定义接口,Spring 就会进行代理,groovy.lang.GroovyObject因为默认情况下所有 Groovy 对象都实现该接口。
interface GroovyControllerInterface {
@RequestMapping("/status_groovy")
@ResponseBody String getStatus()
}
@Controller
class GroovyController implements GroovyControllerInterface {
@RequestMapping("/status_groovy")
public @ResponseBody String getStatus() {
return "Hello World from groovy!";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4110 次 |
| 最近记录: |