gpt4 book ai didi

spring - EL 自动完成/代码协助 Eclipse 和 Spring Beans

转载 作者:行者123 更新时间:2023-12-05 04:07:08 24 4
gpt4 key购买 nike

在 Eclipse 中,JSF/EL 的自动完成仅适用于遗留 @ManagedBean 或 CDI bean (@Named),至少在使用 JBoss 工具插件时是这样。
另请参阅:EL proposals / autocomplete / code assist in Facelets with EclipseEclipse autocomplete (content assist) with facelets (jsf) and xhtmlContent Assist for JSF2 + CDI (weld) beans + Eclipse Helios
=> 总结:
- 安装 JBoss 工具 JSF + CDI(http://download.jboss.org/jbosstools/oxygen/stable/updates/、JBoss Web 和 Java EE/JBoss 工具 JSF + 可视化页面编辑器 + 上下文和依赖注入(inject)工具);
- 在项目属性中:删除 Project Facets/“JavaServer Faces”,这样非常慢的 Eclipse JSF 自动完成器将被使用,激活 CDI/CDI 支持。

但是在使用 Spring 时不支持,即 @Controller@Component
通常,您现在应该使用完全支持所有 JSF 范围的 CDI bean,但您可能有自己的原因,或者现有项目可能会使用 Spring。
另请参阅:Moving JSF Managed Beans to Spring beanshttps://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely/

那么,如何为 Spring web bean 支持 JSF/EL 自动完成?

最佳答案

我深入研究了 JBoss 工具的实现,一个小改动让 Spring 用户很满意。
:-)
有一个基于 JSF 工具的解决方案(首先)和一个基于 CDI 工具的替代方案(之后)。

以下是基于jbosstools-4.5.2.Final使用插件文件org.jboss.tools.jsf_3.8.200.v20170908-0911.jar
但其他版本的更改应该相同或非常相似(相关源文件的最后一次更改可追溯到 2011 年 12 月或 2012 年 9 月)。

org.jboss.tools.jsf.jsf2.bean.model.impl.AbstractMemberDefinition 必须在方法 getManagedBeanAnnotation() 中扩展isAnnotationPresent():

如果没有找到@ManagedBean,那么还要寻找@Controller(应该在Spring中使用,所以@Service等JSF 中不提供)。但这可能很容易调整,请参阅以下来源中的评论。此外,Spring 使用 value 注释属性而不是 name - 这是通过包装类解决的。

public boolean isAnnotationPresent(String annotationTypeName) {
//TW: added Spring annotations
boolean b = (getAnnotation(annotationTypeName) != null);
if (!b && JSF2Constants.MANAGED_BEAN_ANNOTATION_TYPE_NAME.equals(annotationTypeName)) {
b = (getAnnotation("org.springframework.stereotype.Controller") != null);
/* with support for all Spring annotations:
b = (getAnnotation("org.springframework.stereotype.Controller") != null
|| getAnnotation("org.springframework.stereotype.Service") != null
|| getAnnotation("org.springframework.stereotype.Repository") != null
|| getAnnotation("org.springframework.stereotype.Component") != null);
*/
}
return b;
}


public AnnotationDeclaration getManagedBeanAnnotation() {
AnnotationDeclaration ad = annotationsByType.get(JSF2Constants.MANAGED_BEAN_ANNOTATION_TYPE_NAME);
//TW: added Spring annotations
if (ad != null) return ad;
ad = annotationsByType.get("org.springframework.stereotype.Controller");
/* with support for all Spring annotations:
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Service");
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Repository");
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Component");
*/
if (ad != null) {
// create wrapper to map "value" (used by Spring) to "name" (which is used by @ManageBean)
ad = new AnnotationDeclaration() {
private AnnotationDeclaration wrapped;

AnnotationDeclaration init(AnnotationDeclaration wrappedAD) {
this.wrapped = wrappedAD;
return this;
}

@Override
public Object getMemberValue(String name) {
Object val = wrapped.getMemberValue(name);
if (val == null && "name".equals(name)) {
val = wrapped.getMemberValue(null);
}
return val;
}

@Override
public Object getMemberValue(String name, boolean resolve) {
Object result = null;
if (resolve) {
result = this.getMemberConstantValue(name);
}
if (result == null) {
result = this.getMemberValue(name);
}
return result;
}

@Override
public void setDeclaration(IJavaAnnotation annotation) {
wrapped.setDeclaration(annotation);
}

@Override
public IJavaAnnotation getDeclaration() {
return wrapped.getDeclaration();
}

@Override
public IResource getResource() {
return wrapped.getResource();
}

@Override
public IMemberValuePair[] getMemberValuePairs() {
return wrapped.getMemberValuePairs();
}

@Override
public Object getMemberConstantValue(String name) {
return wrapped.getMemberConstantValue(name);
}

@Override
public Object getMemberDefaultValue(String name) {
return wrapped.getMemberDefaultValue(name);
}

@Override
public IMember getParentMember() {
return wrapped.getParentMember();
}

@Override
public String getTypeName() {
return wrapped.getTypeName();
}

@Override
public IType getType() {
return wrapped.getType();
}

@Override
public int getLength() {
return wrapped.getLength();
}

@Override
public int getStartPosition() {
return wrapped.getStartPosition();
}

@Override
public IAnnotationType getAnnotation() {
return wrapped.getAnnotation();
}

@Override
public IAnnotation getJavaAnnotation() {
return wrapped.getJavaAnnotation();
}

@Override
public IMember getSourceMember() {
return wrapped.getSourceMember();
}

@Override
public IJavaElement getSourceElement() {
return wrapped.getSourceElement();
}
}.init(ad); // class
}
return ad;
}

我这里提供两个编译类(main+一个内部类)直接下载:
AbstractMemberDefinition.class + AbstractMemberDefinition$1.class
我保证通过上述更改进行值得信赖的编译(即没有任何恶意代码或类似代码,您可以通过反编译检查 CFRProcyon ,年龄 JADEclipse-ECD ) - 您可以直接使用它们或执行自己编译(顺便说一句:堆栈溢出是否提供文件附件?)

安装:

  • 退出 Eclipse。
  • 制作原始文件的备份副本
    eclipse_home\plugins\org.jboss.tools.jsf_3.8.200.v20170908-0911.jar
    (例如 *.jar_orig)。
  • 将提供的类复制到 org.jboss.tools.jsf_3.8.200.v20170908-0911.jar\org\jboss\tools\jsf\jsf2\bean\model\impl(例如通过 Total Commander 或其他支持 zip/jar 处理的工具;您甚至可以使用 JDKs jar 工具)。注意:A...$1.class 是一个新文件。
  • 再次启动 Eclipse 并享受吧!

转到 JSF 页面并在 #{ 之后键入 Ctrl+Space 以获取 bean 列表。成员自动完成也有效(在 #{beanName. 之后),甚至是递归的。
甚至在 bean 名称上按 Ctrl+click 或 F3 也行!
注意:第一个自动完成调用需要几秒钟来发现初始 bean。

顺便说一句:为此,不需要为项目激活 CDI 支持! (构建速度更快,因为没有 CDI 构建器处于事件状态。)


或者,您可以扩展JBoss 工具CDI 功能来发现Spring bean。它的工作原理相同,此外它们将使用 Ctrl+Alt+Z(工具栏按钮打开 CDI 命名 Bean)列出。
注意:如果非CDI Spring bean被发现为CDI bean,我没有检查是否有任何副作用!

为此,文件 org.jboss.tools.cdi.internal.core.impl.definition.AbstractMemberDefinition 必须在方法 getNamedAnnotation() 中扩展:

public AnnotationDeclaration getNamedAnnotation() {
AnnotationDeclaration ad = getAnnotation(CDIConstants.NAMED_QUALIFIER_TYPE_NAME);
//TW: added Spring annotations
if (ad != null) return ad;
ad = getAnnotation("org.springframework.stereotype.Controller");
/* add additional Spring annotations, if desired:
if (ad != null) return ad;
ad = getAnnotation("org.springframework.stereotype.Service");
if (ad != null) return ad;
ad = getAnnotation("org.springframework.stereotype.Repository");
if (ad != null) return ad;
ad = getAnnotation("org.springframework.stereotype.Component");
*/
return ad;
}

您必须将已编译的类(下载:CDI-AbstractMemberDefinition.class)复制到 plugins\org.jboss.tools.cdi.core_1.8.201.v20171221-1913.jar\org\jboss\tools\cdi\internal\核心\实现\定义

必须为项目提供 CDI 支持。


也许为 JBoss 工具项目工作的人可能会将其包含在官方插件中
最好是提供一个首选项字符串,允许添加任意注释 - 甚至可能是项目特定设置。这将是一个通用的解决方案,没有可能有政治​​接受问题的“官方 Spring 支持”。
参见 https://issues.jboss.org/browse/JBIDE-25748

关于spring - EL 自动完成/代码协助 Eclipse 和 Spring Beans,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48933757/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com