markdown 使用Hibernate和MariaDB开发Jersey(Restful Web)应用程序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown 使用Hibernate和MariaDB开发Jersey(Restful Web)应用程序相关的知识,希望对你有一定的参考价值。
# Develop a Jersey Application using Hibernate and MariaDB
@credit Yan Zhu (https://github.com/nina-zhu)
### Introduction
[Jersey](https://jersey.java.net/) is the most popular amongst Restful web service development. Latest [Jersey 2.x](https://jersey.java.net/documentation/latest/index.html) version has been developed by Oracle/Glassfish team in accordance with [JAX-RS 2.0](https://jax-rs-spec.java.net/) specification. Earlier [Jersey 1.x](https://jersey.java.net/documentation/1.19.1/index.html) version was developed and supported by Oracle/Sun team.
Latest Jersey release version is 2.25 [see here](https://jersey.java.net/) and look [documentation](https://jersey.java.net/documentation/latest/index.html) and [API](https://jersey.java.net/apidocs/latest/jersey/index.html) for details. We will implement a Jersey example in this article based on latest 2.x version.
In this article, we will use Hibernate's rich API to interact with MariaDB database or in general any ORM compliant database. We will create a complete user CRUD application, use MariaDB to store the users records.
### Technology Used
* MariaDB 5.5.52
* Java 1.8
* NetBeans IDE 8.2
* Apache Tomcat 8.5.11
* Apache Maven 3.3.9
* Jersey-2.25
* Jersey-mvc-mustache-2.25
* Jersey-spring3-2.25
* Spring framework-4.3.5.RELEASE
* Hibernate-5.2.6.Final
* mysql-connector-java-5.1.40
## Set Up the MariaDB Server (on Ubuntu 14.04)
First we should set up the MariaDB server.
### Install MariaDB
Install the packages from the repositories by typing:
```
sudo apt-get update
sudo apt-get install mariadb-server libmariadbclient-dev libssl-dev
```
You will be asked to select and confirm a password for the administrative MariaDB account.
### Start MariaDB Server
Most likely, MariaDB is already started after installing, you can run following command to check:
```
ps -ef | grep mysql
```
If it is not started, start it manually by running:
```
sudo service mysql start
```
And to stop MariaDB server manually, run:
```
sudo service mysql stop
```
After installing MariaDB from Ubuntu's repositories, it will be started automatically when system boots up. If you want, you can disable its automatically starting by running:
```
sudo update-rc.d mysql disable
```
This will change `S19mysql` to `K81mysql` in `/etc/rc[2-5].d` directories, thus won't start MariaDB database server at boot time.
### Perform Initial Configuration
Get MariaDB server started, you can then run through a simple security script to perform the necessary initial configuration:
```
sudo mysql_secure_installation
```
You'll be asked for the administrative password you set for MariaDB during installation. Afterwards, you'll be asked a series of questions. Besides the first question, asking you to choose another administrative password, select yes for each question.
With the installation and initial database configuration out of the way, we can move on to create our database and database user.
### Create a Database and Database User
We can start by loggin into an interactive session with our database software by typing the following:
```
mysql -u root -p
```
You will be prompted for the administrative password you selected during installation. Afterwards, you will be given a prompt.
First, we will create a database for our Jersey project. Each project should have its own isolated database for security reasons. We will call our database "jersey". We'll set the default type for the database to UTF-8, which is what Jersey expects:
```
CREATE DATABASE jersey CHARACTER SET UTF8;
```
Remember to end all commands at an SQL prompt with a semicolon.
Next, we will create a database user which we will use to connect to and interact with the database. Set the password to something strong and secure (substitute *<user>* and *<password>* with your own ones):
```
CREATE USER <user>@localhost IDENTIFIED BY '<password>';
```
Now, all we need to do is give our database user access rights to the database we created (substitute *<user>* to yours):
```
GRANT ALL PRIVILEGES ON jersey.* TO <user>@localhost;
```
Flush the changes so that they will be available during the current session:
```
FLUSH PRIVILEGES;
```
Exit the SQL prompt to get back to your regular shell session:
```
exit
```
## Develop Jersey Application integrating with Hibernate
Now that our database is set up, we can start developing our Jersey application. Before that, we should first set up our development environment.
### Install JDK 8
1. Download "jdk-8u111-linux-x64.tar.gz" from <http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html>
2. Extract ("/usr/lib/jvm/" is my extracting destination, you can use yours)
```
$ sudo tar xzvf jdk-8u111-linux-x64.tar.gz -C /usr/lib/jvm/
```
3. Set environment variables
```
$ sudo gedit /etc/profile
```
Add following lines
```
# Set Java environment
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_111
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
```
Log out system and log in again.
You can now use the `java -version` to check the Java version.
### Install Apache Tomcat
1. Download "apache-tomcat-8.5.11.tar.gz" from <http://tomcat.apache.org/download-80.cgi>
2. Ensure `JAVA_HOME` environment variable is set and points to your JDK installation
```
$ echo $JAVA_HOME
```
3. Extract distribution archive in any directory
```
$ tar xzvf apache-tomcat-8.5.11.tar.gz -C ~
```
### Install NetBeans IDE
1. Download the installer file from <https://netbeans.org/downloads/>, select the "IDE Language" and "Platform", download the "All" bundle, the file name is "netbeans-8.2-linux.sh"
2. Make the installer file executable
```
$ chmod +x netbeans-8.2-linux.sh
```
3. Run the installer
```
$ ./netbeans-8.2-linux.sh
```
### Install Apache Maven
1. Download "apache-maven-3.3.9-bin.tar.gz" from <https://maven.apache.org/download.cgi>
2. Ensure `JAVA_HOME` environment variable is set and points to your JDK installation
```
$ echo $JAVA_HOME
```
3. Extract distribution archive in any directory
```
$ tar xzvf apache-maven-3.3.9-bin.tar.gz -C ~
```
4. Add the "bin" directory of the created directory "apache-maven-3.3.9" to the `PATH` environment variable
```
$ vi ~/.bashrc
```
Add following lines
```
export MAVEN_HOME=~/apache-maven-3.3.9
export PATH=$MAVEN_HOME/bin:$PATH
```
Exit terminal and open a new terminal, run
```
$ mvn -v
```
to confirm.
### Create a JavaEE Web Application from Maven Archetype
Jersey provides a Maven archetype for creating web application skeletons. To create the new web application skeleton project, execute the following Maven command in the directory where the new project should reside:
```
$ mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false -DgroupId=com.fortinet.experiment.jersey.examples -DartifactId=user_example -Dpackage=com.fortinet.experiment.jersey.examples.user_example -DarchetypeVersion=2.25
```
Feel free to adjust the "groupId", "package" and/or "artifactId" of your new web application project. Alternatively, you can change it by updating the new project "pom.xml" once it gets generated.
**Note:** It may take a while on the first run, this is because Maven is downloading the most recent artifacts (plugin jars and other files) into your local repository. You may also need to execute the command a couple of times before it succeeds, this is because the remote server may time out before your downloads are complete.
Once the project generation from a Jersey maven archetype is successfully finished, you should see the new "user_example" project directory created in your current location. The directory contains a standard Maven project structure, let's have a look at it in NetBeans IDE.
Open NetBeans IDE, click menu "File > Open Project...", choose the project you just generated, click "Open Project" button, the project is opened in NetBeans IDE. In "Files" window, we can see following project structure:
* Project build and management configuration is described in the pom.xml located in the project root directory.
* Project sources are located under src/main/java.
* Project resources are located under src/main/resources.
* Project web application files are located under src/main/webapp.
There is a generated "MyResource.java" file under "src/main/java/com/fortinet/experiment/jersey/examples/user_example" folder, here we don't need it, thus delete it.
### Mavenize required jars
Add "Jersey-2.25", "jersey-mvc-mustache-2.25", "Jersey-spring3-2.25", "Spring-4.3.5.RELEASE", "Hibernate-5.2.6.Final", "mysql-connector-java-5.1.40", etc. dependencies. To do this, change the generated "pom.xml" file content to following:
**pom.xml**
```
<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.fortinet.experiment.jersey.examples</groupId>
<artifactId>user_example</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>user_example</name>
<build>
<finalName>user_example</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<inherited>true</inherited>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<!-- Jersey extension module providing support for Mustache templates -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-mustache</artifactId>
</dependency>
<!-- Jersey extension module providing support for Spring 3 integration -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring Framework 4.x -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Hibernate Core 5.2.x -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.4.Final</version>
</dependency>
<!-- MySql-Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.25</jersey.version>
<spring.version>4.3.5.RELEASE</spring.version>
<hibernate.version>5.2.6.Final</hibernate.version>
<mysql.version>5.1.40</mysql.version>
<compileSource>1.8</compileSource>
<maven.compiler.version>3.6.0</maven.compiler.version>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
```
### Initialize Database
New a file, named "init-db.sql", under "src/main/resources". Write following sql statements to create a table and insert a few records:
**init-db.sql**
```
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` INT(6) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
```
Log into mysql client:
```
$ mysql -u root -p
```
Enter password then use database "jersey" that you created previously:
```
> use jersey;
```
Execute the sql file:
```
> source /<path to your location>/user_example/src/main/resources/init-db.sql;
```
Check the records:
```
> select * from users;
```
Exit client:
```
> exit
```
### Develop the Web Application
#### web.xml
For any web application, entry point is *web.xml* which describes how the incoming http requests are served / processed.
This *web.xml* file describes,
- Like any JavaEE web framework, register `org.glassfish.jersey.servlet.ServletContainer` with servlet container
- Set `<init-param>` with `<param-name>` as "jersey.config.server.provider.packages" and `<param-value>` describing the qualified package name of the JAX-RS annotated Resource/Provider classes. In this example, "com.fortinet.experiment.jersey.examples.user_example.service"
- Set `<init-param>` with `<param-name>` as "jersey.config.server.provider.classnames" and `<param-value>` describing the qualified class name of `MustacheMvcFeature` to use the capabilities of Jersey MVC templating support, here we use Mustache templating engine
- Set `<init-param>` with `<param-name>` as "jersey.config.server.mvc.templateBasePath.mustache" and `<param-value>` as "templates" to configure the base path where Mustache templates are located
- HTTP requests with URL pattern "/rest/*" will be sent to the registered servlet called "jersey-servlet" i.e. `org.glassfish.jersey.servlet.ServletContainer`
- Register spring listener `org.springframework.web.context.ContextLoaderListener`
- `<context-param>` with its attributes describes the location of the "spring-hibernate-jersey2.xml" file from where it has to be loaded. We will discuss briefly about this file
- `<welcome-file-list>` files under this tag is the start-up page
**web.xml** (under "src/main/webapp/WEB-INF")
```
<?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">
<!-- Jersey Servlet -->
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.fortinet.experiment.jersey.examples.user_example.service</param-value>
</init-param>
<!-- Register and configure MvcFeature -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.server.mvc.mustache.MustacheMvcFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.mvc.templateBasePath.mustache</param-name>
<param-value>templates</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- Spring Listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Load Spring context for registering beans within application context -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring-hibernate-jersey2.xml</param-value>
</context-param>
<!-- Welcome File -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
```
#### Spring Application Context File
This Spring application context file describes,
- `<context:annotation-config />` to activate annotation on the registered beans within application context
- `<context:component-scan base-package=""/>` tag scans all classes & sub-classes under the value of "base-package" attribute and register them with the Spring container
- `<tx:annotation-driven />` to turn ON transaction annotation on all DAO methods
- bean with `id="transactionManager"` to inform Spring to take care of the database transaction. All methods annotated with `@Transactional`
- bean with `id="sessionFactory"` defines hibernate properties to let it take care of database operations using Hibernate's rich API
- bean with `id="dataSource"` defines values for "driverClassName", "url", "username" and "password" for MySql/MariaDB database
**Note:** injection series between *transactionManager*, *sessionFactory* and *dataSource*
**spring-hibernate-jersey2.xml** (substitute *<user>* and *<password>* with your database username and password)
```
<?xml version="1.0" encoding="UTF-8"?>
<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:tx="http://www.springframework.org/schema/tx"
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-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- to activate annotations in beans already registered in the application context -->
<context:annotation-config />
<!-- scans packages to find and register beans within the application context -->
<context:component-scan base-package="com.fortinet.experiment.jersey.examples.user_example" />
<!-- turn on spring transaction annotation -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.fortinet.experiment.jersey.examples.user_example.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- dataSource configuration -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/jersey" />
<property name="username" value="<user>" />
<property name="password" value="<password>" />
</bean>
</beans>
```
#### Model Class (POJO)
Model class `User` with three primitive attributes with their getter/setter.
Also Hibernate POJO class is annotated describing the mapping between java property and database columns.
`@Entity`: represents an object that can be persisted in the database and for this class should have **no-arg** constructor
`@Table`: describes which table in the database to map with this class
`@Id`: defines this is unique which means it represents primary key in the database table
`@GeneratedValue`: this will be taken care by hibernate to define generator sequence
`@Column`: tells to map this particular property to table column in the database
**Note:** we can add attributes to the `@Column` annotation like name, length, nullable and unique
**User.java**
```
package com.fortinet.experiment.jersey.examples.user_example.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="users")
public class User implements Serializable {
// member variables
@Id
@GeneratedValue
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@Column(name="password")
private String password;
// getters & setters
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
```
#### URL Pattern
HTTP URL for any common web application is `http://<server>:<port>/<root-context>/<from_here_application_specific_path>`.
In our example, we are going to deploy the war into Apache Tomcat server so our server and port are `localhost` and `8080` respectively. Context root is the project name i.e. "user_example". Initial path for this application is "http://localhost:8080/user_example".
We have configured "/rest/*" as url-pattern for the "jersey-servlet" servlet in web.xml and at class-level path configured is "/users" using `@Path` annotation. Next respective path for each method annotated with `@Path` (method-level).
#### User Service
Defines basic CRUD operations for User service,
- `@GET` - retrieve all users (get all users)
- `@POST` - create/insert a new resource (add new user)
- `@GET` - read/select internal resource representation based on the user id
- `@PUT` - update/modify an internal resource representation (modify user)
- `@DELETE` - delete/remove a resource (delete user)
Let's discuss `@Produces`, `@Consumes` and `MediaType`.
*@Consumes*
Defines which MIME type is consumed by this method. For example, methods annotated with `@Consumes(MediaType.APPLICATION_JSON)` support JSON format.
*Note: When Content-Type is not specified in the header, then by default it expects request body in "application/x-www-form-urlencoded".*
*@Produces*
Defines which MIME type it will produce. For example, methods annotated with `@Produces(MediaType.APPLICATION_JSON)` produce response in JSON format.
*Note: @Produces can accept a list of types, in this case, when invoked it returns the response in the format which is the first string in the array. So, to get the response in the other format then set accept="<target MIME type>" in the header.*
Most widely used Media Types are
- APPLICATION_XML
- APPLICATION_JSON
- TEXT_HTML
- TEXT_PLAIN
- TEXT_XML
- APPLICATION_FORM_URLENCODED
**Note:** Jersey doesn't inherit JAX-RS annotations, so we are annotating Resource/Provider classes and then defining qualified package name in *web.xml*.
**UserService.java**
```
package com.fortinet.experiment.jersey.examples.user_example.service;
import java.util.List;
import java.net.URI;
import javax.ws.rs.core.Response;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
//import javax.ws.rs.PUT;
//import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.glassfish.jersey.server.mvc.Viewable;
import org.glassfish.jersey.server.mvc.Template;
import com.fortinet.experiment.jersey.examples.user_example.model.User;
import com.fortinet.experiment.jersey.examples.user_example.dao.UserDAO;
@Component
@Path("/users")
public class UserService {
@Autowired
private UserDAO userDAO;
// Basic CRUD operations for User service
// http://localhost:8080/user_example/rest/users/
@GET
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_HTML)
@Template(name="/users")
public List<User> getAllUsers() {
return userDAO.getAll();
}
// http://localhost:8080/user_example/rest/users/showForm
@GET
@Path("showForm")
@Produces(MediaType.TEXT_HTML)
public Viewable showForm() {
return new Viewable("/userForm");
}
// http://localhost:8080/user_example/rest/users/get/1
@GET
@Path("get/{id}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_HTML)
@Template(name="/userForm")
public User getUser(@PathParam("id") int userId) {
return userDAO.get(userId);
}
// http://localhost:8080/user_example/rest/users/add
@POST
@Path("add")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_HTML)
@Template(name="/users")
public List<User> createUser(@FormParam("username") String username,
@FormParam("password") String password) {
User newUser = new User();
newUser.setName(username);
newUser.setPassword(password);
userDAO.insertNew(newUser);
return getAllUsers();
}
// http://localhost:8080/user_example/rest/users/update
@POST // should use @PUT
@Path("update")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_HTML)
@Template(name="/users")
public List<User> updateUser(@FormParam("id") int userId,
@FormParam("username") String username,
@FormParam("password") String password) {
User user = new User();
user.setId(userId);
user.setName(username);
user.setPassword(password);
userDAO.update(user);
return getAllUsers();
}
// http://localhost:8080/user_example/rest/users/delete/1
@GET // should use @DELETE
@Path("delete/{id}")
public Response deleteUser(@PathParam("id") int userId) throws Exception {
User user = new User();
user.setId(userId);
userDAO.remove(user);
return Response.temporaryRedirect(new URI("/user_example/rest/users")).build();
}
}
```
**Note:** We should use `@PUT` for "updateUser" method and `@DELETE` for "deleteUser" method, here I use `@POST` and `@GET` respectively because I do not specify method in client page code (i.e. the template code), I just use the standard `<form action="xxx">` and `<a>` link to send requests for simplicity.
#### DAO Layer
This DAO layer takes care of the database interaction i.e. uses Hibernate's rich API to interact with MySql/MariaDB database using MySQLDialect.
**UserDAO.java**
```
package com.fortinet.experiment.jersey.examples.user_example.dao;
import java.util.List;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.fortinet.experiment.jersey.examples.user_example.model.User;
@Repository("userDAO")
public class UserDAO {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@SuppressWarnings("unchecked")
@Transactional
public List<User> getAll() {
Session session = sessionFactory.getCurrentSession();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> from = criteriaQuery.from(User.class);
CriteriaQuery<User> select = criteriaQuery.select(from);
TypedQuery<User> typedQuery = session.createQuery(select);
List<User> users = typedQuery.getResultList();
return users;
}
@Transactional
public String insertNew(User user) {
// insert into database & return primary key
int userId = (Integer) sessionFactory.getCurrentSession().save(user);
return "User information saved successfully with id " + userId;
}
@Transactional
public User get(int userId) {
User user = (User) sessionFactory.getCurrentSession().get(User.class, userId);
return user;
}
@Transactional
public String update(User user) {
sessionFactory.getCurrentSession().update(user);
return "User information updated successfully";
}
@Transactional
public String remove(User user) {
sessionFactory.getCurrentSession().delete(user);
return "User information with id " + user.getId() + " deleted successfully";
}
}
```
#### Add Templates
Create "templates" folder under "src/main/webapp", then create 2 templates for User service under "templates":
**users.mustache**
```
<!DOCTYPE html>
<html>
<head>
<title>Users</title>
<style>
.row {
line-height: 2;
}
.header {
font-weight: bold;
}
.col {
float: left;
width: 25%;
}
.toolbar {
margin-bottom: 20px;
}
.info {
font-style: italic;
}
</style>
</head>
<body>
<h2>Users</h2>
<div class="toolbar">
<a href="/user_example/rest/users/showForm">Create New One</a>
</div>
<div>
<div class="row header">
<div class="col">ID</div>
<div class="col">User Name</div>
<div class="col">Password</div>
<div class="col">Actions</div>
</div>
{{#.}}
<div class="row">
<div class="col">{{id}}</div>
<div class="col">{{name}}</div>
<div class="col">{{password}}</div>
<div class="col">
<a href="/user_example/rest/users/get/{{id}}">Edit</a>
<a href="/user_example/rest/users/delete/{{id}}">Delete</a>
</div>
</div>
{{/.}}
{{^.}}
<div class="info">Empty List</div>
{{/.}}
</div>
</body>
</html>
```
**userForm.mustache**
```
<!DOCTYPE html>
<html>
<head>
<title>User Form</title>
<style>
.row {
line-height: 2;
}
.row .label {
float: left;
width: 40%;
text-align: right;
margin-right: 20px;
}
.toolbar {
text-align: center;
margin-top: 30px;
}
</style>
</head>
<body>
<h2>User Form</h2>
<form action="{{^id}}/user_example/rest/users/add{{/id}}{{#id}}/user_example/rest/users/update{{/id}}" method="POST">
<input type="hidden" name="id" value="{{id}}" />
<div class="row">
<div class="label">User Name</div>
<div class="control">
<input type="text" name="username" value="{{name}}" {{#name}}readonly{{/name}} />
</div>
</div>
<div class="row">
<div class="label">Password</div>
<div class="control">
<input type="text" name="password" value="{{password}}" />
</div>
</div>
<div class="toolbar">
<input type="submit" value="Save" />
<a href="/user_example/rest/users">Cancel</a>
</div>
</form>
</body>
</html>
```
#### Modify Welcome File
We've specified "index.jsp" as welcome file in "web.xml". The original "index.jsp" file is generated by archetype "jersey-quickstart-webapp", let's modify it a little to provide a link to the User service.
**index.jsp**
```
<html>
<body>
<h2>Jersey RESTful Web Application!</h2>
<p><a href="/user_example/rest/users">User Service</a>
<p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
for more information on Jersey!
</body>
</html>
```
## Build Project
Now, all the code is done, it is time to build this project using maven capability of NetBeans. Right click on "user_example" project to open context menu, select "Clean and Build" option. Maven will start building the project. You can see the output in NetBeans "Output" window.
## Run Application in NetBeans
After building successfully, we can run the application in NetBeans.
First, we have to add Apache Tomcat server to NetBeans IDE. Go to "Services" window, right click "Servers" node, click "Add Server..." option, in dialog "Add Server Instance", choose server "Apache Tomcat or TomEE", click "Next>" button, specify the server location which is your Apache Tomcat installing location, enter the credentials (username, password) of an user in the manager role, check the checkbox "Create user if it does not exist" to create the user, click "Finish" button. You can see "Apache Tomcat or TomEE" under "Servers" node.
Then, we can run the application. Right click on "user_example" project, select "Run" as option, in the "Select deployment server" dialog, choose server "Apache Tomcat or TomEE", select option "Remember in Current IDE Session" to remember the deployment server in current IDE session so you don't have to select server every time you run the application. Click "OK" button.
After a while, your default browser will open page "http://localhost:8080/user_example/", what you see is the "index.jsp" page. You can test User service by clicking the "User Service" link.
### References
- https://mariadb.org/learn/
- https://mariadb.com/kb/en/
- http://www.oracle.com/technetwork/java/javase/downloads/index.html
- http://www.linuxdiyf.com/linux/16127.html
- http://www.linuxdiyf.com/linux/14898.html
- http://www.linuxdiyf.com/linux/15996.html
- https://netbeans.org/
- https://netbeans.org/community/releases/82/install.html
- https://netbeans.org/kb/docs/javaee/ecommerce/setup-dev-environ.html
- https://maven.apache.org/
- https://maven.apache.org/install.html
- https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
- https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
- http://search.maven.org/
- http://tomcat.apache.org/
- https://jersey.java.net/
- https://jersey.java.net/documentation/latest/getting-started.html
- https://jersey.java.net/documentation/latest/modules-and-dependencies.html
- https://jersey.java.net/documentation/latest/deployment.html
- https://jersey.java.net/documentation/latest/mvc.html
- http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/griz_jersey_intro/Grizzly-Jersey-Intro.html
- http://www.benchresources.net/jersey-2-x-web-service-integrating-with-spring-and-hibernate-orm-framework-using-annotation/
- http://www.tutorialspoint.com/jpa/jpa_criteria_api.htm
- https://www.tutorialspoint.com/maven/maven_netbeans.htm
以上是关于markdown 使用Hibernate和MariaDB开发Jersey(Restful Web)应用程序的主要内容,如果未能解决你的问题,请参考以下文章
markdown Principios de hibernate
markdown [Hibernate:basic-APIs] #hibernate #sessionFactory #session #session #transaction #database