Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

JAVA, Dripstat, JVM, MMO

Anna | 2.06.2014 | нет комментариев

Поискал на прогре аналогичные статьи, обнаружил только Morphia — легкий ORM для MongoDB, управляемый аннотациями, ничего по связке Spring Data MongoDB не нашлось, в связи с этим решил написать пост из раздела «для самых маленьких» по настройке и применению связки Spring MongoDB.

Что будет из себя представлять само приложение:

Сделаем самый примитивный администратор контактов, для того, Дабы испробовать на примере элементарные операции CRUD.

Используемые библиотеки:
  • Spring IoC, MVC, Data (Mongo)
  • Mongo Driver
  • Log4j через sl4j
  • ну и немного дополнительных, которые опишу теснее в конфигурационном файле

Собирать план будет Maven, а код, лично я, пишу в Intellij IDEA (думаю, это лучшая IDE для Java). Кстати говоря, о превосходствах этой среды в своё время рассказывал asolntsev в посте Отчего IDEA отменнее Eclipse.

Конфигурация плана

Для начала опишем pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>

    <groupId>habra</groupId>
    <artifactId>habr</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- На момент написания статьи, версии библиотек являются последними -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <version.jdk>1.6</version.jdk>
        <version.spring>4.0.2.RELEASE</version.spring>
        <version.spring.mongodb>1.4.0.RELEASE</version.spring.mongodb>
        <version.jackson>1.9.13</version.jackson>
    </properties>

    <dependencies>
        <!-- Все, что необходимо для Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${version.spring}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${version.spring}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${version.spring}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${version.spring}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>${version.spring.mongodb}</version>
        </dependency>

        <!-- MongoDB драйвер -->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>2.11.4</version>
        </dependency>

        <!--
        Jackson JSON Mapper
        Тащу его неизменно, когда необходимо писать API на базе JSON объектов.
        В нашем случае можете эту библиотеку не тащить.
        -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>${version.jackson}</version>
        </dependency>

        <!-- Servlet Api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Логгирование -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>

        <!-- TEST -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!--
        Apache Commons, тащу пратически в всякий свой план из-за их полезности.
        Можете также их пропустить.
        -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Сейчас, когда все библиотеки описаны, дозволено приступить к изложению конфигурационных файлов Spring.
Для этого я традиционно создаю папку «spring» в src/main/resources, некоторые хранят файлы конфигурации Spring в webapp/WEB-INF/*, но это теснее кому как комфортно. Скажу сразу, конфигурационных файла будет 2, по весьма мере я считаю, что это особенно правильный вариант изложения конфигурации. 1-й файл будет включать конфигурацию по созданию бинов, подключение к БД, и пр., так сказать конфигурация контекстакаждого приложения. 2-й файл — это изложение работы DispatcherServlet, в всеобщем все, что связано теснее с отображением страниц, и вообще c Spring MVC.

Начнем с изложения контекста каждого приложения (src/main/resources/spring/applicationContext.xml):

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mongo="http://www.springframework.org/schema/data/mongo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context.xsd


http://www.springframework.org/schema/data/mongo

        http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">

    <!-- Включаем контекстные аннотации типа @Service, @Controller, @Repository... -->
    <context:annotation-config/>

    <!--
    Указываем Springу пакет, в котором он будет искать классы,
    помеченные аннотациями @Service, @Repository, и создавать их бины, но исключать он будет @Controller,
    т.к. эти классы нам необходимы будут в ином месте.
    -->
    <context:component-scan base-package="ru.habrahabr.sm">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--
    Загружает properties файл в конфигурацию Spring (т.е. сюда).
    Переменные из файла дозволено будет применять как ${mongo.host} (пример см. ниже)
    -->
    <context:property-placeholder location="classpath:database.properties"/>

    <!-- Создаем бин 'mongo' -->
    <mongo:mongo host="${mongo.host}" port="${mongo.port}"/>

    <!--
    Создаем бин 'mongoDbFactory'.
    Если MongoDB не требует авторизации, то поля username, password дозволено убрать
    -->
    <mongo:db-factory
            username="${mongo.username}"
            password="${mongo.password}"
            dbname="${mongo.db}"
            mongo-ref="mongo"/>

    <bean id="mongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
    </bean>
</beans>

Изложение контекста Spring MVC (src/main/resources/spring/dispatcherServlet.xml):

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context.xsd


http://www.springframework.org/schema/mvc

        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- Включаем MVC аннотации -->
    <mvc:annotation-driven/>

    <!--
    Применение MVC Resources
    Проще говоря, все файлы из папки webapp/resources/ будут доступны по адресу: localhost/resources/
    -->
    <mvc:resources mapping="/resources/**" location="/resources/"/>

    <!-- Указываем Spring MVC где искать классы-контроллеры -->
    <context:component-scan base-package="ru.habrahabr.sm">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- Указываем Spring MVC где будут лежать наши Viewшки, в данном случае это "/WEB-INF/pages/" -->
    <bean>
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

чудесно, Spring настроен, но если вы наблюдательно читали конфигурационные файлы, то подметили, что вapplicationContext.xml мы тянули “classpath:database.properties“. Это значит, что необходимо сделать файл в «src/main/resources/database.properties» со дальнейшим оглавлением:

mongo.host=localhost
mongo.port=27017
mongo.db=mydb
mongo.username=username
mongo.password=password

Разумеется, необходимо заменить данные позже знака ‘=’ своими. Подметьте, что поля username, password необязательные, и если у вас не необходима авторизация для приобретения доступа к MongoDB, загляните в applicationContext.xml, там указано какие поля необходимо убрать. Сразу сотворим конфигурационный файл для системы логгирования (src/main/resources/log4j.properties):

log4j.rootLogger=INFO, stdout

# Direct log messages to 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{dd.MM.yy HH:mm:ss} %5p - %m%n
log4j.appender.stdout.encoding=UTF-8

Наконец дозволено перейти к завершающему этапу конфигурирования Java Web приложения — изложение web.xml (src/main/webapp/WEB-INF/web.xml):

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <!-- Spring Application Context -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <!-- /Spring Application Context -->

    <!-- Spring Dispatcher Servlet Context -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/dispatcherServlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- /Spring Dispatcher Servlet Context -->

    <!-- Filters -->

    <!-- Character Filter -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- /Character Filter -->

    <!-- /Filters -->

</web-app>

На данном этапе у Вас теснее должна быть дальнейшая конструкция файлов в плане:

В папку «src/webapp/resources/» можете ложить всякий статический контент (картинки, жанры, js скрипты, и т.д.).

Написание кода

Наконец-то план сконфигурирован, и дозволено приступить к написанию самого кода приложения. Начнем с изложения модели и реализации слоя по работе с БД. Хочу подметить следующее: в MongoDB нет целочисленного AUTO_INCREMENT PK поля, а объекту по умолчанию присваивается ID такого вида: ObjectId(«5326b46f44ae9e6328b4566c»). Spring Data понимает данный ID как объект типа String. Проще говоря, если вам необходимо сделать так, Дабы у вас ID объекта было целочисленным и авто увеличивающимся, то придется над этим поработать независимо. Но на самом деле в этом нет ничего трудного и не стоит этого опасаться, а я теперь опишу как это делается! Если же Вас устраивает и длинный String в качестве ID объекта, то пропустите все классы (и соответственно их применение) в которых встречается слово «Sequence».

Для начала создаем коллекцию в БД с именем sequences. И руками вносим туда объект (insert):

{
    "_id" : "contacts",
    "sequence" : 0
}

В этой коллекции мы будем беречь пару: «имя таблицы» — «конечный ID», это значит, что для всякой таблицы(коллекции), в которой Вы хотите применять нашу самописную AUTO_INCREMENT реализацию, вам необходимо внести новую запись, как указано выше, только взамен «contacts» введите имя требуемой Вам коллекции. Кстати, если еще не знаете какой инструмент(management-tool) применять для MongoDB, то рекомендую Robomongo.

Сейчас создаем класс-обертку для этой коллекции:

package ru.habrahabr.sm.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * Date: 26.03.2014
 * Time: 15:38
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
@Document(collection = Sequence.COLLECTION_NAME)
public class Sequence {
    public static final String COLLECTION_NAME = "sequences";

    @Id
    private String id;
    private Long sequence;

    public Sequence() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Long getSequence() {
        return sequence;
    }

    public void setSequence(Long sequence) {
        this.sequence = sequence;
    }
}

Обратите внимание на запись “@Document(collection = Sequence.COLLECTION_NAME)” на самом деле дозволено было бы написать “@Document(collection = «sequences»)”, но это теснее скорее дело вкуса. Плюс есть одно очевидное превосходство у такого способа, дальше осознаете какое.

Сейчас опишем слой по работе с БД для класса-обертки “Sequence“, скажу сразу, Дабы не растягивать статью, я не буду создавать интерфейсы для сервисов и DAO, буду пользоваться теснее реализациями объектов (правда это как бы не дюже отлично), верю, что Вы понимаете о чем идет речь.

package ru.habrahabr.sm.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import ru.habrahabr.sm.exceptions.SequenceException;
import ru.habrahabr.sm.model.Sequence;

/**
 * Данный код взят с сайта mkyong,
 * точную ссылку обнаружить не сумел
 */
@Repository
public class SequenceDao {
    @Autowired private MongoOperations mongoOperations;

    public Long getNextSequenceId(String key) {
        // получаем объект Sequence по названию коллекции
        Query query = new Query(Criteria.where("id").is(key));

        // увеличиваем поле sequence на единицу
        Update update = new Update();
        update.inc("sequence", 1);

        // указываем опцию, что необходимо возвращать измененный объект
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);

        // немножко магии :) 
        Sequence sequence = mongoOperations.findAndModify(query, update, options, Sequence.class);

        // if no sequence throws SequenceException
        if(sequence == null) throw new SequenceException("Unable to get sequence for key: "   key);

        return sequence.getSequence();
    }
}

Сейчас класс исключения, которое выбрасывается, если в нашей коллекции `sequences` не будет соответствующей записи в БД (о которой я писал выше):

package ru.habrahabr.sm.exceptions;

/**
 * Date: 26.03.2014
 * Time: 16:09
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
public class SequenceException extends RuntimeException {
    public SequenceException(String message) {
        super(message);
    }
}

Сейчас создаем в БД коллекцию `contacts`, и класс-обертку:

package ru.habrahabr.sm.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serializable;

/**
 * Date: 26.03.2014
 * Time: 15:29
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
@Document(collection = Contact.COLLECTION_NAME)
public class Contact implements Serializable {
    public static final String COLLECTION_NAME = "contacts";

    @Id
    private Long id;
    /* *******************************************************
     Если вы хотите, Дабы ID объекта была автогенерируемая
     строка (об этом я писал в посте), то опишите поле ID так:
     @Id
     private String id;
     ********************************************************* */

    private String name;
    private String number;
    private String email;

    public Contact() {
    }

    public Contact(String name, String number, String email) {
        this.name = name;
        this.number = number;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Сейчас опишем DAO слой для нашего класса «Contact»:

package ru.habrahabr.sm.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import ru.habrahabr.sm.model.Contact;

import java.util.List;

/**
 * Date: 26.03.2014
 * Time: 19:13
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
@Repository
public class ContactDao {
    @Autowired private MongoOperations mongoOperations;

    public void save(Contact contact) {
        mongoOperations.save(contact);
    }

    public Contact get(Long id) {
        return mongoOperations.findOne(Query.query(Criteria.where("id").is(id)), Contact.class);
    }

    public List<Contact> getAll() {
        return mongoOperations.findAll(Contact.class);
    }

    public void remove(Long id) {
        mongoOperations.remove(Query.query(Criteria.where("id").is(id)), Contact.class);
    }
}

Хотелось бы подметить, что обновить запись в БД дозволено на ярусе DAO дальнейшим образом:

mongoOperations.updateFirst(query, update, Contact.class);

Разобраться с этим независимо проще простого и не составит для Вас сложностей. Но хотелось бы подметить, что если вы исполните:

mongoOperations.save(contact);

на объект, у которого ID теснее выставлен, и существует в БД, то произойдет перезапись объекта в БД под указанным ID.

Сейчас опишем слой бизнес-логики для класса «Contact»:

package ru.habrahabr.sm.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.habrahabr.sm.dao.ContactDao;
import ru.habrahabr.sm.dao.SequenceDao;
import ru.habrahabr.sm.model.Contact;

import java.util.List;

/**
 * Date: 26.03.2014
 * Time: 20:09
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
@Service
public class ContactService {
    @Autowired private SequenceDao sequenceDao;
    @Autowired private ContactDao contactDao;

    public void add(Contact contact) {
        contact.setId(sequenceDao.getNextSequenceId(Contact.COLLECTION_NAME));
        contactDao.save(contact);
    }

    public void update(Contact contact) {
        contactDao.save(contact);
    }

    public Contact get(Long id) {
        return contactDao.get(id);
    }

    public List<Contact> getAll() {
        return contactDao.getAll();
    }

    public void remove(Long id) {
        contactDao.remove(id);
    }
}

Ну вот, собственно и все, все, что касается связки Spring MongoDB мы проделали, т.е. сейчас Вы можете пользоваться ORM Spring Data с теснее подключенной к плану MongoDB, но раз я обещал на примере справочника показать работу с БД, то осталось написать еще класс-контроллер:

package ru.habrahabr.sm.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import ru.habrahabr.sm.model.Contact;
import ru.habrahabr.sm.services.ContactService;

/**
 * Date: 26.03.2014
 * Time: 20:30
 *
 * @author Ruslan Molchanov (ruslanys@gmail.com)
 */
@Controller
public class MainController {
    @Autowired private ContactService contactService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView showAll() {
        ModelAndView modelAndView = new ModelAndView("all");

        modelAndView.addObject("contacts", contactService.getAll());

        return modelAndView;
    }

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView showAddForm() {
        return new ModelAndView("add_form", "contact", new Contact());
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addContact(@ModelAttribute("contact") Contact contact) {
        if(contact.getId() == null) contactService.add(contact);
        else contactService.update(contact);

        return "redirect:/";
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public ModelAndView showEditForm(@RequestParam(required = true) Long id) {
        return new ModelAndView("add_form", "contact", contactService.get(id));
    }

    @RequestMapping(value = "/delete", method = RequestMethod.GET)
    public String deleteContact(@RequestParam(required = true) Long id) {
        contactService.remove(id);

        return "redirect:/";
    }
}

Ну и вьюшки (src/webapp/WEB-INF/pages/add_form.jsp):

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Добавить контакт</title>
</head>
<body>
<form:form method="POST" action="/add" modelAttribute="contact">
    <form:hidden path="id" />
    <table>
        <tr>
            <td>Name:</td>
            <td><form:input path="name" /></td>
        </tr>
        <tr>
            <td>Number:</td>
            <td><form:input path="number" /></td>
        </tr>
        <tr>
            <td>E-mail:</td>
            <td><form:input path="email" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" />
            </td>
        </tr>
    </table>
</form:form>
</body>
</html>

Еще одна (src/webapp/WEB-INF/all.jsp):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>Все контакты</title>
</head>
<body>
<table width="600px">
    <tr>
        <td><b>ID</b></td>
        <td><b>Name</b></td>
        <td><b>Number</b></td>
        <td><b>E-mail</b></td>
        <td><b>Action</b></td>
    </tr>
    <c:forEach var="contact" items="${contacts}">
        <tr>
            <td>${contact.id}</td>
            <td>${contact.name}</td>
            <td>${contact.number}</td>
            <td>${contact.email}</td>
            <td><a href="/edit?id=${contact.id}">Edit</a> | <a href="/delete?id=${contact.id}">Delete</a></td>
        </tr>
    </c:forEach>
    <tr>
        <td colspan="5">
            <a href="/add">Добавить запись</a>
        </td>
    </tr>
</table>
</body>
</html>

Ну вот и все, собираем план, запускаем, и вуаля:

Ссылка на исходники: db.tt/2zfWWsJT

P.S. Буду радостен, если кому-нибудь сгодится данный пост. Буду признателен за подсказки и исправления.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB