Организация передачи данных из сервлетов, которые осуществляют обработку запросов пользователя, станицам JSP, которые отображают пользователю результат – одна из типовых задач разработки web приложений на Java. Однако эта задача имеет и ряд тонкостей.
Рассмотрим её решение на примере передачи JSP странице четырёх переменных:
- Массив строк (в качестве примера он будет содержать);
- Объект произвольного класса;
- Целое число;
- Строка.
В качестве «произвольного класса» для примера используем простейший класс.
1 2 3 4 5 6 7 8 9 |
public class MyClass { @Override public String toString(){ return "This is MyClass object"; } public String getTestString(){ return "Test string"; } } |
Передача данных из сервлета
Передача данных странице JSP из сервлета осуществляется посредством атрибутов запроса. Поэтому перед отправкой данных нужной странице необходимо их подготовить, присвоив значения соответствующим атрибутам. Например:
1 2 3 4 5 |
String[] strArray = {"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"}; request.setAttribute("months", strArray); request.setAttribute("int_attr", 777); request.setAttribute("str", "Test"); request.setAttribute("my_class", new MyClass()); |
После этого можно передавать данные странице и заодно выводить её в браузер при помощи интерфейса RequestDispatcher.
1 |
this.getServletContext().getRequestDispatcher("/ServletView.jsp").forward(request, response); |
Где «/ServletView.jsp» – адрес страницы JSP, которая должна получить переданные данные
Ниже приведён пример сервлета передающего данные странице JSP.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@WebServlet(name = "TestJSPServlet", urlPatterns = {"/TestJSPServlet"}) public class TestJSPServlet extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String[] strArray = {"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"}; request.setAttribute("months", strArray); request.setAttribute("my_class", new MyClass()); request.setAttribute("int_attr", 777); request.setAttribute("str", "Test"); this.getServletContext().getRequestDispatcher("/ServletView.jsp").forward(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override public String getServletInfo() { return "Short description"; } } |
Получение и вывод данных на странице JSP
Получение и вывод данных полученных от сервлета ничем не отличается от аналогичных операций для любых других атрибутов запроса.
Однако нужно всегда учитывать, что атрибуты запроса возвращаются в виде Object. Поэтому, если предстоит получить данные какого-либо другого типа (за редким исключением) или необходим доступ к функционалу соответствующего класса или интерфейса, требуется приведение типов.
Это очень легко увидеть на примере объекта MyClass переданного из приведённого ранее сервлета.
Если необходимо использовать метод toString, он корректно отработает и без приведения типов. В результате при выполнении следующего кода, будет выведена надпись «This is MyClass object».
1 2 |
" + request.getAttribute("my_class").toString() + ""); }%> |
Но, если требуется обратиться к методу getTestString, которого нет в классе Object, отсутствие приведения типов вызовет ошибку. Ниже показан пример правильного обращения к функционалу произвольного класса или интерфейса.
1 2 |
" + ((MyClass) request.getAttribute("my_class")).getTestString() + ""); }%> |
Примитивные и строковый типы не нуждаются в приведении, но для работы с массивами, даже если они состоят из элементов этих типов, приведение обязательно.
1 2 3 |
" + item + ""); } }%> |
Ниже показан пример страницы, которая получает данные от ранее приведённого сервлета и отображает их в браузере.
1 |
1 |
Servlet View
1 |
1 2 3 4 5 6 7 8 |
<br>" + request.getAttribute("my_class").toString() + ""); }%> <br>" + ((MyClass) request.getAttribute("my_class")).getTestString() + ""); }%> <br>" + request.getAttribute("int_attr") + ""); }%> <br>" + request.getAttribute("str") + ""); }%> |
1 |
Месяцы года:
1 2 3 4 |
" + item + ""); } } %> |
Вид страницы в браузере.
Нюансы, связанные с адресами
Связка сервлет – JSP имеет ряд особенностей, связанных с доступом.
Сервлет всегда доступен по адресу (адресам), который указан в параметре «urlPatterns». Доступ к странице JSP возможен двумя способами:
- Через вызов сервлета;
- Путём прямого обращения по имени JSP файла.
В последнем случае данные сервлета не будут отображаться так при прямом обращении к JSP странице он не вызывается.
Разумеется, что подобное нежелательно.
Существуют два основных способа решения этой проблемы:
- Настройка маршрутизации средствами сервера приложения или фреймворка;
- Передача странице JSP параметра обозначающего правильность перехода на неё и его последующая проверка.
Рассмотрим подробнее второй способ.
Добавим в сервлете атрибут запроса, который будет служить признаком правильности перехода на страницу. Например:
1 |
request.setAttribute("true_page", this.getServletName()); |
На самой же странице перед отображением её содержимого будем выполнять его проверку:
1 |
Если результат проверки удовлетворительный, будет отображено содержимое страницы. В противном случае будет выполнено перенаправление на правильный адрес.
Для вышеописанной проблемы с прямым доступом, кажется очевидным решение – указать адрес страницы в параметре «urlPatterns». Однако, этого делать нельзя потому, что обращение в данном случае по этому адресу завершится ошибкой.
Указывать в параметре «urlPatterns» адреса схожие с адресом страницы или отличающиеся от него только регистром (например, адрес страницы – «ServletView.jsp», а адрес в «urlPatterns» – «servletview.jsp») также не рекомендуется.
Последнее не решает проблему, так как не устраняет прямого доступа. Более того подобный подход очень опасен (особенно в случае отличий только в регистре), потому что при опечатке в коде вероятно совпадение с адресом страницы (о чём говорилось выше).
Это плохая практика и применять её не стоит.
Добавить комментарий