| « JSTL: Шаблоны для разработки веб-приложений в java. Часть 2 | Hibernate: отображая иерархии классов » |
JSTL: Шаблоны для разработки веб-приложений в java. Часть 3
Теперь перейдем к рассмотрению методик работы с SQL-запросами в jstl. Скажу честно и прямо, этот подход ужасен (полагаю, вы все в курсе, что смешивать логику и визуализацию глупо). Хотя этими тегами я иногда пользуюсь для маленьких, секретненьких (никогда ни кому не показываемых) проектиков.Для работы всех показанных далее тегов необходимо подключить к jsp-файлу следующую библиотеку тегов:
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
CREATE TABLE `tm_user` (
`UserID` int(11) NOT NULL AUTO_INCREMENT,
`UserName` varchar(100) DEFAULT NULL,
`BirthDate` datetime DEFAULT NULL,
`Sex` enum('male','female') DEFAULT NULL,
`Comment` text,
PRIMARY KEY (`UserID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO `tm_user` (username, birthdate, sex, comment) VALUES
('Jim Tapkin', '2006.1.1', 'male', 'bla-bla-bla'),
('Ron Baskerville', '2002.7.5', 'male', 'be-be-be'),
('Lenka Slonova', '2009.4.1', 'female', 'wow-wow-wow')
<?xml version="1.0" encoding="UTF-8"?><Context path="/"><Resource name="jdbc/VeloDemoDS" auth="Container" type="javax.sql.DataSource"username="jim"password=""driverClassName="com.mysql.jdbc.Driver"url="jdbc:mysql://center/obmachine_t?autoReconnect=true&useUnicode=true&characterEncoding=UTF8"/></Context>
Теперь можно попробовать выполнить запрос, для этого используется два тега: либо query либо update. Полагаю, что вы догадались, когда нужно использовать первый из них, а когда – второй. Что касается текста запроса, то его можно указать (как сделал я) непосредственно как тело тега query, либо значением атрибута sql – без разницы.
<%InitialContext co = new InitialContext();pageContext.setAttribute("ds_jndi", co.lookup("java:comp/env/jdbc/VeloDemoDS"));%><body><sql:query var="users" dataSource="${ds_jndi}">select * from tm_user
</sql:query><c:forEach items="${users.rows}" var="row"><c:out value="${row.UserName}"/></c:forEach>
<sql:query var="users" dataSource="jdbc/VeloDemoDS">select * from tm_user
</sql:query>
<sql:setDataSource dataSource="jdbc/VeloDemoDS" var="velo_simple"/><sql:query var="users" dataSource="${velo_simple}">select * from tm_user
</sql:query>
rows – представляет собой список вида HashMap
rowsByIndex – список массивов. Т.е. каждый элемент списка – массив – представляет отдельную запись в таблице. Однако для доступа к полям нужно указать не имя поля, а его порядковый номер (отсчет начинается с 1).
columnNames – список имен полей.
Например, так я распечатаю все имена отобранных полей:
<c:forEach items="${users.columnNames}" var="col"><c:out value="${col}"/></c:forEach>
limitedByMaxRows – логическая переменная, признак того, что количество отобранных записей было ограничено, правда, я так и не понял чем ограничено и зачем … (ни явные команды в тексте запроса вида LIMIT “что-там-надо-ограничить”, ни дополнительные атрибуты для тега query не повлияли на эту переменную).
Последнее действия приведенного выше примера тривиально – нужно организовать цикл по списку rows, затем вывести с помощью c:out значения полей.
У тега query еще есть несколько атрибутов: scope – контекст, куда будет помещена переменная с результатом отбора данных; атрибуты maxRows и startRow служат для ограничения выборки начиная с некоторой записи и числом не более чем.
Запросы без переменных (параметров) слишком редки, чтобы разработчики jstl не предусмотрели несколько механизмов позволяющих вам использовать функциональность PreparedStatement-s. Для этого внутрь тега query кроме текста запроса необходимо поместить еще и элементы param. Каждый из них имеет атрибут value со значением, которое будет подставлено в текст запроса вместо вопросика (будьте внимательны с порядком следования параметров).
<sql:query var="users" dataSource="${ds_jndi}">select * from tm_user where UserID between ? and ?
<sql:param value="${param.minID}" /><sql:param value="${param.maxID}" /></sql:query>
<sql:query var="users" dataSource="${ds_jndi}">select * from tm_user where BirthDate = ?
<sql:dateParam value="${date}"/></sql:query>
<sql:update var="qtyInsterted" dataSource="${ds_jndi}">insert into `tm_user` (username, birthdate, sex, comment) values
('Jim Tapkin', '2006.1.1', 'male', 'bla-bla-bla'),('Ron Baskerville', '2002.7.5', 'male', 'be-be-be'),('Lenka Slonova', '2009.4.1', 'female', 'wow-wow-wow')</sql:update>count affected records = <c:out value="${qtyInsterted}" />
<sql:transaction dataSource="${ds_jndi}"><sql:update>delete from tm_user
</sql:update><sql:update>delee adfs adasd
</sql:update></sql:transaction>
Вторая команда внутри транзакции, очевидно, должна привести к ошибке – будет выброшено исключение. Визуально на экране браузера я вижу текст сообщения об ошибке, и выполнение дальнейшего кода jstl было прервано. Надо бы это поправить. Методы обработки исключений в jstl тривиальны. Если исключение произошло не внутри блока catch, то генерация страницы прерывается и с этим поделать ничего нельзя. В случае если потенциально опасные действия были внутри catch, то при генерации исключения объект, описывающий его, будет помещен внутрь переменной заданной с помощью атрибута var. Затем нужно с помощью if-а проверить чему равна эта переменная, и если она не равна null, то ошибка случилась.
<c:catch var="e_sql"><sql:transaction dataSource="${ds_jndi}"><sql:update>delete from tm_user
</sql:update><sql:update>delee adfs adasd
</sql:update></sql:transaction></c:catch><c:if test="${e_sql != null}">Произошла страшная ошибка: <c:out value="${e_sql}"/></c:if>
<sql:setDataSource driver="com.mysql.jdbc.Driver" user="jim" password=""url="jdbc:mysql://center/obmachine_t?autoReconnect=true&useUnicode=true&characterEncoding=UTF8"var="velo_local" scope="application"/>
Работа с форматирование, локализацией
В jstl входит набор тегов, специально предназначенный для создания локализованных приложений: представление дат, чисел в соответствии с определенными национальными настройками, также есть средства для загрузки текстовых ресурсов из Resource Boundle.
Начнем мы с того, что подключим библиотеку тегов fmt:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:requestEncoding value="utf-8" />
Единственным необходимым атрибутом является value – значение даты, которую необходимо форматировать. Если не указать значение атрибута var, то результат форматирования будет выведен на экран, а не в промежуточную переменную. Атрибут pattern задает строку форматирования.
<jsp:useBean id="beanNow" class="java.util.Date" /><fmt:formatDate value="${beanNow}" var="s_now" pattern="yyyy.MMM.dd hh:mm:ss" /><c:out value="${s_now}" />
<fmt:parseDate pattern="dd.MM.yyyy" value="12.04.2001" />
<fmt:timeZone value="Europe/Minsk"><fmt:formatDate value="${beanNow}" pattern="yyyy.MMM.dd hh:mm:ss" /></fmt:timeZone><fmt:timeZone value="Antarctica/Casey"><fmt:formatDate value="${beanNow}" pattern="yyyy.MMM.dd hh:mm:ss" /></fmt:timeZone>
<fmt:setLocale value="ja_JP"/><fmt:formatDate value="${beanNow}" pattern="yyyy.MMM.dd hh:mm:ss" />
Сначала из числа в строку:
<fmt:formatNumber pattern="#,##0.0#" value="234234.23423" />
<fmt:parseNumber value="234,234.23" pattern="#,##0.0#" />
<fmt:setBundle basename="testi.messages" var="loc" /><fmt:message bundle="${loc}" key="MSG_1" /><fmt:message bundle="${loc}" key="MSG_2" var="m_2"/><c:out value="${m_2}" />
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<c:set value="boy goes to school" var="boy" /><c:if test="${fn:contains(boy, 'goes')}"><h1>He goes to School. Realy.
</h1></c:if>
<c:if test="${fn:containsIgnoreCase(boy, 'GOES')}"><h1>He goes to School. Realy.
</h1></c:if>
<c:if test="${fn:startsWith(boy, 'boy')}"><h1>Starts from BOY
</h1></c:if><c:if test="${fn:endsWith(boy, 'school')}"><h1>Ends with SCHOOL
</h1></c:if>
<c:set value="boy goes � to school" var="boy" /><c:out value="${boy}" /><c:out value="${fn:escapeXml(boy)}" /><c:out value="${boy}" escapeXml="true" />
<c:set value="boy goes to school" var="boy" /><c:out value="${fn:indexOf(boy, 'to' )}" />
<c:set value="boy goes to school" var="boy" /><c:out value="${fn:substring(boy, fn:indexOf(boy, 'to' ), 100)}" />
<c:out value="${fn:substring(boy, fn:indexOf(boy, 'to' ), fn:indexOf(boy, 'to' )+2)}" />
<c:out value="${fn:substring(boy, fn:indexOf(boy, 'to' ), -1)}" />
<sql:query var="users" dataSource="jdbc/VeloDemoDS">select * from tm_user
</sql:query><c:set value="boy goes to school" var="boy" />
<c:out value="${fn:length(boy)}" />
<c:out value="${fn:length(users.rows)}" />
<c:set value="boy goes to school" var="boy" />After:<c:out value="${fn:substringAfter(boy, 'to')}" />Before:<c:out value="${fn:substringBefore(boy, 'to')}" />
<c:set value="boy goes to school" var="boy" />
<c:out value="${fn:toLowerCase(boy)}" />
<c:out value="${fn:toUpperCase(boy)}" />
<c:set value=" boy goes to school " var="boy" /><h1><c:out value="${fn:trim(boy)}"/></h1>
<c:set value="boy goes to school" var="boy" /><c:out value="${fn:replace(boy, 'school', 'bar')}"/>
<c:set value="1,2,3,4" var="str_digits" /><c:set value="${fn:split(str_digits, ',')}" var="arr_digits" /><c:set value="${fn:join(arr_digits, '!')}" var="str2_digits"/>
<c:out value="${fn:length(arr_digits)}" />
<c:out value="${str2_digits}" />
| « JSTL: Шаблоны для разработки веб-приложений в java. Часть 2 | Hibernate: отображая иерархии классов » |