JSP EL и путаница атрибутов - PullRequest
       16

JSP EL и путаница атрибутов

2 голосов
/ 19 августа 2010

Я хотел бы попросить вас помочь в разъяснении некоторых вопросов.Но, прежде всего, сначала идет входящий код - это очень простой пример входа в систему, который я создал.

Контейнером является Tomcat 5.5.27.

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

LoginPage.jsp (точка входа - просмотр)

<%@ page language="java" contentType="text/html; charset=windows-1250" pageEncoding="windows-1250"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <link rel="stylesheet" type="text/css" href="mystyle.css" />
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>Login Page</title>
 </head>
 <body>
  <div id="page">
   <div id="content_container">
    <div id="content">
     <form action="LoginServlet">
     Username: <input type="text" name="username"><br>
     Password: <input type="text" name="password"><br>
     <input type="submit" value="Submit">
     </form>
    </div>
   </div>
  </div>
 </body>
</html>

LoginServlet.java (контроллер)

public class LoginServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

public LoginServlet() {
  super();
}

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  try {
   UserBean user = new UserBean();
   user.setUsername(request.getParameter("username"));
   user.setPassword(request.getParameter("password"));

   user = UserDAO.login(user);

   if(user.isValid()){
    HttpSession session = request.getSession();
    session.setAttribute("currentSessionUser", user);
    response.sendRedirect("userLogged.jsp");
   } else {
    response.sendRedirect("invalidLogin.jsp");
   }
  } catch (Exception e){
   e.printStackTrace();
  }
 }
}

UserDAO.java ("service"class)

//snipped imports and such

public class UserDAO {

    static Connection currConn = null;
    static ResultSet rs = null;

    public static UserBean login(UserBean userBean) {
        Statement stmt = null;

        String username = userBean.getUsername();
        String password = userBean.getPassword();

        String searchQuery = "SELECT * FROM pilots x WHERE x.email = '" + username + "' AND x.password = '" + password + "'";

        System.out.println("Your user name is " + username);
        System.out.println("Your password is " + password);
        System.out.println("Query: " + searchQuery);

        try {
            currConn = ConnectionManager.getConnection();
            stmt = currConn.createStatement();
            rs = stmt.executeQuery(searchQuery);
            boolean more = rs.next();

            if (!more) {
                System.out.println("Sorry, you are not a registered user! Please sign up first");
                userBean.setValid(false);
            } else {
                String firstName = rs.getString("FIRST_NAME");
                String lastName = rs.getString("LAST_NAME");

                System.out.println("Welcome " + firstName);

                userBean.setFirstName(firstName);
                userBean.setLastName(lastName);
                userBean.setValid(true);
            }
        } catch (Exception ex) {
            System.out.println("Log In failed: An Exception has occurred! " + ex);
            ex.printStackTrace();
        } finally {
            if(rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(currConn != null){
                try {
                    currConn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return userBean;
    }
}

UserBean.java (модель, классический POJO / bean-компонент, используемый в качестве DTO)

//...
public class UserBean {
 private String username;
 private String password;
 private String firstName;
 private String lastName;
 private boolean valid;

 public String getUsername() {
  return username;
 }

 public void setUsername(String username) {
  this.username = username;
 }

 public String getPassword() {
  return password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public boolean isValid() {
  return valid;
 }

 public void setValid(boolean valid) {
  this.valid = valid;
 }
}

userLogged.jsp (точка выхода - просмотр) - никогда не обращайте внимания наdiv elements-

<%@ page language="java" contentType="text/html; charset=windows-1250" pageEncoding="windows-1250"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <link rel="stylesheet" type="text/css" href="mystyle.css" />
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Successful login!</title>
</head>
<body>
 <div id="page">
  <div id="content_container">
   <div id="content">
   <jsp:useBean id="currentSessionUser" class="examplePackage.UserBean" scope="application">
    Welcome, <jsp:getProperty name="currentSessionUser" property="username"/> <br>
    ********<br>
    Test 0 -> ${param.name}<br>
    Test 1 -> ${paramValues.name[0]}<br>
    Test 2 -> ${paramValues[name[0]]}<br>
    Test 3 -> ${param["name"]}<br>
    Test 4 -> ${param.username}<br>
    Test 5 -> ${param["username"]}<br>
    Test 6 -> ${sessionScope.currentSessionUser.username}<br>  
    *******<br>
    Test 7 -> ${header.host}<br>
    Test 8 -> ${header["host"]}<br>
    Test 9 -> ${pageContext.request.method}<br>
   </jsp:useBean>
   </div>
  </div>
 </div> 
</body>
</html>

Вывод веб-страницы выглядит следующим образом (c / p прямо из FireFox):

Welcome, USER_X
********
Test 0 ->
Test 1 ->
Test 2 ->
Test 3 ->
Test 4 ->
Test 5 ->
Test 6 -> USER_X
*******
Test 7 -> localhost:8080
Test 8 -> localhost:8080
Test 9 -> GET

1) Мой первый вопрос касается области действия - какая область фактически применима??Если вы извлечете userLogged.jsp, строки 13 и 22 (L13 и L22), вы увидите мою дилемму - если я использую любую другую область, кроме «application» в L13, L14 возвращает нулевое значение.С другой стороны, если я использую applicationScope на L22, он возвращает ноль (как это чертовски хорошо следует, так как я устанавливаю атрибут SESSION, а не атрибут контекста!).Итак, вопрос - зачем мне вообще использовать область применения на L13 ??Я не ожидал ничего, кроме области видимости сеанса, как видно из моего контроллера.

2) Другой вопрос касается EL - почему я не могу получить параметры запроса в тестах 0-5?Другие вещи работают хорошо (как видно из вывода), но я не могу понять, как распечатать эти параметры запроса, как я и предполагал (посредством неявных объектов запроса EL).

3) Мне также любопытнопочему это не сработает, если я буду его использовать (L24 из userLogged.jsp, изменить атрибут на property="*")?

Welcome, <jsp:getProperty name="currentSessionUser" property="*"/>

Возвращает значение NULL, и я сопоставил свойства моего объекта домена (UserBean) в соответствии со спецификацией JavaBeans.Я ожидаю, что он вернет ВСЕ свойства userBean, которые соответствуют полю типа ввода из LoginPage.jsp и имеют правильный тип для использования функции (должен быть String или примитив).

Заранее большое спасибо

С уважением, EK

Ответы [ 2 ]

5 голосов
/ 19 августа 2010

Вам не нужно jsp:useBean или jsp:getProperty. Избавься от них. Вы уже используете сервлеты и уже поместили зарегистрированного пользователя в область сеанса с ключом currentSessionUser в этой строке:

session.setAttribute("currentSessionUser", user);

Все, что вам нужно сделать для отображения имени пользователя, это:

<p>Welcome, ${currentSessionUser.username}</p>

Чтобы предотвратить XSS, используйте JSTL c:out:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<p>Welcome, <c:out value="${currentSessionUser.username}" /></p>

Вы определенно не хотите помещать это в область применения. Он будет применяться к всем посетителям сайта.


Что касается вопроса о параметрах запроса: вы запускаете редирект , используя response.sendRedirect(). Это в основном даст указание веб-браузеру создать новый запрос по указанному URL. Вы не передали ему никаких параметров, поэтому он действительно не будет доступен в перенаправленном запросе. Все работает как положено. Если вы хотите, чтобы исходные параметры запроса были все еще доступны на странице результатов, то вам следует либо переслать запрос, используя RequestDispatcher#forward()

request.getRequestDispatcher("page.jsp").forward(request.response);

или передать параметры по перенаправлению

response.sendRedirect("page.jsp?param1=" + URLEncoder.encode(param1, "UTF-8"));

Кстати, в вашем коде DAO есть основная проблема: она не является поточно-ориентированной. Соединение и набор результатов объявлены static. Это также подвержено утечкам ресурсов, закрытие не было проведено в finally.


Смотри также:


Обновление согласно комментариям:

Когда вы ссылаетесь на объект в контексте EL с помощью ${key}, он будет скрытно использовать JspContext#findAttribute(), чтобы найти соответствующее значение в областях соответственно страницы, запроса, сеанса и приложения и вернуть первое ненулевое значение.

Что касается jsp:useBean, вы в основном определяете новый компонент в области приложения вместо ссылки на существующий компонент в области сеанса. Если вы явно ссылаетесь на него в области приложения как ${applicationScope.currentSessionUser}, вы увидите, что он не возвращает то же самое, что вы установили в области сеанса в сервлете. Вам нужно заменить scope="application" на scope="session".

Что касается property="*", то это работает только тогда, когда вы перенаправляют запрос, как и прежде. Они будут установлены из параметров запроса.

И нет, finally, конечно, не является анти-паттерном. Однако это одно из самых недооцененных / недооцененных ключевых слов среди начинающих. Блок finally не делает его потокобезопасным. Это предотвращает утечку ресурсов. Удаление static и объявление ресурсов в локальном блоке метода сделает его потокобезопасным. Что касается шаблона DAO, вы можете найти эту статью полезной.

0 голосов
/ 19 августа 2010

Если вы используете jsp: useBean с атрибутом class, новый компонент будет создан и помещен в запрошенную область.Чтобы повторно использовать bean-компонент, он уже доступен в некоторой области видимости, вам нужно будет использовать атрибут type и установить для области видимости «сеанс», например.Отношения между различными атрибутами описаны в http://java.sun.com/products/jsp/tags/11/syntaxref11.fm14.html.

...