Веб разработка с Gaelyk

от автора

Меня давно вопрос — на чём проще всего сделать веб приложение ява программисту неискушенному в веб разработке.

Меня смущали несколько вещей — во первых — регистрация пользователей, логин, права доступа и так далее. Не хотелось с этим много возиться. Решение здесь я нашел в Grails с плагином Spring Security.

Во вторых — хостинг. Если писать на Яве (а мне так комфортнее всего, я на Яве с 1996 года), то хостинг дорогой. Платить по 15-20 долларов в месяц за сайты-эксперименты не хотелось.

И вот, наконец я нашел решение. Это — Gaelyk. Groovy фреймворк для Google App Engine.

Чтобы понять что он даёт и как его использовать давайте посмотрим на простейший проект.

Простейший проект можно сделать скачав template project или воспользовавшись maven archetype

Однако же первый из них использует gradle, а не maven и оба используют стандартный groovy компилятор, а не экслипсовский, который позволяет не создавать стабы, и оба не создают пример работы с Google datastore

Поэтому я создал свой maven archetype. Давайте с его помощью и создадим Gaelyk проект:

mvn archetype:generate -DarchetypeGroupId=org.bernshtam -DarchetypeArtifactId=gaelyk-archetype -DarchetypeRepository=http://bernshtam.name/maven2 -DgroupId=myexample -DartifactId=test1 -DarchetypeVersion=1.0 

Теперь можно сделать импорт созданному проекту в IDEA (в принципе и сгенерировать проект из архетайпа можно в IDEA тоже):

После импорта остается добавить Facet Google App Engine:

После этого добавляем конфигурацию запуска.
Обратите внимание что Google App Engine development kit, должен быть уже инсталлирован у Вас на машине и указан в IDEA (я указал кнопку). Все остальные зависимости принесет maven.

Нажимаем на мавеновский install:

И запускаем!

Ура, работает! Это простейшее приложения для создания заметок с приоритетом (зачем заметкам приоритет — я не знаю 🙂 )

Теперь давайте посмотрим, что же там есть.

web.xml ставит сервлет для грувлетов и шаблонов (gtpl)

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">     <listener>         <listener-class>groovyx.gaelyk.GaelykServletContextListener</listener-class>     </listener>      <servlet>         <servlet-name>GroovletServlet</servlet-name>         <servlet-class>groovyx.gaelyk.GaelykServlet</servlet-class>         <init-param>             <param-name>verbose</param-name>             <!-- Set it to true for more details -->             <param-value>false</param-value>         </init-param>         <load-on-startup>1</load-on-startup>     </servlet>     <servlet>         <servlet-name>TemplateServlet</servlet-name>         <servlet-class>groovyx.gaelyk.GaelykTemplateServlet</servlet-class>         <init-param>             <!-- Remove the default "generated by" messages from the templates -->             <param-name>generated.by</param-name>             <param-value>false</param-value>         </init-param>         <init-param>             <param-name>verbose</param-name>             <!-- Output generation time in the HTML, see source page -->             <param-value>false</param-value>         </init-param>         <load-on-startup>1</load-on-startup>     </servlet>      <filter>         <filter-name>RoutesFilter</filter-name>         <filter-class>groovyx.gaelyk.routes.RoutesFilter</filter-class>     </filter>      <servlet-mapping>         <servlet-name>GroovletServlet</servlet-name>         <url-pattern>*.groovy</url-pattern>     </servlet-mapping>     <servlet-mapping>         <servlet-name>TemplateServlet</servlet-name>         <url-pattern>*.gtpl</url-pattern>     </servlet-mapping>      <filter-mapping>         <filter-name>RoutesFilter</filter-name>         <url-pattern>/*</url-pattern>     </filter-mapping>      <welcome-file-list>         <welcome-file>index.gtpl</welcome-file>     </welcome-file-list> </web-app> 

appengine-web.xml дескриптор для Google App Engine. Вам надо заменить test1-archetype на имя своего приложения app engine, предварительно созданного в консоли app engine

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0-SNAPSHOT">     <application>test1-archetype</application>          <version>1</version>      <!-- Enable concurrent requests by default to serve requests in parallel -->     <threadsafe>true</threadsafe>      <!-- If all your templates and groovlets are encoding in UTF-8 -->     <!-- Please specify the settings below, otherwise weird characters may appear in your templates -->     <system-properties>         <property name="file.encoding" value="UTF-8"/>         <property name="groovy.source.encoding" value="UTF-8"/>         <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />     </system-properties>      <!-- Uncomment this section if you want your application to be able to receive XMPP messages -->     <!-- And create a file named jabber.groovy in /WEB-INF/groovy -->     <!-- Similarily, if you want to receive incoming emails -->     <!-- And create a file named email.groovy in /WEB-INF/groovy -->     <!--     <inbound-services>         <service>xmpp_message</service>         <service>mail</service>     </inbound-services>     -->      <!-- It it advised to keep this parameter to true -->     <!-- as per the release of SDK 1.2.8, -->     <!-- this should speed up cold startups of applications by 10% -->     <precompilation-enabled>true</precompilation-enabled>          <static-files>         <exclude path="/WEB-INF/**.groovy" />         <exclude path="**.gtpl" />     </static-files> </appengine-web-app>  

Теперь специфика Gaelyk. routes.groovy содержит инструкции какой запрос куда перенаправлять

get "/", redirect: "listnotes.groovy" get "/favicon.ico", redirect: "/images/favicon.png" 

Gaelyk это MVC фреймворк, а значит чаще всего запросы будут перенаправляться на контроллеры, в роли которых тут выступают грувлеты. Полное описание DSL для routes.groovy можно посмотреть здесь.

Теперь посмотрим на класс Note:

package myexample  import groovyx.gaelyk.datastore.Entity import groovyx.gaelyk.datastore.Key import groovyx.gaelyk.datastore.Unindexed  @Entity(unindexed=false) class Note {     @Key long id     String login     @Unindexed int priority     String text } 

По умолчанию Gaelyk предлагает простейшую интеграцию с Google App Engine datastore — это не полноценный ORM, не JPA, но для простейших вещей подходит.

Можно посмотреть примеры в контроллерах:

 Note  note = new Note(priority:priority, text: text, login: email) note.save() ...  def  note = Note.get(id) note.delete() .. def notes = Note.findAll { login == email } 

Элегантно, не правда ли?

Теперь посмотрите на это:

def email = user.email ... log.fine("$notes ${notes.size()}") ... String text =   request.getParameter("text") 

Переменные user, request и log не определены. Они инжектятся, как и многие другие. В частности user будет null, если пользователь не сделал логин и будет содержать класс содержащий детали пользователя если сделал. log содержит логгер.
request — это HttpRequest

Вообще, вы будете удивлены сколько всего автоматически инжектится в Ваши контроллеры и шаблоны (а по желанию — и в любые классы)

Модель из контроллеров в шаблоны передается через свойства request:

 request['notes'] = notes forward "index.gtpl" 

Осталось посмотреть на шаблоны. Они похожи на jsp, содержат % include %, вставки кода

<% include '/WEB-INF/includes/header.gtpl' %>  <h1>My notes</h1>  <% if (user) { %>     <p>                <table width="50%" border="1">                 <tr><th width="30%">Note</th><th>Priority</th><th></th></tr>                     <% request.notes.each { note -> %>                         <tr><td>${note.text}</td><td align="left"> ${note.priority}</td><td><A href="deletenote.groovy?id=${note.id}">X</A> </td></tr>                     <% } %>             </table>       </p>     <div class="add">     <h2>Add a new note</h2>     <p>     <form name="addnote" action="addnote.groovy" method="post">      Priority: <input name="priority" id="priority" type="number" value="1" min="1" max="10"/><br/> <br/>     Text: <input name="text" id="text" type="text"/>     <input type="submit" value=" Add Note "/></form>     </p>     </div>     <% } else { %>     <p><A href="${users.createLoginURL("/")}">Login</A> </p> to access your notes <% } %>   <% include '/WEB-INF/includes/footer.gtpl' %>  

Заметьте проверку на то, что пользователь залогинился ( if (user)), вытаскивание модели из request ( request.notes.each ), использование груви стиля ${note.priority}, создания ссылки на логин: ${users.createLoginURL("/")} (users — еще одна инжектнутая переменная).

Страница с логином в разработке выглядит совсем не так, как после деплоймента на Google App Engine, она дает возможность логинится под разными адресами, как админ и не как админ

Если понравилось, начинайте читать tutorial

ссылка на оригинал статьи http://habrahabr.ru/post/160281/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *