Является ли это приемлемым случаем использования сценария JSP? - PullRequest
3 голосов
/ 15 февраля 2011

Я знаю, что использование JSP-скриптлетов обычно не одобряется, поэтому мне интересно, есть ли более элегантный способ достижения того, что я пытаюсь сделать. В основном я создаю представление, и в зависимости от определенных ситуаций в модели предметной области я отображаю другой 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. Использование скриплетов здесь - хорошая идея? Или есть другой подход, который я должен использовать?

Спасибо за любые предложения.

Ответы [ 3 ]

8 голосов
/ 15 февраля 2011

Я бы либо обновил 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).

5 голосов
/ 16 февраля 2011

Вы также можете создать собственный тег для этого. Вот простой пример:

создайте новый файл 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>

При таком подходе ваша модель и тег остаются слабо связанными, и его, скорее всего, можно использовать в других проектах.

2 голосов
/ 15 февраля 2011

Эмпирическое правило, которое я использую, заключается в том, что скриптлеты (или теги JSP или EL в этом отношении) должны использовать только ту модель, которая уже была настроена контроллером, а не запускать действия, которые взаимодействуют с внутренними системами и получаютвещи.

Разница часто неуловима, но, на мой взгляд, весьма значительнаВ вашем примере, скажем, что для определения, является ли пользователь администратором, требуется доступ к какой-либо базе данных или вызов веб-службы.Тогда вы будете нарушать MVC, вызывая это действие из представления.Вызываете ли вы действие из скриптлета, тега JSP или EL, не имеет значения.Вы сделали то, что лучше всего делает контроллер.

Так как бы я решил эту проблему?Я бы поставил логику определения, находится ли пользователь в роли администратора в контроллере.Затем я сделал бы эту информацию доступной в модели, чтобы представление могло использовать модель, чтобы определить, находится ли пользователь в роли администратора.Простой $ {user.isAdmin} тогда ответил бы на вопрос из представления.Эта точка зрения не будет «обвинена» в инициировании каких-либо действий.

Итак, я пурист, будучи сторонником такого рода судебных запретов?Я считаю, что во многих случаях, когда требуется оптимизация приложения, мне легче сканировать контроллеры и оптимизировать то, что они делают.Если представление также запускает работу бэкэнда, тогда будет очень трудно выполнить этот вид оптимизации, так как взаимодействие с бэкэндом тогда будет разбросано по нескольким контроллерам и представлениям.

Это также нарушает принцип единственной ответственности.Надеюсь, что это ответ на ваш вопрос.

Кстати, отличный вопрос.Я рад, что вы думаете об этом до такого уровня детализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...