Spring Framework
Простой проект с использованием Spring MVC
[править]Для первого знакомства создадим проект по управлению пользователями. Пользователей можно смотреть, добавлять, удалять и изменять. Все очень просто. Разделим проект на две части - одна часть будет реализацией бизнес логики, а вторая для ее управления и отображения. Сделано это для того, чтобы реализовать слабую связанность компонентов в проекте и облегчения тестирования.
Для работы нужно:
- Apache Tomcat 7.0.22
- Java SDK 7
- Ant 1.7
- Spring Framework 3.1.1
- NetBeans IDE 7.1
Создание проекта ModelService
[править]Создадим проект в NetBeans для бизнес логики под именем ModelService:
-
Шаг 1. New Project -> Java-> Java Class Library
-
Шаг 2. Даем имя проекту - ModelService
-
Шаг 3. Правый клик на Libraries в проекте ModelService -> Add Library и выбираем библиотеку JUnit 4.10
-
Шаг 4. Правый клик на Libraries в проекте ModelService -> Add JAR/Folder и добавляем spring-context-3.0.6.RELEASE.jar для того, чтобы вставить в сервис UserService аннотацию @Service (находится в архиве Spring-а)
-
Шаг 5. Создаем тесты для сервиса. Запускаем и собираем в jar командой "Clean and build"
-
Шаг 6. Структура созданного проекта ModelService
Посмотрим на проект UserService.
Сервис-слой приложения(Содержит интерфейсы, в которых описано ЧТО ДЕЛАТЬ С ДАННЫМИ или, другими словами, бизнес логика приложения . Также содержит практические реализации этих интерфейсов.). Добавим в проект файлы IUserService.java, UserService.java и User.java.
Интерфейс сервиса org.app.service.IUserService
package org.app.service;
import java.util.List;
import org.app.domain.User;
public interface IUserService {
List<User> getAll();
void updateUser(User user);
void deleteUser(Long id);
void addUser(User user);
}
... и его реализация
package org.app.service;
import java.util.ArrayList;
import java.util.List;
import org.app.domain.User;
import org.springframework.stereotype.Service;
@Service
public class UserService implements IUserService{
List<User> users = new ArrayList<User>();
public UserService() {
init();
}
private void init(){
users.add(new User(Long.valueOf(1), "alec"));
}
@Override
public List<User> getAll() {
return users;
}
@Override
public void updateUser(User user) {
for (User us : users) {
if (us.getId().longValue() == user.getId().longValue()) {
int index = users.indexOf(us);
users.set(index, user);
break;
}
}
}
@Override
public void deleteUser(Long id) {
for(User u : users){
if(u.getId().longValue() == id.longValue()) {
users.remove(u);
break;
}
}
}
@Override
public void addUser(User user) {
Long l = Long.MAX_VALUE;
for (User u : users) {
l = u.getId();
}
user.setId(l + 1);
users.add(user);
}
}
Доменный слой (Здесь находятся POJO-классы, такие как User - это то, ЧЕМ приложение оперирует в бизнес логике). Сущность пользователя с которой мы работаем - User.java:
package org.app.domain;
public class User {
private Long id;
private String name;
public User() {
}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
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;
}
}
Создание проекта UserProject
[править]Создадим новый Web проект в NetBeans под именем UserProject:
-
Шаг 1. New Project -> Web Application
-
Шаг 2. Даем имя проекту - UserProject
-
Шаг 3. Устанавливаем сервер для проекта
-
Шаг 4. Выбираем что проект будет использовать Spring Framework и имя dispatcher для имени контекста
-
Шаг 5. Правый клик на Libraries в проекте UserProject -> и добавляем созданный ModelService.jar
-
Шаг 6. Структура созданного проекта UserProject
Посмотрим на проект UserProject.
В дескрипторе развертывания приложения, web.xml, мы определяем, что все, что в запросе соответствует паттерну *.htm, должно обрабатываться DispatcherServlet из Spring-а. Также установим страницу по умолчанию в redirect.jsp:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<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-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
Файл applicationContext.xml оставим как есть. Потом туда можно будет добавлять настройки для Hibernate, JPA и т.д.
Файл dispatcher-servlet.xml содержит описания бинов (Java-файлов), которые будет использовать DispatcherServlet и является контекстом сервлета (WebApplicationContext).
<context:component-scan base-package="org.app" /> - указывает Spring где в CLASSPATH нужно искать бины контроллеров и сервисов(которые помечены аннотациями @Controller и @Service).
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<context:component-scan base-package="org.app" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
Веб-слой приложения (классы-контроллеры, описывающие КАК и КОГДА приложение взаимодействует с пользователем через веб.). Добавим в проект контроллер UserController.java
package org.app.controller;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.app.domain.User;
import org.app.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
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;
@Controller
@Scope("singleton")
public class UserController {
@Autowired
private IUserService userService;
@PostConstruct
public void post(){
System.out.println("post construct");
}
@PreDestroy
public void pre(){
System.out.println("pre destroy");
}
@RequestMapping(value="/index.htm", method=RequestMethod.GET)
public String index(Model model) {
model.addAttribute("accounts", userService.getAll());
return "index"; // показываем страницу index.jsp
}
@RequestMapping(value="/user/create.htm", method=RequestMethod.GET)
public String createUser(@ModelAttribute("userAttribute") User account, Model model) {
return "usercreate"; // показываем страницу usercreate.jsp
}
@RequestMapping(value="/user/update/{id}.htm", method=RequestMethod.GET)
public String updateUser(@PathVariable Long id, @ModelAttribute("userAttribute") User account, Model model){
for(User us : userService.getAll()){
if(us.getId().longValue() == id.longValue()){
account.setId(us.getId());
account.setName(us.getName());
model.addAttribute("userAttribute", account);
break;
}
}
return "userupdate";
}
@RequestMapping(value="/user/delete/{id}.htm", method=RequestMethod.GET)
public String deleteUser(@PathVariable Long id, Model model){
userService.deleteUser(id);
return "redirect:/index.htm"; // делаем редирект на index.htm
}
@RequestMapping(value="/user/save.htm", method=RequestMethod.POST)
public String saveUser(@ModelAttribute("userAttribute") User account, Model model) {
if(account.getId() == null){
this.userService.addUser(account);
} else {
this.userService.updateUser(account);
}
return "redirect:/index.htm";
}
}
Для проверки работы приложения можно создать файл org.app.controller.Main:
package org.app.controller;
import org.app.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(new String[] {"/web/WEB-INF/dispatcher-servlet.xml"});
IUserService iuser = (IUserService)context.getBean("userService"); // имя бина должно быть с маленькой буквы
System.out.println("count of users:"+iuser.getAll().size());
}
}
Слой представления (Описывает ЧТО пользователь увидит при взаимодействии с приложением).
Слой состоит из 4 файлов JSP: redirect, index, usercreate и userupdate:
redirect.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<% response.sendRedirect("index.htm"); %>
index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User catalog</title>
</head>
<body>
<a href="user/create.htm">create</a><br/>
<c:forEach items="${accounts}" var="car">
username: ${car.name} <a href="user/update/${car.id}.htm">update</a> <a href="user/delete/${car.id}.htm">delete</a>
<br />
</c:forEach>
</body>
</html>
usercreate.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Create user</h1>
<c:url var="saveUrl" value="/user/save.htm" />
<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}">
User:
<form:input path="name"></form:input>
<input type="submit" value="Save" />
</form:form>
</body>
</html>
userupdate.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Update user</h1>
<c:url var="saveUrl" value="/user/save.htm" />
<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}">
<form:hidden path="id" />
User:
<form:input path="name"></form:input>
<input type="submit" value="Save" />
</form:form>
</body>
</html>
Это все. Можно запускать проект и смотреть что получилось.
Средний проект с использованием Spring MVC, Hibernate, AJAX и валидации
[править]Создадим проект для хранения данных пользователей в организации. И снова разделим проект на две части. Будем использовать jQuery для отправки ajax запросов. И так же будем проверять входящие данные на валидность с помощью валидаторов.
Для работы нужно:
- Apache Tomcat 7.0.22
- Java SDK 7
- Ant 1.7
- Spring Framework 3.1.1
- NetBeans IDE 7.1
- Hibernate 3.2.5
- jQuery 1.7.2
Создание базы данных
[править]Создаем базу данных organization и соединение в NetBeans.
use organization;
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
position_id INT,
group_id INT
) ENGINE = InnoDB;
CREATE TABLE positions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255)
)ENGINE = InnoDB;
CREATE TABLE groups (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255)
)ENGINE = InnoDB;
CREATE TABLE languages (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255)
)ENGINE = InnoDB;
CREATE TABLE language_user (
user_id INT UNSIGNED ,
language_id INT UNSIGNED
)ENGINE = InnoDB;
INSERT INTO positions (title) VALUES ('junior developer');
INSERT INTO positions (title) VALUES ('middle developer');
INSERT INTO positions (title) VALUES ('senior developer');
INSERT INTO groups (title) VALUES ('group a');
INSERT INTO groups (title) VALUES ('group b');
INSERT INTO groups (title) VALUES ('group c');
INSERT INTO languages (title) VALUES ('java');
INSERT INTO languages (title) VALUES ('c#');
INSERT INTO languages (title) VALUES ('php');
INSERT INTO users (username, position_id, group_id) VALUES ('user 1', 1, 1);
INSERT INTO users (username, position_id, group_id) VALUES ('user 2', 2, 2);
INSERT INTO users (username, position_id, group_id) VALUES ('user 3', 3, 3);
INSERT INTO users (username, position_id, group_id) VALUES ('user 4', 2, 2);
INSERT INTO users (username, position_id, group_id) VALUES ('user 5', 3, 3);
INSERT INTO language_user (user_id, language_id) VALUES (1,1);
INSERT INTO language_user (user_id, language_id) VALUES (2,1);
INSERT INTO language_user (user_id, language_id) VALUES (3,1);
INSERT INTO language_user (user_id, language_id) VALUES (3,3);
INSERT INTO language_user (user_id, language_id) VALUES (4,2);
INSERT INTO language_user (user_id, language_id) VALUES (5,2);
INSERT INTO language_user (user_id, language_id) VALUES (4,1);
INSERT INTO language_user (user_id, language_id) VALUES (5,3);
Создание проекта OrganizationProject
[править]Создадим новый Web проект в NetBeans под именем OrganizationProject:
-
Структура проекта OrganizationProject
Подключаемые библиотеки:
- logback-classic-1.0.4.jar
- logback-core-1.0.4.jar
- slf4j-api.1.6.4.jar
- OrgService.jar
- mysql-connector-java-5.1.7-bin.jar
- Hibernate
- Persistence
Файл web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<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-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
В файле applicationContext.xml определим бин messageSource с помощью которого будем использовать в валидаторе локализованные сообщения.
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>
</beans>
Файл dispatcher-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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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">
<context:component-scan base-package="org.app" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
Веб слой приложения.
Файл org.app.controller.UsersController:
package org.app.controller;
import org.app.config.UserSettings;
import org.app.service.IGroupsService;
import org.app.service.IUserService;
import org.app.service.PositionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.bind.annotation.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Controller
@RequestMapping(value="/user")
public class UsersController {
@Autowired
private PositionService positionService;
@Autowired
private IUserService userService;
@Autowired
private IGroupsService groupsService;
@Autowired
private UserSettings userSettings;
Logger log = LoggerFactory.getLogger(UsersController.class);
@RequestMapping(value="/index.htm", method=RequestMethod.GET)
public String index(Model model) {
model.addAttribute("groups", groupsService.getAll());
model.addAttribute("positions", positionService.getAll());
model.addAttribute("users", userService.getAll());
log.debug("xxx debug");
userSettings.loadSettings();
log.debug("user settings :{}, {}", userSettings.getCountry(), userSettings.getLanguage());
return "user/list";
}
@RequestMapping(value="addajax.htm",method=RequestMethod.POST)
public @ResponseBody String add(@RequestParam(value = "username", required = true) String username,
@RequestParam(value = "positionid", required = true) Integer positionid,
@RequestParam(value = "groupid", required = true) Integer groupid ){
String returnText;
if(!username.isEmpty()){
userService.addEntity(username, groupid, positionid);
returnText = "User has been added to the list. Total number of users are: " +username+";posid = "+positionid+";grid="+groupid;
}else{
returnText = "Sorry, an error has occur. User has not been added to list.";
}
return returnText;
}
@RequestMapping(value="/deleteajax.htm",method=RequestMethod.POST)
public @ResponseBody String delete(@RequestParam(value = "userid", required = true) Integer userid ){
String returnText;
if(userid.intValue() != 0){
userService.deleteEntity(userid);
returnText = "deleted: " +userid;
}else{
returnText = "Sorry, an error has occur. User has not been added to list.";
}
return returnText;
}
}
Файл org.app.controller.GroupController:
package org.app.controller;
import org.app.domain.entities.Groups;
import org.app.service.IGroupsService;
import org.app.utils.GroupValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
public class GroupController {
@Autowired
private IGroupsService groupsService;
Logger log = LoggerFactory.getLogger(GroupController.class);
GroupValidator groupValidator = new GroupValidator();
@RequestMapping(value="/group/list.htm", method=RequestMethod.GET)
public String list(Model model){
model.addAttribute("groups", groupsService.getAll());
log.debug("group list");
return "group/list";
}
@RequestMapping(value="/group/add.htm",method=RequestMethod.GET)
public String add(@ModelAttribute("groupAttribute") Groups group){
return "group/add";
}
@RequestMapping(value = "/group/save.htm", method = RequestMethod.POST)
public String save(@ModelAttribute("groupAttribute") Groups group, BindingResult result) {
groupValidator.validate(group, result);
if (!result.hasErrors()) {
if (group.getId() == null) {
log.debug("group save");
this.groupsService.addEntity(group);
}
}
return "redirect:/group/list.htm";
}
}
Файл org.app.controller.Main для проверки работы:
package org.app.controller;
import java.util.Locale;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(new String[] {"/web/WEB-INF/dispatcher-servlet.xml", "/web/WEB-INF/applicationContext.xml"});
String message = context.getMessage("title.required", null, Locale.getDefault());
System.out.println("mess:"+message);
}
}
Файл org.app.utils.GroupValidator:
package org.app.utils;
import org.app.domain.entities.Groups;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class GroupValidator implements Validator{
@Override
public boolean supports(Class<?> type) {
return Groups.class.equals(type);
}
@Override
public void validate(Object o, Errors errors) {
Groups group = (Groups) o;
if(group.getTitle().trim().equals("")){
errors.rejectValue("title", "title.required");
}
}
}
Файл org.app.config.UserSettings для сохранения информации пользователя:
package org.app.config;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("userSettings")
public class UserSettings {
@Value("#{countryBean}") //inject bean
private Country country;
public UserSettings() {
}
public void loadSettings(){
country.loadSettings();
}
public String getLanguage(){
return country.getLanguage();
}
public String getCountry(){
return country.getCountry();
}
}
@Component("countryBean")
class Country {
@Value("RU") //inject string directly
private String country;
@Value("ru")
private String language;
public Country() {
}
public String getCountry() {
return country;
}
public String getLanguage() {
return language;
}
void loadSettings(){
this.country = Locale.getDefault().getCountry();
this.language = Locale.getDefault().getLanguage();
}
}
Слой представления приложения.
Чтобы в каждом файле не использовать одни и те же строки воспользуемся файлом include.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
Файл user/list.jsp:
<%@ include file="../include.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.7.2.min.js" />"></script>
<script type="text/javascript">
function addUser() {
var name = $('#name').val();
var positionid = $("#positions option:selected").val();
var groupid = $("#groups option:selected").val();
$.ajax({
type: "POST",
url: "${pageContext.request.contextPath}/user/addajax.htm",
data: "username=" + name+"&positionid="+positionid+"&groupid="+groupid,
success: function(response){
$('#info').html(response);
$('#name').val('');
},
error: function(e){
alert('Error: ' + e);
}
});
}
function deleteUser(id){
$.ajax({
type: "POST",
url: "${pageContext.request.contextPath}/user/deleteajax.htm",
data: "userid=" + id,
success: function(response){
$('#info').html(response);
},
error: function(e){
alert('Error: ' + e);
}
});
}
</script>
</head>
<body>
<a href="${pageContext.request.contextPath}/group/list.htm">groups</a><br/>
<h1>List users</h1>
<ul>
<c:forEach items="${users}" var="user">
<li>Name : <c:out value="${user.username}" />;<input type="button" value="Delete" onclick="deleteUser(${user.id})">
</c:forEach>
</ul>
<table>
<tr><td>Enter your name : </td><td> <input type="text" id="name"></td><td>
<select id="positions">
<c:forEach items="${positions}" var="pos">
<option value="${pos.id}"><c:out value="${pos.title}" /></option>
</c:forEach>
</select>
</td><td>
<select id="groups">
<c:forEach items="${groups}" var="group">
<option value="${group.id}"><c:out value="${group.title}" /></option>
</c:forEach>
</select>
</td></tr>
<tr><td colspan="2"><input type="button" value="Add Users" onclick="addUser()"><br/></td></tr>
<tr><td colspan="2"><div id="info" style="color: green;"></div></td></tr>
</table>
</body>
</html>
Файл group/add.jsp:
<%@ include file="../include.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<style>
.error {
color: #ff0000;
font-style: italic;
}
</style>
</head>
<body>
<h1>Add group</h1>
<c:url var="indexUrl" value="/user/index.htm" />
<c:url var="saveUrl" value="/group/save.htm" />
<form:form modelAttribute="groupAttribute" method="POST" action="${saveUrl}">
Title:
<form:input path="title"></form:input><form:errors path="title" cssClass="error" />
<input type="submit" value="Save" />
</form:form>
<p>Return to <a href="${indexUrl}">Index Page</a></p>
</body>
</html>
Файл group/list.jsp:
<%@ include file="../include.jsp" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>List groups</h1>
<c:url var="indexUrl" value="/user/index.htm" />
<a href="add.htm">create</a><br/>
<c:if test="${empty groups}">
List is empty.<br/>
</c:if>
<ul>
<c:forEach items="${groups}" var="group">
<li>Title : <c:out value="${group.title}" />;
</c:forEach>
</ul>
<p>Return to <a href="${indexUrl}">Index Page</a></p>
</body>
</html>
Файл logback.xml для логгирования с использованием SLF4J и его реализацией Logback:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p | %-55logger{55} | %m %n</pattern>
</encoder>
</appender>
<logger name="org.app.service">
<level value="DEBUG" />
</logger>
<logger name="org.springframework">
<level value="DEBUG" />
</logger>
<root>
<level value="DEBUG" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
Файл messages.properties:
title.required = Title is required
Создание проекта OrgService
[править]Создадим проект в NetBeans для бизнес логики под именем OrgService и подключим созданный OrgService.jar в проект OrganizationProject:
-
Структура проекта OrgService
-
1. Создаем конфигурационные файлы Hibernate
-
2. Создаем конфигурационные файлы Hibernate
-
3. Создаем конфигурационные файлы Hibernate
-
4. Создаем файл HibernateUtil
-
1. Создаем сущности для маппинга на БД
-
2. Создаем сущности для маппинга на БД
-
3. Создаем сущности для маппинга на БД
-
4. Создаем сущности для маппинга на БД
Подключаемые библиотеки:
- org.springframework.context-3.0.0.M3.jar
- org.springframework.transaction-3.0.0.M3.jar
- mysql-connector-java-5.1.7-bin.jar
- Hibernate
- Persistence
Доменный слой приложения.
HibernateUtil:
package org.utils;
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
private static final Session session;
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
session = sessionFactory.openSession();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession(){
return session;
}
}
Файл org.app.service.IUserService:
package org.app.service;
import java.util.List;
import org.app.domain.entities.Users;
public interface IUserService {
List<Users> getAll();
void addEntity(String username, Integer groupid, Integer positionid);
void deleteEntity(Integer id);
}
Файл org.app.service.IGroupsService:
package org.app.service;
import java.util.List;
import org.app.domain.entities.Groups;
public interface IGroupsService {
List<Groups> getAll();
void addEntity(Groups group);
void deleteEntity(Integer id);
}
Файл org.app.service.IPositionService:
package org.app.service;
import java.util.List;
import org.app.domain.entities.Positions;
public interface IPositionService {
List<Positions> getAll();
}
Файл org.app.service.UsersService:
package org.app.service;
import java.util.ArrayList;
import java.util.List;
import org.app.domain.entities.Users;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.utils.HibernateUtil;
@Service
public class UsersService implements IUserService{
Session session;
public UsersService() {
this.session = HibernateUtil.getSession();
}
@Override
public List<Users> getAll(){
List <Users>resultList = new ArrayList<Users>();
String hql = "from Users u";
session.beginTransaction();
Query q = session.createQuery(hql);
resultList.addAll(q.list());
session.getTransaction().commit();
return resultList;
}
public static void main(String[] args) {
try {
String hql = "from Users u where id = 1";
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Query q = session.createQuery(hql);
List <Users>resultList = q.list();
for(Users u : resultList){
System.out.println("user:"+u.getUsername());
}
System.out.println("size:" + resultList.toString());
session.getTransaction().commit();
SQLQuery sq = session.createSQLQuery("select u.* from users as u, languages as l, language_user as lu where l.id = lu.language_id and u.id = lu.user_id and l.title = ? and u.position_id = ?");
sq.setParameter(0, "c#");
sq.setParameter(1, 3);
List founded = sq.list();
System.out.println("res:"+founded.size());
} catch (HibernateException he) {
he.printStackTrace();
}
}
@Override
public void addEntity(String username, Integer groupid, Integer positionid) {
session.beginTransaction();
//Query q = session.createQuery(hql);
Users u = new Users(username, positionid, groupid);
session.save(u);
session.getTransaction().commit();
}
@Override
public void deleteEntity(Integer id) {
Users user = (Users) session.get(Users.class, id);
if(user != null) {
session.beginTransaction();
session.delete(user);
session.getTransaction().commit();
}
}
}
Файл org.app.service.GroupsService:
package org.app.service;
import java.util.ArrayList;
import java.util.List;
import org.app.domain.entities.Groups;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.utils.HibernateUtil;
@Service
@Transactional
public class GroupsService implements IGroupsService{
Session session;
public GroupsService() {
this.session = HibernateUtil.getSession();
}
@Override
public List<Groups> getAll(){
List <Groups>resultList = new ArrayList<Groups>();
String hql = "from Groups g";
Query q = session.createQuery(hql);
resultList.addAll(q.list());
return resultList;
}
@Override
public void addEntity(Groups group) {
session.save(group);
}
@Override
public void deleteEntity(Integer id) {
Groups g = (Groups) session.get(Groups.class, id);
if(g != null) {
session.delete(g);
}
}
}
Файл org.app.service.PositionService:
package org.app.service;
import java.util.ArrayList;
import java.util.List;
import org.app.domain.entities.Positions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.utils.HibernateUtil;
@Service
public class PositionService implements IPositionService{
Session session;
public PositionService() {
this.session = HibernateUtil.getSession();
}
@Override
public List<Positions> getAll() {
List <Positions>resultList = new ArrayList<Positions>();
String hql = "from Positions u";
session.beginTransaction();
Query q = session.createQuery(hql);
resultList.addAll(q.list());
session.getTransaction().commit();
return resultList;
}
}
Файл org.app.domain.entities.Users:
package org.app.domain.entities;
public class Users implements java.io.Serializable {
private Integer id;
private String username;
private Integer positionId;
private Integer groupId;
public Users() {
}
public Users(String username, Integer positionId, Integer groupId) {
this.username = username;
this.positionId = positionId;
this.groupId = groupId;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getPositionId() {
return this.positionId;
}
public void setPositionId(Integer positionId) {
this.positionId = positionId;
}
public Integer getGroupId() {
return this.groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
}
Файл org.app.domain.entities.Groups:
package org.app.domain.entities;
public class Groups implements java.io.Serializable {
private Integer id;
private String title;
public Groups() {
}
public Groups(String title) {
this.title = title;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
}
Настройки Hibernate
[править]Файл hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/organization</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<mapping resource="org/app/domain/entities/Positions.hbm.xml"/>
<mapping resource="org/app/domain/entities/Languages.hbm.xml"/>
<mapping resource="org/app/domain/entities/Groups.hbm.xml"/>
<mapping resource="org/app/domain/entities/Users.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Файл hibernate.reveng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
<schema-selection match-catalog="organization"/>
<table-filter match-name="languages"/>
<table-filter match-name="positions"/>
<table-filter match-name="groups"/>
<table-filter match-name="users"/>
</hibernate-reverse-engineering>
Это все. Можно запускать проект и смотреть что получилось.
Простой проект с использованием Spring Framework и JSON
[править]Создадим проект который будет использовать REST подход с использованием формата JSON и Spring Framework. Как обычно создаем Web проект и подключаем Spring Framework.
Для работы нужно:
- Apache Tomcat 7.0.22
- Java SDK 7
- Ant 1.7
- Spring Framework 3.1.1
- NetBeans IDE 7.1
- Jackson 1.9.7
Подключаемые библиотеки:
- Spring Framework
- jackson-all-1.9.7.jar http://jackson.codehaus.org/
-
Структура проекта UserService
Затем редактируем файлы и в итоге получаем следующие изменения.
Файл dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="app.controller" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
Файл web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<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-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Файл app.controller.IndexController:
package app.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping(value="/index")
public class IndexController {
@RequestMapping(value="/list", method=RequestMethod.GET)
@ResponseBody
public final List<UserObject> list(){
List<UserObject> list = new ArrayList<UserObject>();
list.add(new UserObject(Long.valueOf(1), "one"));
list.add(new UserObject(Long.valueOf(2), "two"));
return list;
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String help(){
return "help";
}
@RequestMapping(value="create", method=RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public UserObject create(@RequestBody final UserObject entity){
entity.setId(new Long(1));
// add to somewhere
System.out.println("create");
return entity;
}
@RequestMapping(value="update", method=RequestMethod.PUT)
@ResponseStatus(HttpStatus.OK)
public final void update(@RequestBody final UserObject entity){
// update to somewhere
System.out.println("update");
}
@RequestMapping(value="delete/{id}", method=RequestMethod.DELETE)
@ResponseStatus(HttpStatus.OK)
public final void delete(@PathVariable final Long id){
// delete to somewhere
System.out.println("delete");
}
@RequestMapping(value="findbyid/{id}", method=RequestMethod.GET)
@ResponseBody
public UserObject findByID(@PathVariable final Long id){
return new UserObject(id, "three");
}
}
Файл app.controller.UserObject:
package app.controller;
public class UserObject {
private Long id;
private String name;
public UserObject()
{
}
public UserObject(Long id, String name) {
this.id = id;
this.name = name;
}
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;
}
}
Файл jsp/index.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Service</title>
</head>
<body>
<a href="list">list</a>
</body>
</html>
Файл jsp/help.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Service</title>
</head>
<body>
<h1>Help</h1>
<a href="list">list</a>
<a href="delete/5">delete id = 5</a>
<a href="findbyid/5">find by id = 5</a>
</body>
</html>
Компилируем проект и запускаем.