【问题标题】:Should I retrieve database record in Struts2 view layer?我应该在 Struts2 视图层中检索数据库记录吗?
【发布时间】:2012-12-12 05:36:02
【问题描述】:

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

当表单提交时,它会发出一个新的请求,用户输入被 courseBean 捕获并进行 XML 验证。当 XML 验证失败时,它会将刚刚捕获用户输入的 courseBean 转发到 edit.jsp

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

此外,我尝试检索 subject 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>

【问题讨论】:

  • 您可以将它们放在您的会话中(request.getSession().setAttribute()),直到验证成功。
  • @dinukadev 我认为这是另一种方法;:)

标签: java jsp model-view-controller struts2 struts-action


【解决方案1】:

使用 Struts2,您将不再需要使用 Scriptlets (&lt;% stuff %&gt;)。它们很旧,很糟糕,它们是在视图页面中注入的业务逻辑,不要使用它们。你也不需要JSTL,只要使用Struts2标签就可以达到任何效果。

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

  1. DAO Layer:它只做简单的查询;
  2. BUSINESS Layer:它通过Service(s) 公开 DAO 层结果,聚合多个 DAO 调用并在需要时执行多个业务操作;
  3. PRESENTATION Layer:动作,在 Struts2 中充当模型;这里从业务层调用Service,获取JSP需要的对象;
  4. JSP (VIEW Layer):JSP 包含纯 HTML,并通过 Action 的访问器(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/业务层中,由 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 提供了一些很好的支持...

【讨论】:

  • 非常感谢,这是我见过的最佳答案。我使用了你的方法,jsp看起来比以前更好了。
【解决方案2】:

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

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

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

既然你已经添加了标签 struts 2,我会假设这是一个 struts 2 web 项目。考虑(强烈)使用内置的 struts ui 标签来完成在您的 scriplets 中完成的工作。

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

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

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

【讨论】:

  • @Thihata 你的意思是结构的选择标签吗?但是如何访问 jsp scriplet 中的变量定义
  • 您没有在脚本中定义它。 JSP 是视图。至少您应该使用 struts 2 动作类来完成这项工作。我强调这是最起码的做法,也不是很好的做法。
  • 你的意思是设置动作类的属性吗?并为该属性使用 struct2 选择标记?
  • 是的,尽管您应该将业务逻辑隔离在单独的类中。而数据访问在另一层。但是,如果应用程序相对较小且没有进化潜力,则可以做出妥协。
【解决方案3】:

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

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

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

【讨论】:

  • 我用标签库来分离Java代码和HTML怎么样?
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多