Разработка web-приложения в Eclipse

В данном примере я попытаюсь показать, каким образом можно создать web-приложение под SpringFramework, используя Eclipse и Maven. Для воспроизведения всего ниже описанного нам потребуется Eclipse с предустановленным плагином под Maven.

Опубликовано 16-10-2012
Эксперементы
Теги java, http, servlet, eclipse, springframework

В данном примере я попытаюсь показать, каким образом можно создать web-приложение под SpringFramework, используя Eclipse и Maven. Для воспроизведения всего ниже описанного нам потребуется Eclipse с предустановленным плагином под Maven.

Создание Maven проекта.

Начнем с создания проекта. Для этого выберем в меню File -> New -> Project... затем в окне выбора проекта Maven -> Maven Project. В следующем окне нажимаем Next. Ищем achetypey которого GID "org.apache.maven.archetypes" и AID "maven-archetype-webapp" выбираем его и жмем Next. В появившемся окне указываем параметры нашего Maven проекта:

Group Id: ru.example
Artefact Id: sampleweb
Package: ru.example.sampleweb

Жмем Finish. Наш проект создан.

Запуск проекта из-под Tomcat при помощи Maven.

Для того что бы запустить наш новый проект под Tomcatом проделаем следующие шаги:
Нажимаем правой кнопкой мыши на наш проект и выбираем в выпадающем меню RunAs ->Mavenbuild... .
В появившемся окне заполняем поле Goals значением tomcat:run и нажимаем кнопку Run.
В консоли вы должны увидеть записи говорящие о том, что приложение запущено и доступно по адресу http://localhost:8080/sampleweb.

[INFO] --- tomcat-maven-plugin:1.1:run (default-cli) @ sampleweb ---
[INFO] Running war on http://localhost:8080/sampleweb

Добавляем поддержку Spring MVC.

Для подключения функций Spring MVC к нашему приложению нужно добавить зависимости в Maven проект. Для этого откроем файл pom.xml и в блок dependencies добавим следующие зависимости:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <type>jar</type>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>

Добавим загрузку контекста в web.xml нашего приложения:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

И servlet для обработки входящих запросов:

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/app/*</url-pattern>
</servlet-mapping>

Далее создаем файл описания основного контекста applicationContext.xml в директории src/main/webapp/WEB-INF/ следующего содержания:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
</beans>

Там же создаем файл контекста сервлета spring-servlet.xml (имяфайла состоит из имени сервлета + '-servlet.xml') следующего содержания:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/info.html">infoController</prop>
            </props>
        </property>
    </bean>

    <bean id="infoController" class="ru.example.sampleweb.InfoController">
    </bean>

</beans>

В контексте сервлета определен один контроллер infoController, который привязан к адресу /info.html . Создадим класс контролера, для этого сначала добавим папку с исходным кодом. Нажмем правой кнопкой мыши на нашем проекте и выберем в выпадающем меню New -> Source Folder. В появившемся окне заполним поле Folder name значением src/main/java и нажмем кнопку Finish. Теперь создадим класс контролера. Правой кнопкой мыши на проекте выбираем New ->Class. В появившемся окне заполняем поля Sourcefolder: sampleweb/src/main/java,Package: ru.example.sampleweb , Name: InfoController ,Superclass: org.springframework.web.servlet.mvc.AbstractController . Нажимаем кнопку Finish.
Редактируем новый класс src/main/java/ru/example/sampleweb/InfoController.java:

package ru.example.sampleweb;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class InfoController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html");
    
        PrintWriter out = response.getWriter();
        out.write("Server name: " + request.getServerName() + "<br/>");
        out.write("Server port: " + request.getServerPort() + "<br/>");
        out.write("Servlet path: " + request.getServletPath() + "<br/>");
        out.flush();

        return null;
    }
}

Запускаем наше приложение, как было описано ранее tomcat:run . Открываем браузером http://localhost:8080/sampleweb/app/info.html и видим результат:

Server name: localhost
Server port: 8080
Servlet path: /app

Добавляем логирование log4j.

Добавляем зависимость log4j в файл pom.xml блок dependencies:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
    <type>jar</type>
</dependency>

Добавляем ссылку на конфигурационный файл log4j в web.xml:

<context-param>
    <param-name>Log4j</param-name>
    <param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>

Создаем файл конфигурации log4j в папке src/main/resources. Для этого нажимаем правой кнопкой мыши на нашем проекте и выбираем в выпадающем меню New -> File . В появившемся окне выбираем папку sampleweb/src/main/resources и вводим имя файла log4j.properties. Жмем Finish.

Редактируем созданный файл:

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.conversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%M:%L - %m%n

Теперь добавим логирование в наш контроллер src/main/java/ru/example/sampleweb/InfoController.java:

package ru.example.sampleweb;

import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class InfoController extends AbstractController {

    private static Log log = LogFactory.getLog(InfoController.class);

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html");

        log.info("Request start.");
        PrintWriter out = response.getWriter();
        out.write("Server name: " + request.getServerName() + "<br/>");
        out.write("Server port: " + request.getServerPort() + "<br/>");
        out.write("Servlet path: " + request.getServletPath() + "<br/>");
        out.flush();
        log.info("Request finish.");

        return null;
    }
}

Запускаем наше приложение tomcat:run . Открываем http://localhost:8080/sampleweb/app/info.html . И видим в консоли две записи:

11:11:06,536  INFO http-8080-1 InfoController:handleRequestInternal:18 - Request start.
11:11:06,538  INFO http-8080-1 InfoController:handleRequestInternal:24 - Request finish.

Манипулирование запросами при помощи URLRewrite.

Облагородить адреса запросов нашего приложения позволит URLRewrite. Включаем зависимость URLRewrite в pom.xml блок dependencies:

<dependency>
    <groupId>org.tuckey</groupId>
    <artifactId>urlrewritefilter</artifactId>
    <version>4.0.3</version>
</dependency>

И добавляем фильтр в web.xml (после последнего context-param) для обработки входящих запросов:

<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Создадим конфигурационный файл urlrewrite.xml в папке src/main/webapp/WEB-INF/:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
        "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite>
    <rule match-type="wildcard">
        <from>/**</from>
        <to>/app/$1</to>
    </rule>
</urlrewrite>

Запускаем наше приложение tomcat:run . И если мы перейдем по адресу http://localhost:8080/sampleweb/info.html мы увидим http://localhost:8080/sampleweb/app/info.html. Для получения информации о конфигурации URLRewrite можно открыть адрес http://localhost:8080/sampleweb/rewrite-status .

Добавляем поддержку работы с БД.

Для демонстрации работы с БД мы будем использовать базу данных HSQLDB и пул соединений Apache DBCP. Для этого добавим зависимости в pom.xml блок dependencies :

<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.0.0</version>
</dependency>

Настроим пул соединений с базой HSQLDB, для этого добавим в файл applicationContext.xml следующие строчки:

<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver" />
    <property name="url" value="jdbc:hsqldb:mem:mymemdb" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

Добавим в наш контроллер InfoController поддержку DataSource :

package ru.example.sampleweb;

import java.io.PrintWriter;
import javax.sql.DataSource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class InfoController extends AbstractController {

    private static Log log = LogFactory.getLog(InfoController.class);
    private DataSource ds;

    public DataSource getDs() {
        return ds;
    }

    public void setDs(DataSource ds) {
        this.ds = ds;
    }

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html");

        log.info("Request start.");
        PrintWriter out = response.getWriter();
        out.write("Server name: " + request.getServerName() + "<br/>");
        out.write("Server port: " + request.getServerPort() + "<br/>");
        out.write("Servlet path: " + request.getServletPath() + "<br/>");
    out.write("DB name: "+ds.getConnection().getMetaData().getDatabaseProductName()+"<br/>");
        out.flush();
        log.info("Request finish.");

        return null;
    }
}

Привяжем ранее настроенный пул соединений к нашему контроллеру в контексте сервлета src/main/webapp/WEB-INF/spring-servlet.xml:

<bean id="infoController" class="ru.example.sampleweb.InfoController">
    <property name="ds" ref="ds"/>
</bean>

Запускам наше приложение tomcat:run . Открываем http://localhost:8080/sampleweb/info.html. И видим:

Servername: localhost
Serverport: 8080
Servletpath: /app
DB name: HSQL DatabaseEngine

Создаем шаблон на основе написанного приложения.

Все дальнейшие статьи и примеры будут базироваться на разработанном нами приложении. Для того чтобы не создавать каждый раз его с нуля, создадим Maven шаблон (Mavenarchetype), из которого без труда можно будет создавать сколь угодно новых проектов с написанной нами сегодня функциональностью.

Нажмем правой кнопкой мыши на проекте. В выпадающем меню выберем Run -> Maven build… . В появившемся окне заполним поле Goals: archetype:create-from-project . И нажмем Run. Не обращаем внимание на ошибки в консоли. Жмем правой кнопкой мыши на target/generated-sources/archetype, выбираем Run -> Maven build…. В появившемся окне заполняем Goals: install. Жмем Run. Все, наш шаблон проинсталлирован в локальный репозитарий Maven.

Теперь попробуем создать новый проект из шаблона. В верхнем меню выбираем File -> New -> Project…, далее Maven -> Maven Project жмем кнопку Next. Еще раз жмем Next. В появившемся окне выбираем "Include snapshot archetypes". Находим наш шаблон GID "ru.example" AID "semapleweb-archetype". Жмем Next. Заполняем поля Group Id: ru.test .Artefact Id: test . Package: ru.test.test. Жмем Finish. В созданном проекте изменился package на то, что мы указали, все остальное осталось неизменным. Запускаем созданный проект tomcat:run. Открываем http://localhost:8080/test/info.html .