3

我有一个编辑页面,我想在其中从数据库中检索科目级别,并显示为用户编辑课程的选择选项。

当表单提交时,它会发出一个新的请求,用户输入被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>
4

3 回答 3

7

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

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

  1. DAO Layer:它只做简单的查询;
  2. BUSINESS Layer:它通过 (s) 暴露 DAO 层结果Service,聚合多个 DAO 调用并在需要时执行多个业务操作;
  3. PRESENTATION Layer:动作,在 Struts2 中充当模型;这里你从业务层调用Service,来检索JSP需要的对象;
  4. JSP (VIEW Layer):JSP 包含纯 HTML,并通过操作的访问器(Getter)访问所需的数据,并最终从值堆栈(、、等)中访问任何其他所需的#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(); 
%>

应该在 DAO/Business Layers 中,由 和 等两个函数getSubjectList();公开getLevelList();。然后在你的 Action 你应该有类似的东西:

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;
    }

}

在您的 JSP 中,而不是:

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

您可以像访问列表一样(丑陋的混合 HTML/Struts2 方式):

<select name="subject_id">
    <s:iterator value="subjectList">
        <option value="<s:property value="id"/>">
            <s:property value="name"/>
        </option>   
    </s:iterator>
</select>

或者,对于 Select,使用正确的 Struts2 UI Select Tag:

<s:select name = "subject_id" 
          list = "subjectList" 
       listKey = "id" 
     listValue = "name" />

如果一开始分离所有层太难,把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;
    }    
}

关于您关于多次加载列表的问题,如果列表是固定的(例如,它每月更改一个),您可以使用缓存(如果使用计时器更好),或者每次都加载它,这样做没有问题那。请注意,如果验证失败,ValidationInterceptor 会将请求转发到 INPUT 类型结果中映射的 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;
    }
}

循序渐进,框架简单而强大,网络上有大量示例,StackOverflow 提供了一些很好的支持...

于 2012-12-12T10:40:42.000 回答
2

你需要的是一个缓存。但是,如果数据库记录必然会频繁更改,则不可取。

但是,如果有问题的查询很小(我认为是),那么查询数据库应该不是一个大的性能问题。

另一方面,查看您的 JSP,我看到的只是 JSP 脚本已被弃用和滥用。

由于您添加了标签 struts 2,我将假设这是一个 struts 2 Web 项目。考虑(强烈)使用内置的 struts ui 标签来完成在您的 scriplets 中完成的工作。

你的方法只能被描述为当你有一个核反应堆可供你使用时,使用一堆发电机为一个城市供电。

我建议你从这里开始:http ://struts.apache.org/2.x/docs/home.html

这将使您对框架及其全部功能有一个正确的认识。

于 2012-12-12T05:44:06.760 回答
1

一个建议是,如果你想坚持 MVC 架构,那么永远不要在视图中看到业务逻辑。根据 MVC 架构,使用 View 的 UI 工程师根本不需要了解业务逻辑。

在您的 JSP 页面中混合 HTML 和 Java 代码会使视图复杂化,并会导致维护代码出现问题。

利用教程了解如何在 Struts 2 中实现 CRUD 操作。

于 2012-12-12T05:45:39.790 回答