Всем привет) Пожалуйста помогите решить задачу.
Условия:
Есть приложение написанное на JavaEE JSF. В приложении есть пользователи, у пользователей есть профиль, соответственно регистрация и идентификация. Приложение в стиле SPA соответственно есть всего две страницы на которых разворачиваются события. Первая эта страница регистрации/логина - my_site.com/login.xhtml, вторая это основная страница приложения - my_site.com/main_page.xhtml.
Задача:
Страница логина стартовая, поэтому также доступна по адресу my_site.com/, а вот страница my_site.com/main_page.xhtml, согласно ТЗ должна быть доступна по адресу - my_site.com/user_name, причем user_name соответственно для каждого юзера свой. Как это реализовать ума не приложу(
Есть замечательные библиотеки prettyfaces и rewrite которые призваны решать подобные вопросы, но к сожалению они только умеют на старте приложения формировать URL из переменной, например так -
<url-mapping id="userName">
<pattern value="/#{ user.getName() }/"/>
<view-id value="/main_page.xhtml" />
</url-mapping>
Результат мог бы быть положительным и на самом деле страница main_page.xhtml будет доступна по имени нашего пользователя при условии что мы знаем имя пользователя на старте приложения. Но его имя мы получаем из базы, только после того как он залогинился. Видимо урлы определяются во время деплоя приложения на сервер, потому что изменяя значение переменной userName(из примера с xml конфигурацией) нам НЕ становится доступна страница main_page.xhtml по новому имени.
Теперь снова вкратце -
Приложение развернуто и в работе, приходит пользователь на страницу логина, логинится. Мы подтягиваем данные о нем из базы и должны переадресовать его на основную страницу приложения. При этом в адресной строке у него должен быть виден URL состоящий из данных(его имени) которые мы только что получили из базы. Как это реализовать?
Можно воспользоваться ResourceHandler
-ом. Не помню с какой версии в JSF появились ResourceHandler-ы, но в последней-то точно есть:)
Сначала составим простенький ResourceHandler
:
public class UserPageResourceHandler extends ResourceHandlerWrapper {
private final ResourceHandler wrapped;
public UserPageResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
@Override
public ViewResource createViewResource(FacesContext context, String resourceName) {
String remoteUser = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
if (remoteUser == null) {
// если никто не подключился, то ничего особого не предприминать
return super.createViewResource(context, resourceName);
}
// Вычислить название страницы ползователя: /user_name.xhtml
String userPage = "/" + remoteUser + ".xhtml";
if (resourceName.equals(userPage)) {
// тут и подменим /Василий_Пупкин.xhtml на /main_page.xhtml
// т.е. запрос /Василий_Пупкин.xhtml обрабатывается как /main_page.xhtml
return super.createViewResource(context, "/main_page.xhtml");
} else {
// во всех остальных случаях что запросят, то и выдать
return super.createViewResource(context, resourceName);
}
}
}
Потом пропишем его в faces-config.xml
:
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<resource-handler>my.application.UserPageResourceHandler</resource-handler>
</application>
</faces-config>
Если не ошибаюсь, /main_page.xhtml
можно переместить в /WEB-INF
. Чтобы не открывалась прямым запросом в браузере. Тогда надо изменить и код на return super.createViewResource(context, "/WEB-INF/main_page.xhtml");
Вкратце по второму вопросу.
Есть несколько способов.
а) При программной реализации входа через форму кнопка "Войти" может иметь примерно такой action-метод:
public String login() {
...
// Код ниже должен выполняться при успешной аутентификации
String remoteUser = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
String userPage = "/" + remoteUser + ".xhtml";
return userPage + "?faces-redirect=true";
}
б) При стандартном способе понадобится ещё одна страница. Пусть это будет index.xhtml
. Его и надо указать в качестве wellcome-страницы, как это обычно делается.
Создать страницу index.xhtml
с viewAction
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:metadata>
<f:viewAction action="#{indexPage.init}"/>
</f:metadata>
...
И сама viewAction такая:
@Named
@RequestScoped
public class IndexPage {
public String init() {
String remoteUser = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();
String userPage = "/" + remoteUser + ".xhtml";
return userPage + "?faces-redirect=true";
}
}
При успешном входе произойдёт два перенаправления вместо одного.
Сначала на index.xhtml и потом уже на user_name.xhtml.
Но пользователь всё равно этого же не заметит.
Только бы заказчик не заметил или не был бы против в крайнем случае.
login.xhtml
-> index.xhtml
-> user_name.xhtml
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть бд, в ней 2 сущности и связь many to many, создаю DAO для crud операций, далее возникает вопрос, я хочу создать developer и добавить ему skillКак мне добавить...
Использую в своем приложении yandex map kitЕсли работает GPS, то на карте появляется значок "Я", который, я так полагаю, перемещается в зависимости...
Прописываю следующие проперти, но идея ругается драйвер - пишет, что не может его загрузить