【问题标题】:Is this an acceptable case to use a JSP scriptlet?这是使用 JSP scriptlet 的可接受情况吗?
【发布时间】:2011-06-27 07:53:20
【问题描述】:

我知道使用 JSP scriptlets 通常是不受欢迎的,这就是为什么我想知道是否有更优雅的方式来实现我想要做的事情。我几乎是在创建一个视图,并且根据域模型中的某些情况,我正在渲染不同的 HTML。

例如,考虑用户可能担任某个角色的场景。在 User 模型类上定义了这样的方法:

public boolean isInRole(String roleName) {
    // Logic here to determine if the user is in a role
}

然后我们有一个 JSP,如下所示:

<%
    User user = (User)request.getAttribute("user");
%>

// Some HTML here...

<% if (user.isInRole("admin") { %>
    // Generate some admin menu here
<% } %>

据我所知,这不能使用 JSTL/EL 来完成。在这里使用小脚本听起来是个好主意吗?还是我应该采取其他方法?

感谢您的任何建议。

【问题讨论】:

    标签: java model-view-controller jsp servlets jakarta-ee


    【解决方案1】:

    我要么升级到 Servlet 3.0 / JSP 2.2,在 EL 中允许使用参数调用方法

    <c:if test="${user.isInRole('admin')}">
    

    或创建自定义 EL 函数

    <c:if test="${util:isUserInRole(user, 'admin')}">
    

    根据您的问题历史,您似乎已经在使用 JEE6。所以第一种方法应该适合你(如果你的 web.xml 被声明为符合 Servlet 3.0 规范)。

    【讨论】:

      【解决方案2】:

      我使用的经验法则是 scriptlet(或 JSP 标签或 EL)必须只使用控制器已经设置的模型,而不是触发与后端系统交互并获取东西。

      这种差异通常很微妙,但在我看来却非常重要。在您的示例中,假设确定用户是否具有管理员角色需要您访问某个数据库或进行 Web 服务调用。然后,您将通过从视图触发该操作来违反 MVC。无论您是从 scriptlet 还是从 JSP 标记或 EL 调用操作都无关紧要。你已经做了最好由控制器完成的事情。

      那么我该如何解决这个问题呢?我会将确定用户是否具有管理员角色的逻辑放入控制器中。然后我会在模型中提供这些信息,以便视图可以使用模型来确定用户是否处于管理员角色。 然后,一个简单的 ${user.isAdmin} 将从视图中回答问题。该视图不会被“指责”触发任何操作。

      那么,我是不是因为坚持这种禁令而成为纯粹主义者?我发现在许多需要优化应用程序的情况下,我更容易扫描控制器并优化它们正在做的事情。如果视图也触发了后端工作,那么进行这种优化将非常困难,因为后端交互会分散在多个控制器和视图中。

      这也违反了单一职责原则。希望这能回答你的问题。

      顺便说一句,很好的问题。我很高兴你正在考虑这个细节。

      【讨论】:

        【解决方案3】:

        您也可以创建自定义标签来完成此操作。这是一个简单的例子:

        创建一个新的 tld 文件: WEB-INF/user.tld

        <?xml version="1.0" encoding="ISO-8859-1" ?>
        <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag 
        Library 1.2//EN"
        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
        <taglib>
          <tlib-version>1.0</tlib-version>
          <jsp-version>1.2</jsp-version>
          <short-name></short-name>
            <tag>
               <name>user</name>
               <tag-class>tags.UserRoleTag</tag-class>
               <body-content>JSP</body-content>
               <attribute>
                  <name>roles</name>
                  <required>true</required>
                  <rtexprvalue>true</rtexprvalue>
               </attribute>
            </tag>
        </taglib>
        

        创建自定义标签类: 标签/UserRoleTag.java

        package tags;
        
        import javax.servlet.jsp.JspException;
        import javax.servlet.jsp.tagext.TagSupport;
        
        @SuppressWarnings("serial")
        public class UserRoleTag extends TagSupport {
          private String roles;
        
          public int doStartTag() throws JspException {
            String userRole = (String)pageContext.getAttribute("currentUserRole");
        
            return roles.contains(userRole) ? EVAL_BODY_AGAIN : SKIP_BODY;
          }
        
          public String getRoles() {
            return roles;
          }
        
          public void setRoles(String roles) {
            this.roles = roles;
          }
        }
        

        创建你的 jsp:warfolder/home.jsp

        <%@ taglib uri="/WEB-INF/user.tld" prefix="u" %>
        
        <% pageContext.setAttribute("currentUserRole", "admin"); // this value would come from the controller... %>
        
        <u:user roles="admin registered">
            welcome admin!
        </u:user>
        
        <u:user roles="guest">
            welcome guest!
        </u:user>
        

        采用这种方法可以使您的模型和标签保持松散耦合,并且很可能可以在其他项目中重复使用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-04
          • 2012-09-08
          • 2018-05-30
          • 2011-04-08
          • 2022-06-14
          • 1970-01-01
          • 1970-01-01
          • 2015-07-14
          相关资源
          最近更新 更多