Spring MVC Hibernate MySQL Integration(集成) CRUD Example Tutorial【摘】

Spring MVC Hibernate MySQL Integration(集成) CRUD Example Tutorial

We learned how to integrate Spring and Hibernate in our last tutorial(教程). Today we will move forward and integrate Spring MVC and Hibernate frameworks in a web application CRUD example.

Our final project structure(結(jié)構(gòu)) looks like below image, we will look into each of the components(組件) one by one.


Alt text
Alt text

Spring-MVC-Hibernate-Example

Note that I am using Spring 4.0.3.Release and Hibernate 4.3.5.Final versions for our example, same program is also compatible(兼容) for Spring 4 and Hibernate 3, however you need to make small changes in spring bean configuration file discussed in the last tutorial.

Maven Dependencies(maven依賴關(guān)系)

Let’s look at all the maven dependencies are required for hibernate and spring mvc framework integration.

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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.journaldev.spring</groupId>
    <artifactId>SpringMVCHibernate</artifactId>
    <name>SpringMVCHibernate</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>4.0.3.RELEASE</org.springframework-version>
        <org.aspectj-version>1.7.4</org.aspectj-version>
        <org.slf4j-version>1.7.5</org.slf4j-version>
        <hibernate.version>4.3.5.Final</hibernate.version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                 </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
         
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
         
        <!-- Apache Commons DBCP -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- Spring ORM -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
                 
        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency> 
         
        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>
 
        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
                 
        <!-- Servlet -->
        <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>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
     
        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
 
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>

Some of the dependencies above are included by STS (Spring Tool Suite) when I create Spring MVC project. Important dependencies above are spring-context, spring-webmvc, spring-tx, hibernate-core, hibernate-entitymanager and spring-orm. I am using Apache Commons DBCP for connection pooling, but in real life situations, most probably you have connection pooling done by the container and all we need is to provide the JNDI reference details to use.

NOTE: I noticed that some of the readers are getting database connection issues. Notice that in my pom.xml, there is no database driver. That works for me because I have MySQL driver in tomcat lib directory and some DataSource connections configured with it. For any database connection related issues, either put the database driver in container lib or include that in pom.xml dependencies.

Deployment Descriptor(部署描述符)

We need to plugin spring framework in our web application, that is done by configuring (配置)Spring framework DispatcherServlet as front controller. Our web.xml file looks like below.

web.xml

<?xml version="1.0" encoding="UTF-8"?>

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

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
 
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
     
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

Most of the part is boiler plate code(樣板代碼), most important part is the spring context file location where we will configure our spring beans and services. If you want, you can change them according to your project requirements.

Hibernate Entity Bean

We are using JPA annotations(JPA注解) in our entity bean class, however we can also have a simple java bean and mapping details in the xml file. In that case, we need to provide mapping file details while configuring Hibernate SessionFactory in spring bean configurations.

Person.java

package com.journaldev.spring.model;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
/**
 * Entity bean with JPA annotations
 * Hibernate provides JPA implementation
 * @author pankaj
 *
 */
@Entity
@Table(name="PERSON")
public class Person {
 
    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
     
    private String name;
     
    private String country;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getCountry() {
        return country;
    }
 
    public void setCountry(String country) {
        this.country = country;
    }
     
    @Override
    public String toString(){
        return "id="+id+", name="+name+", country="+country;
    }
}

Our entity bean maps to PERSON table in MySQL database, notice that I have not annotated “name” and “country” fields with @Column annotation because they are of same name. Below SQL script shows the table details.

person.sql

CREATE TABLE `Person` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '',
  `country` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Hibernate DAO Implementation(實現(xiàn))

We will create PersonDAO interface to declare the methods that we will use in our project. Next, we will provide hibernate specific(具體) implementation for it.(接口)

PersonDAO.java

package com.journaldev.spring.dao;
 
import java.util.List;
import com.journaldev.spring.model.Person;
 
public interface PersonDAO {
 
    public void addPerson(Person p);         
    public void updatePerson(Person p);
    public List<Person> listPersons();
    public Person getPersonById(int id);
    public void removePerson(int id);
}

Hibernate specific DAO implementation looks like below.

PersonDAOImpl.java

package com.journaldev.spring.dao;
 
import java.util.List;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.journaldev.spring.model.Person;
 
@Repository
public class PersonDAOImpl implements PersonDAO {
     
    private static final Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class);
 
    private SessionFactory sessionFactory;
     
    public void setSessionFactory(SessionFactory sf){
        this.sessionFactory = sf;
    }
 
    @Override
    public void addPerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.persist(p);
        logger.info("Person saved successfully, Person Details="+p);
    }
 
    @Override
    public void updatePerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.update(p);
        logger.info("Person updated successfully, Person Details="+p);
    }
 
    @SuppressWarnings("unchecked")
    @Override
    public List<Person> listPersons() {
        Session session = this.sessionFactory.getCurrentSession();
        List<Person> personsList = session.createQuery("from Person").list();
        for(Person p : personsList){
            logger.info("Person List::"+p);
        }
        return personsList;
    }
 
    @Override
    public Person getPersonById(int id) {
        Session session = this.sessionFactory.getCurrentSession();      
        Person p = (Person) session.load(Person.class, new Integer(id));
        logger.info("Person loaded successfully, Person details="+p);
        return p;
    }
 
    @Override
    public void removePerson(int id) {
        Session session = this.sessionFactory.getCurrentSession();
        Person p = (Person) session.load(Person.class, new Integer(id));
        if(null != p){
            session.delete(p);
        }
        logger.info("Person deleted successfully, person details="+p);
    }
 
}

Notice that I am not using Hibernate Transaction, that is because it will be taken care by Spring framework.

Spring Service Classes

Here are our service classes that are using Hibernate DAO classes to work with Person objects.

PersonService.java

package com.journaldev.spring.service;
 
import java.util.List;
 
import com.journaldev.spring.model.Person;
 
public interface PersonService {
 
    public void addPerson(Person p);
    public void updatePerson(Person p);
    public List<Person> listPersons();
    public Person getPersonById(int id);
    public void removePerson(int id);
     
}

PersonServiceImpl.java

package com.journaldev.spring.service;
 
import java.util.List;
 
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import com.journaldev.spring.dao.PersonDAO;
import com.journaldev.spring.model.Person;
 
@Service
public class PersonServiceImpl implements PersonService {
     
    private PersonDAO personDAO;
 
    public void setPersonDAO(PersonDAO personDAO) {
        this.personDAO = personDAO;
    }
 
    @Override
    @Transactional
    public void addPerson(Person p) {
        this.personDAO.addPerson(p);
    }
 
    @Override
    @Transactional
    public void updatePerson(Person p) {
        this.personDAO.updatePerson(p);
    }
 
    @Override
    @Transactional
    public List<Person> listPersons() {
        return this.personDAO.listPersons();
    }
 
    @Override
    @Transactional
    public Person getPersonById(int id) {
        return this.personDAO.getPersonById(id);
    }
 
    @Override
    @Transactional
    public void removePerson(int id) {
        this.personDAO.removePerson(id);
    }
 
}

Notice that spring declarative(聲明) transaction management(事物管理) is applied by using @Transactional annotation.

Spring Controller Class

Our DAO and Service classes are ready, it’s time to write our controller class that will take care of client(客戶端) requests and use service classes to perform(執(zhí)行) database specific operations (特殊操作)and then return the view pages.

PersonController.java

package com.journaldev.spring;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.journaldev.spring.model.Person;
import com.journaldev.spring.service.PersonService;
 
@Controller
public class PersonController {
     
    private PersonService personService;
     
    @Autowired(required=true)
    @Qualifier(value="personService")
    public void setPersonService(PersonService ps){
        this.personService = ps;
    }
     
    @RequestMapping(value = "/persons", method = RequestMethod.GET)
    public String listPersons(Model model) {
        model.addAttribute("person", new Person());
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }
     
    //For add and update person both
    @RequestMapping(value= "/person/add", method = RequestMethod.POST)
    public String addPerson(@ModelAttribute("person") Person p){
         
        if(p.getId() == 0){
            //new person, add it
            this.personService.addPerson(p);
        }else{
            //existing person, call update
            this.personService.updatePerson(p);
        }
         
        return "redirect:/persons";
         
    }
     
    @RequestMapping("/remove/{id}")
    public String removePerson(@PathVariable("id") int id){
         
        this.personService.removePerson(id);
        return "redirect:/persons";
    }
  
    @RequestMapping("/edit/{id}")
    public String editPerson(@PathVariable("id") int id, Model model){
        model.addAttribute("person", this.personService.getPersonById(id));
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }
     
}

Notice that I am using @Controller annotation, so that Spring framework will treat it as a Controller class to handle(處理) client requests. Also I am using @Autowired and @Qualifier annotations for injecting PersonService(使用自動注入注解注入service), we could have done it in the spring context xml file too.

Recommended Read: Spring Bean Autowiring

Spring Bean Configuration

Our services are ready, all we need is to wire them through spring bean configurations. Our root-context.xml file is empty, so we will look only into servlet-context.xml file.

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing 
        infrastructure -->
 
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
 
    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <beans:property name="url"
            value="jdbc:mysql://localhost:3306/TestDB" />
        <beans:property name="username" value="pankaj" />
        <beans:property name="password" value="pankaj123" />
    </beans:bean>
 
    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="annotatedClasses">
            <beans:list>
                <beans:value>com.journaldev.spring.model.Person</beans:value>
            </beans:list>
        </beans:property>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
                </beans:prop>
                <beans:prop key="hibernate.show_sql">true</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>
     
    <beans:bean id="personDAO" class="com.journaldev.spring.dao.PersonDAOImpl">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </beans:bean>
    <beans:bean id="personService" class="com.journaldev.spring.service.PersonServiceImpl">
        <beans:property name="personDAO" ref="personDAO"></beans:property>
    </beans:bean>
    <context:component-scan base-package="com.journaldev.spring" />
     
    <tx:annotation-driven transaction-manager="transactionManager"/>
     
    <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    </beans:bean>
 
</beans:beans>

dataSource bean is defined for org.apache.commons.dbcp.BasicDataSource class for basic connection pooling.

org.springframework.orm.hibernate4.LocalSessionFactoryBean bean is used for Hibernate 4 SessionFactory. For Hibernate 3, you will find similar classes as org.springframework.orm.hibernate3.LocalSessionFactoryBean and org.springframework.orm.hibernate3.AnnotationSessionFactoryBean.

One important point is that when we are depending on Spring framework for Hibernate Session management, we should not define hibernate.current_session_context_class property, otherwise you will get a lot of session transaction related issues.

personDAO and personService beans are self understood.

transactionManager bean definition for org.springframework.orm.hibernate4.HibernateTransactionManager is required for Spring ORM to support hibernate session transaction management. For Hibernate 3, you will find similar class as org.springframework.orm.hibernate3.HibernateTransactionManager. Spring uses AOP for transaction management, you can now relate it with @Transactional annotation.

Recommended Read: Spring AOP and Spring Transaction Management

View Page

Our last part of application is the view page, notice the attributes added to Model in Controller handler methods, we will use them to create our view page. We will also use JSTL tags, spring core and spring form tags.

person.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ page session="false" %>
<html>
<head>
    <title>Person Page</title>
    <style type="text/css">
        .tg  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}
        .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}
        .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}
        .tg .tg-4eph{background-color:#f9f9f9}
    </style>
</head>
<body>
<h1>
    Add a Person
</h1>
 
<c:url var="addAction" value="/person/add" ></c:url>
 
<form:form action="${addAction}" commandName="person">
<table>
    <c:if test="${!empty person.name}">
    <tr>
        <td>
            <form:label path="id">
                <spring:message text="ID"/>
            </form:label>
        </td>
        <td>
            <form:input path="id" readonly="true" size="8"  disabled="true" />
            <form:hidden path="id" />
        </td> 
    </tr>
    </c:if>
    <tr>
        <td>
            <form:label path="name">
                <spring:message text="Name"/>
            </form:label>
        </td>
        <td>
            <form:input path="name" />
        </td> 
    </tr>
    <tr>
        <td>
            <form:label path="country">
                <spring:message text="Country"/>
            </form:label>
        </td>
        <td>
            <form:input path="country" />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <c:if test="${!empty person.name}">
                <input type="submit"
                    value="<spring:message text="Edit Person"/>" />
            </c:if>
            <c:if test="${empty person.name}">
                <input type="submit"
                    value="<spring:message text="Add Person"/>" />
            </c:if>
        </td>
    </tr>
</table>  
</form:form>
<br>
<h3>Persons List</h3>
<c:if test="${!empty listPersons}">
    <table class="tg">
    <tr>
        <th width="80">Person ID</th>
        <th width="120">Person Name</th>
        <th width="120">Person Country</th>
        <th width="60">Edit</th>
        <th width="60">Delete</th>
    </tr>
    <c:forEach items="${listPersons}" var="person">
        <tr>
            <td>${person.id}</td>
            <td>${person.name}</td>
            <td>${person.country}</td>
            <td><a href="<c:url value='/edit/${person.id}' />" >Edit</a></td>
            <td><a href="<c:url value='/remove/${person.id}' />" >Delete</a></td>
        </tr>
    </c:forEach>
    </table>
</c:if>
</body>
</html>

項目源碼:鏈接:http://pan.baidu.com/s/1cC2WLw 密碼:f7mm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拢锹,隨后出現(xiàn)的幾起案子灾票,更是在濱河造成了極大的恐慌,老刑警劉巖获列,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粱胜,死亡現(xiàn)場離奇詭異,居然都是意外死亡徒蟆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門型型,熙熙樓的掌柜王于貴愁眉苦臉地迎上來段审,“玉大人,你說我怎么就攤上這事闹蒜∷峦鳎” “怎么了抑淫?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姥闪。 經(jīng)常有香客問我始苇,道長,這世上最難降的妖魔是什么筐喳? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任催式,我火速辦了婚禮,結(jié)果婚禮上硅瞧,老公的妹妹穿的比我還像新娘取董。我一直安慰自己假夺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布哺窄。 她就那樣靜靜地躺著,像睡著了一般账锹。 火紅的嫁衣襯著肌膚如雪萌业。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天奸柬,我揣著相機與錄音咽白,去河邊找鬼。 笑死鸟缕,一個胖子當(dāng)著我的面吹牛晶框,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播懂从,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼授段,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了番甩?” 一聲冷哼從身側(cè)響起侵贵,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缘薛,沒想到半個月后窍育,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡宴胧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年漱抓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恕齐。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡乞娄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仪或,我是刑警寧澤确镊,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站范删,受9級特大地震影響蕾域,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜到旦,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一束铭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厢绝,春花似錦契沫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至靶病,卻和暖如春会通,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背娄周。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工涕侈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煤辨。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓裳涛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親众辨。 傳聞我的和親對象是個殘疾皇子端三,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的閱讀 13,471評論 5 6
  • 今天宸宸還是重復(fù)他的《十根香腸》,音頻視頻都是在孩寶小鎮(zhèn)上看鹃彻。里面穿插有練習(xí)郊闯,也就幾個單詞跟讀和選圖片。跟讀后有分...
    宸媽418閱讀 193評論 0 0
  • 白落落的適應(yīng)能力是與生俱來的蛛株。 美麗的校園我的家团赁,白落落的口頭禪。一周左右谨履,適應(yīng)的也是妥妥的了欢摄。她熱愛校園如熱愛生...
    落花已忘言閱讀 252評論 0 2
  • 新裝系統(tǒng) 或者 修改主機名后,執(zhí)行 sudo 命令屉符,提示 無法解析主機 XXX剧浸。 解決方法: 修改 /etc/ho...
    西文Steven閱讀 5,531評論 0 0
  • 是哪一刻流年 如恒河沙粒 等多少微笑來超度 石頭滾出山谷 棱角還給刀劍 多少歲月顛倒 如光影暗換 怕是一千年短到 ...
    李榆閱讀 184評論 7 13