struts2形式的抽象类

struts2形式的抽象类,struts2,Struts2,我想要一个表单,它可以在类型层次结构中创建几个子类中的一个。假设它是AbstractPerson,子类为Employee和Visitor 我可以用一个Action/REST控制器Bean来实现吗 通常我使用智能ids表单,因此它直接将值分配给动作的设置器。 所以如果我有一个像 AbstractPerson member; 我会尝试使用一个名为“member.name”的输入字段的表单 然而,struts必须首先创建AbstractPerson的实例,因为它是抽象的!如果我能给struts2一个

我想要一个表单,它可以在类型层次结构中创建几个子类中的一个。假设它是AbstractPerson,子类为Employee和Visitor

我可以用一个Action/REST控制器Bean来实现吗

通常我使用智能ids表单,因此它直接将值分配给动作的设置器。 所以如果我有一个像

AbstractPerson member;
我会尝试使用一个名为“member.name”的输入字段的表单

然而,struts必须首先创建AbstractPerson的实例,因为它是抽象的!如果我能给struts2一个提示,让它实际创建一个Empolyee或Visitor对象(取决于表单内容),那就太酷了。这可能吗


干杯

这类似于我最近通过一小组crud操作访问实体类所做的事情。也就是说,一些crud操作允许您对某个包中的所有实体类进行操作。您应该能够将此策略应用于您的员工和访客类

简而言之,它是如何工作的:

1) 您需要在名称空间或操作名称中指定应创建的类的名称

2) 您可以使用struts2s Preparable接口创建模型。(以反射方式创建从步骤1确定的类

3) 使用模型驱动接口,该接口返回步骤2中定义的对象。这样,对象就位于堆栈的顶部,您可以简单地说“name”,并知道它是在步骤1中确定的类的name属性。你可以避免这一步,但它没有那么漂亮

现在,这样做有一个小问题,您会发现要执行上述三个步骤,您需要一个自定义堆栈,“staticParams prepare params”堆栈

首先是一个示例,然后是该堆栈的定义,如果您有任何问题,请告诉我:

package com.quaternion.demo.action.crud;

import com.quaternion.demo.orm.ActionValidateable;
import com.quaternion.demo.service.CrudService;
import com.quaternion.demo.util.ActionUtils;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;

// Adds a new record to the database
@ParentPackage("staticParams-prepare-parms")
@Namespace("/crud/{entityName}")
@Result(type = "kjson") //TODO: could rid of this line by setting the result as the default for the package
public class AddAction extends ActionSupport implements Preparable, ModelDriven {

    private static final Logger log = Logger.getLogger(AddAction.class.getName());
    @Autowired
    private CrudService crudService;
    private String entityName; 
    private Object entityModel; 
    private Map jsonModel = new HashMap(); //for output, return the newly created object
    private Class clazz;

    @Override
    public String execute() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        log.log(Level.INFO, "In execute entityName is set with {0}", entityName);
        //If an id is passed in it will merge the object with that id, null will be used for unset attributes
        String status = SUCCESS;
        boolean error = false;
        Object entity = null;
        try { 
            entity = crudService.create(clazz, entityModel);
        } catch (Exception e) {
            error = true;
            status = ERROR;
            jsonModel.put("message", e.getMessage());
        }
        if (error == false) {
            jsonModel.put("entity", entity);
        }
        jsonModel.put("status", status);
        return SUCCESS;
    }

    public Object getEntityModel() {
        return entityModel;
    }

    public void setEntityModel(Object entityModel) {
        this.entityModel = entityModel;
    }

    public Object getJsonModel() {
        return jsonModel;
    }

    @Override
    public Object getModel() {
        return this.entityModel;
    }

    @Override
    public void prepare() throws Exception {
        log.log(Level.INFO, "In prepare entityName is set with {0}", entityName);
        clazz = ActionUtils.initClazz(entityName);
        entityModel = clazz.newInstance();
    }

    public String getEntityName() {
        return entityName;
    }

    public void setEntityName(String entityName) {
        this.entityName = entityName;
    }

    //TODO: validation would be a good idea can't implement in this class need to delegate
    //if entity implements a validate method, this validate should
    //call that validate
    @Override
    public void validate(){
        if (entityModel instanceof ActionValidateable){
            ((ActionValidateable)entityModel).validate(this);
        }
    }
}
以下是堆栈的定义:

<package name="staticParams-prepare-parms" extends="struts-default">
    <result-types>
        <result-type name="kjson" default="true" class="com.quaternion.demo.result.Kjson"/>
    </result-types>
    <interceptors>
        <interceptor-stack name="staticParamsPrepareParamsStack">
            <interceptor-ref name="exception"/>
            <interceptor-ref name="alias"/>
            <interceptor-ref name="i18n"/>
            <interceptor-ref name="checkbox"/>
            <interceptor-ref name="multiselect"/>
            <interceptor-ref name="staticParams"/>
            <interceptor-ref name="actionMappingParams"/>
            <interceptor-ref name="servletConfig"/>
            <interceptor-ref name="prepare"/>
            <interceptor-ref name="chain"/>
            <interceptor-ref name="modelDriven"/>
            <interceptor-ref name="fileUpload"/>
            <interceptor-ref name="staticParams"/>
            <interceptor-ref name="actionMappingParams"/>
            <interceptor-ref name="params">
                <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
            </interceptor-ref>
            <interceptor-ref name="conversionError"/>
            <interceptor-ref name="validation">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>
            <interceptor-ref name="workflow">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>
        </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="staticParamsPrepareParamsStack"/>
</package> 

dojo\..*、^struts\..*、^session\..*、^request\..*、^application\..*、^servlet(请求|响应)\..*、参数*
输入、返回、取消、浏览
输入、返回、取消、浏览

您可能想知道kjson的结果类型是什么。我觉得struts2 json插件在其他几个动作上对我提出了挑战。我创建了一个通用的分页和读取操作,“flexjson”在默认情况下不会序列化集合,这可以防止延迟加载问题(在没有加载集合的情况下,这些简单服务总是如此),因此kjson只是一个使用flexjson返回json的结果类型

查看文档。+1可以通过
excludeProperties
防止延迟加载。使用自定义堆栈的好主意@RomanC但是当实体类在运行时通过名称空间参数确定时,我应该排除哪些属性呢?@Quaternion在这种情况下最好在属性上添加JSON注释。什么属性?模型是在运行时确定的!