我应该在Struts2视图层中检索数据库记录吗?

cod*_*e4j 3 java model-view-controller jsp struts2 struts-action

我有一个编辑页面,我想从数据库中检索主题级别,并显示为用户编辑课程的选项.

提交表单时,它将发出新请求,courseBean将使用XML验证捕获用户输入.当XML验证失败时,它将使用courseBean转发,后者刚刚捕获了edit.jsp的用户输入.

在此输入图像描述

所以每次我去edit.jsp,我都会检索数据库记录.我应该这样做吗?

此外,我尝试检索主题litlevel lit并将它们作为请求属性存储在动作类中,该动作类在第一次显示edit.jsp.但是,当新请求来自用户输入时,从数据库检索的主题列表级别列表将不再可用.

代码(edit.jsp):

<%
    Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = session2.beginTransaction();
    Query q = session2.createQuery("from Subject");
    List subjectList = q.list();
    List levelList = session2.createQuery("from Level").list();
%>

<div class="control-group">
    <label class="control-label" for="inputPassword">Subject</label>
    <div class="controls">
        <select name="subject_id">
            <%
                for (Object subjectObject : subjectList) {
                    Subject subject = (Subject) subjectObject;
            %>
            <option value="<%=subject.getId()%>"><%=subject.getName()%></option>
            <%  } //end for %>
        </select>
    </div>
</div>

<div class="control-group">
    <label class="control-label" for="inputPassword">Level</label>
    <div class="controls">
        <select name="level_id">
            <%
                for (Object levelObject : levelList) {
                    Level level = (Level) levelObject;
            %>
            <option value="<%=level.getId()%>"><%=level.getName()%></option>
            <%  } //end for %>
        </select>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

And*_*ios 7

使用Struts2,您将不再需要使用Scriptlets(<% stuff %>).它们很旧,很糟糕,它们是在视图页面中注入的业务逻辑,不使用它们.你也不需要JSTL,只需使用Struts2标签即可获得任何结果.

为了更好地解耦和分离代码和概念,您应该:

  1. DAO Layer:它只是简单的查询;
  2. BUSINESS Layer:它通过Service(s)公开DAO层结果,聚合多个DAO调用并在需要时执行多个业务操作;
  3. PRESENTATION Layer:Struts2中的Actions作为模型; 在这里,您从业务层调用服务,以检索JSP所需的对象;
  4. JSP (VIEW Layer):在JSP包含普通的HTML,并访问通过行动的访问者(吸气剂)所需的数据,并最终从所述值栈(任何其他必要的元件#session,#request等等).

    在你的例子中,所有这一切

<% 
   Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
   Transaction tx = session2.beginTransaction();
   Query q = session2.createQuery("from Subject");
   List subjectList = q.list();
   List levelList = session2.createQuery("from Level").list(); 
%>
Run Code Online (Sandbox Code Playgroud)

应该在DAO/Business Layers中,由两个函数表示,如getSubjectList();getLevelList();.然后在你的行动中你应该有类似的东西:

public class YourAction {

    private List<Object> levelList; // private
    private List<Object> subjectList; // private

    public String execute() throws Exception {      
        // Call the service, load data
        levelList = getMyService().getLevelList();
        subjectList = getMyService().getSubjectList();

        // Forwarding to the JSP
        return SUCCESS;
    }

    public List<Object> getLevelList() {
        return levelList;
    }
    public List<Object> getSubjectList() {
        return subjectList;
    }

}
Run Code Online (Sandbox Code Playgroud)

在您的JSP中,而不是:

<select name="subject_id">
<%
  for (Object subjectObject : subjectList) {
      subject subject = (Subject) subjectObject;
%>
      <option value="<%=subject.getId()%>"><%=subject.getName()%></option>
<%
  } //end for
%>
</select>
Run Code Online (Sandbox Code Playgroud)

你访问列表(丑陋的混合HTML/Struts2方式):

<select name="subject_id">
    <s:iterator value="subjectList">
        <option value="<s:property value="id"/>">
            <s:property value="name"/>
        </option>   
    </s:iterator>
</select>
Run Code Online (Sandbox Code Playgroud)

或者,在选择的情况下,使用正确的Struts2 UI选择标记:

<s:select name = "subject_id" 
          list = "subjectList" 
       listKey = "id" 
     listValue = "name" />
Run Code Online (Sandbox Code Playgroud)

如果在开始时分离所有层太困难,请在Actions中展平前三个级别,只是为了理解如何分离Java(Action)和Struts2 UI Tags(JSP).理解后,您可以将DAO逻辑移动到业务层,最好是EJB.实现这一目标后,再次以更细粒度分割......

行动将是这样的:

public class YourAction {

    private List<Object> levelList; // private
    private List<Object> subjectList; // private

    public String execute() throws Exception {      
            Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
            Transaction tx = session2.beginTransaction();
            Query q = session2.createQuery("from Subject");
            subjectList = q.list();
            levelList = session2.createQuery("from Level").list();

        // Forwarding to the JSP
            return SUCCESS;
    }

    public List<Object> getLevelList() {
        return levelList;
    }
    public List<Object> getSubjectList() {
        return subjectList;
    }    
}
Run Code Online (Sandbox Code Playgroud)

关于你多次加载列表的问题,如果列表是固定的(例如每月更改一次),或者每次加载,都可以使用缓存(如果使用计时器则更好),这样就没有问题了那.请注意,如果验证失败,ValidationInterceptor会将请求转发到INP​​UT类型结果中映射的JSP,而不会到达execute()方法,因此您应该从Action实现Preparable接口并将加载内容放入prepare()方法中,每次都执行通过PrepareInterceptor

public class YourAction implements Preparable {

    private List<Object> levelList; // private
    private List<Object> subjectList; // private

    public void prepare() throws Exception {
        // Call the service, load data, 
        // every time even if validation fails
        levelList = getMyService().getLevelList();
        subjectList = getMyService().getSubjectList();
    }

    public String execute() throws Exception {      

        // Forwarding to the JSP
        return SUCCESS;
    }

    public List<Object> getLevelList() {
        return levelList;
    }
    public List<Object> getSubjectList() {
        return subjectList;
    }
}
Run Code Online (Sandbox Code Playgroud)

继续步骤,框架简单而强大,Web有大量示例,StackOverflow提供了一些很好的支持......