Я работаю над веб-приложением Java EE (в котором я довольно новичок) (JSF, JPA, EJB) и нахожусь в процессе включения PrettyFaces для читаемых/закладок URL-адресов. Я использую фильтр по двум причинам.
- чтобы убедиться, что пользователь вошел в систему.
- чтобы обернуть вызов filterChain.doFilter(...) в транзакцию, чтобы ленивая загрузка JPA работала при создании представлений (например, я могу просто установить объект отдела в компоненте поддержки и использовать #{backingBean.department.employees} чтобы получить связанный список сотрудников в файле .xhmtl).
Перед включением PrettyFaces я использовал шаблон URL-адреса (в web.xml) *.xhmtl (хотя фильтр на самом деле не нужно запускать для страницы входа) для фильтра. С PrettyFaces попытка указать шаблон URL-адреса для фильтров кажется небольшой проблемой, в основном из-за отсутствия гибкости правил шаблона URL-адреса (отсутствие поддержки регулярных выражений). Есть ли другой способ выполнить то, что мне нужно, без использования фильтров (и без дублирования кода)?
Кроме того, я знаю, что могу добавить статическую часть в начало URL-адреса (например, /dept/#{deptName}/..., а затем использовать фильтр с шаблоном URL-адреса /dept/*, но я надеялся просто начать с чего-то вроде /#{deptName}/... (и с помощью шаблона URL-адреса /* запускает фильтр для всего, включая изображения, javascript, css и т. д.)
По сути, в фильтр вводится транзакция...
@Resource UserTransaction tx;
И делает что-то вроде этого.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
HttpSession session = httpReq.getSession();
User currentUser = (User)session.getAttribute("userInSession");
if (currentUser == null) {
httpRes.sendRedirect("...") //redirect to LoginServlet
} else {
try {
tx.begin();
chain.doFilter(httpReq, httpRes);
}
catch (Exception e) { }
finally {
try {
tx.commit();
}
catch (Exception e) { }
}
}
У меня есть управляемый bean-компонент, подобный этому...
@ManagedBean
@RequestScoped
@URLMapping(
id="uutSerialNumber",
pattern="/#{uutSerialNumberController.programId}/uut/#{uutSerialNumberController.uutId}",
viewId="/uutSerialNumber.xhtml"
)
public class UutSerialNumberController {
@EJB private ProgramServiceBean programServiceBean;
@EJB private UutServiceBean uutServiceBean;
private Integer programId;
private Integer uutId;
private Program program;
private Uut uut;
@URLAction
public String loadData() {
program = programServiceBean.findByProgramId(programId);
uut = uutServiceBean.findUutByUutId(uutId);
return null;
}
//other stuff, setters/getters
}
В представлении uutSerialNumber.xhmtl я делаю что-то вроде этого (для чего требуется отложенная загрузка, если только я не хочу заниматься предварительной выборкой коллекций вручную в моем uutServiceBean.findUutByUutId())...
<ul>
<c:forEach var="serialNumber item="#{uut.serialNumbers}>
<li>#{serialNumber.description}</li>
</c:forEach>
</ul>