Главным образом из-за того, что мне пришлось настроить его в xml. Если вы когда-либо делали проект JSF, вы знаете, что это то, что вы делаете позже. Или никогда. С последним вариантом, который я видел много. Переписать собирается изменить это. Программный, простой в использовании и настраиваемый. Именно то, что я искал.
Начиная
Нет ничего проще, чем начать работать с вещами одного из ребят из RedHat. Запустите NetBeans, создайте новое веб-приложение на основе Maven, добавьте JSF и Primefaces к миксу и запустите его на GlassFish.
Первый шаг для добавления магии переписывания в ваше приложение — это добавление зависимостей перезаписи в ваш проект.
|
1
2
3
4
5
|
<dependency> <groupId>org.ocpsoft.rewrite</groupId> <artifactId>rewrite-servlet</artifactId> <version>1.1.0.Final</version></dependency> |
Этого недостаточно, так как я собираюсь использовать его вместе с JSF, вам также необходима интеграция с jsf.
|
1
2
3
4
5
|
<dependency> <groupId>org.ocpsoft.rewrite</groupId> <artifactId>rewrite-integration-faces</artifactId> <version>1.1.0.Final</version> </dependency> |
Затем реализуйте свой собственный ConfigurationProvider. Это центральная часть, где происходит большая часть магии. Давайте пока назовем это TricksProvider, и мы также расширим абстрактный HttpConfigurationProvider. Простая первая версия выглядит так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class TricksProvider extends HttpConfigurationProvider{ @Override public int priority() { return 10; } @Override public Configuration getConfiguration(final ServletContext context) { return ConfigurationBuilder.begin() .addRule(Join.path("/").to("/welcomePrimefaces.xhtml")); }} |
Теперь вы должны зарегистрировать свой ConfigurationProvider. Вы делаете это, добавляя простой текстовый файл с именем org.ocpsoft.rewrite.config.ConfigurationProvider в папку вашего приложения / META-INF / services /. Добавьте к нему полное имя вашей реализации ConfigurationProvider, и все готово. Если вы запустите свое приложение.
Основы переписывания
При копировании вышеуказанного провайдера вы неявно добавили свое первое правило перезаписи. Запрашивая http: // host: 8080 / yourapp /, вы попадаете на страницу приветствия Primefaces, созданную NetBeans. Все правила основаны на одном и том же принципе. Каждое правило состоит из условия и операции. Что-то вроде «Если X случится, сделай Y». Переписать знает два разных вида правил. Некоторые предварительно сконфигурированные (Join), начиная с «addRule ()», и свободный интерфейс, начинающийся с defineRule (). Это немного сбивает с толку, потому что следующий основной выпуск устареет defineRule () и переименует его в addRule (). Так что большинство примеров, которые вы найдете (особенно тестовые примеры в последней транке), не работают с 1.1.0.Final.
Переписать знает о двух разных направлениях. Входящий и исходящий. Входящий, скорее всего, работает как любой известный вам механизм перезаписи (например, mod_rewrite). Запрос поступает и перенаправляется или перенаправляется на ресурсы, определенные в ваших правилах. Исходящее направление немного меньше. Он в основном имеет хук в методе encodeURL () HttpServletRequest и переписывает ссылки, которые есть на ваших страницах (если они вообще отображаются с помощью encodeURL). JSF делает это из коробки. Если вы планируете использовать его с JSP, вы должны сами его назвать.
Переадресация .html в .xhtml с некоторой магией
Давайте посмотрим на некоторые вещи, которые вы могли бы сделать с переписать. Сначала мы добавляем в TricksProvider следующее:
|
1
2
3
4
|
.defineRule().when(Direction.isInbound().and(Path.matches("{name}.html").where("name").matches("[a-zA-Z/]+"))).perform(Forward.to("{name}.xhtml")); |
Это правило, которое просматривает входящие запросы и проверяет все совпадения Patch {name} .html, которые подтверждают шаблон регулярного выражения [a-zA-Z /] +, и перенаправляет их в файлы {name} .xhtml.
Если это правило действует, все запросы к http: // host: 8080 / yourapp / something.html будут в конечном итоге перенаправлены в нечто .xhtml. Теперь ваши пользователи больше не будут знать, что вы используете причудливые JSF-материалы, и верят, что вы работаете с html 🙂 Если запрашивается URL, не соответствующий регулярному выражению, например что-то вроде http: // host: 8080 / yourapp /thing123.html это просто не пересылается, и если что-то12123.html отсутствует в вашем приложении, вы в конечном итоге получите ошибку 404.
Перезапись исходящих ссылок
В противном случае вы также можете добавить следующее правило:
|
1
2
3
4
|
.defineRule().when(Path.matches("test.xhtml").and(Direction.isOutbound())).perform(Substitute.with("test.html")) |
Вы представляете, что это делает, верно? Если у вас есть лицевая сторона, которая содержит что-то вроде этого:
|
1
|
<h:outputLink value="test.xhtml">Normal Test</h:outputLink> |
Ссылка, которая отображается для пользователя, будет переписана в test.html. Это самое основное действие для исходящих ссылок, которое вам когда-либо понадобится. Большая часть магии происходит с входящими ссылками. Неудивительно, если взглянуть на очень ограниченный охват хука encodeURL ().
OutputBuffer
Самая удивительная вещь в переписывании называется OutputBuffer. По крайней мере, до релиза, с которым мы сейчас работаем. Он будет переименован в 2.0, но сейчас давайте просто посмотрим, что вы можете сделать. OutputBuffer — ваш хук к ответу. Все, что вы хотели бы сделать с ответом до его фактического поступления в браузер вашего клиента, можно сделать здесь. Думаете о преобразовании разметки? Преобразование CSS? Или даже сжатие GZIP? Отлично, это именно то, что вы могли бы сделать. Давайте реализуем простой ZipOutputBuffer
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class ZipOutputBuffer implements OutputBuffer { private final static Logger LOGGER = Logger.getLogger(ZipOutputBuffer.class.getName()); @Override public InputStream execute(InputStream input) { String contents = Streams.toString(input); LOGGER.log(Level.FINER, "Content {0} Length {1}", new Object[]{contents, contents.getBytes().length}); byte[] compressed = compress(contents); LOGGER.log(Level.FINER, "Length: {0}", compressed.length); return new ByteArrayInputStream(compressed); } public static byte[] compress(String string) { ByteArrayOutputStream os = new ByteArrayOutputStream(string.length()); byte[] compressed = null; try { try (GZIPOutputStream gos = new GZIPOutputStream(os)) { gos.write(string.getBytes()); } compressed = os.toByteArray(); os.close(); } catch (IOException iox) { LOGGER.log(Level.SEVERE, "Compression Failed: ", iox); } return compressed; }} |
Как вы можете видеть, я возиться с некоторыми потоками и использую java.util.zip.GZIPOutputStream, чтобы уменьшить поток, полученный этим методом. Далее мы должны добавить соответствующее правило в TricksProvider:
|
1
2
3
4
5
6
|
.defineRule().when(Path.matches("/gziptest").and(Direction.isInbound())).perform(Forward.to("test.xhtml").and(Response.withOutputBufferedBy(new ZipOutputBuffer()).and(Response.addHeader("Content-Encoding", "gzip")).and(Response.addHeader("Content-Type", "text/html")))) |
Входящее правило (мы не хотим переписывать ссылки на страницах здесь … поэтому оно должно быть входящим), которое добавляет ZipOutputBuffer к Ответу. Также позаботьтесь о дополнительном заголовке ответа (оба), если вы не хотите, чтобы ваш браузер жаловался на содержимое, которое я перепутал 🙂 Вот и все. Запрос http: // host: 8080 / yourapp / gziptest теперь доставляет test.xhtml со сжатием GZIP. Это 2,6 КБ против 1,23 КБ! Менее половины размера! Не очень удобно работать с потоками и байтами []. И я не уверен, будет ли это работать с большими размерами страниц с точки зрения фрагментации памяти, но это простой выход, если у вас нет фильтра сжатия или вам нужно только сжимать отдельные части вашего приложения.
Повысить безопасность с помощью Rewrite
Но это еще не все, что вы могли бы сделать: вы также можете повысить безопасность с помощью перезаписи. У Линкольна есть отличный пост о защите вашего приложения с помощью перезаписи . Есть много возможных примеров того, как это использовать. Я придумал один вариант использования, в котором не хотел использовать функции файла приветствия и предпочитаю отправлять пользователей индивидуально. При этом я также проверял их пути и проверял, являются ли вводимые ими данные вредоносными или нет. Вы можете сделать это либо с условием .matches (), либо с пользовательским ограничением. Добавьте следующее в TricksProvider:
|
1
2
3
4
5
6
7
|
Constraint<String> selectedCharacters = new Constraint<String>() { @Override public boolean isSatisfiedBy(Rewrite event, EvaluationContext context, String value) { return value.matches("[a-zA-Z/]+"); } }; |
И определите следующее правило:
|
1
2
3
4
5
|
.defineRule().when(Direction.isInbound().and(Path.matches("{path}").where("path").matches("^(.+)/$").and(Path.captureIn("checkChar").where("checkChar").constrainedBy(selectedCharacters)))).perform(Redirect.permanent(context.getContextPath() + "{path}index.html")) |
Еще одна входящая модификация. Проверка пути, если он имеет шаблон папки, и запись его в переменную, которая проверяется на соответствие пользовательским ограничениям. Большой! Теперь у вас есть простой и удобный механизм пересылки. Все http: // host: 8080 / yourapp / folder / request теперь переписываются на http: // host: 8080 / yourapp / index.html. Если вы посмотрите на другие правила сверху, вы увидите, что .html перенаправляется в .xhtml … и все готово!
Нижняя линия
Мне очень нравится работать с переписать. Это проще, чем настраивать xml-файлы prettyfaces, и я действительно пользовался поддержкой Линкольна и Кристиана во время моих первых шагов с ним. Мне любопытно посмотреть, что выйдет с 2.0, и я надеюсь, что я получу еще один отладочный вывод для конфигурации правил, просто чтобы посмотреть, что происходит. По умолчанию ничего нет, и может быть очень сложно найти правильную комбинацию условий, чтобы иметь рабочее правило.
Ищете полные источники? Найди их на github . Рад прочитать о вашем опыте.
Где находится GlassFish Part?
О, да. Я упоминал об этом в заголовке, верно? Это должно быть больше похоже на дефолт. Я запускал все с последней версией GlassFish 3.1.2.2, так что вы можете быть уверены, что это работает. И NetBeans сейчас находится на уровне 7,2, и вы должны попробовать, если у вас его нет. Я не сталкивался ни с одной проблемой, связанной со GlassFish, и мне очень приятно подчеркнуть это здесь. Отличная работа! И последнее замечание: прежде чем вы собираетесь безумно реализовать OutputBuffer, взгляните на то, что ваш любимый сервер приложений уже есть в наличии. GlassFish уже знает о сжатии GZIP, и его просто можно включить! Возможно, стоит подумать дважды, прежде чем внедрять здесь.
Ссылка: Переписать до краев — получить максимальную отдачу от этого! На GlassFish! от нашего партнера по JCG Маркуса Эйзела (Markus Eisele) из блога « Разработка программного обеспечения для предприятий с использованием Java» .
