这几天由于项目需要,开始着手搭建项目Web的后端。后端采用的是Spring Web MVC + Hibernate4 + MySQL架构。之前的项目基本都是通过XML文件进行项目配置的,这一次将采用纯Java进行配置,Servlet3.0之后才支持这种配置,所以要选择支持Servlet3.0的容器运行,如:Tomcat7+、Jetty9等。一直习惯用Eclipse进行项目开发,本次开发将迁移到Intellij IDEA,我用的是IDEA15版本。目前最常见的构建工具有MavenGradle,由于对Gradle比较熟悉,所以还是依然选择Gradle进行项目的构建。接下来将一步一步地介绍本次项目后台的搭建过程。

Intellij IDEA

Gradle配置

创建工作目录

首先,先搭建Gradle项目的基本目录。先创建项目的根目录,如MyProject。然后进入根目录,创建src目录,这个目录是放开发的源代码的,该目录下创建main和test目录,main是放置主开发代码,test则放置编写的测试用例。在main和test目录下,都需要创建java和resources目录,java目录用来放置开发时的java代码,而resources目录则是用来放置配置文件等相关资源。其中main目录下还需创建webapp目录,这是用来存放web相关资源的。在根目录下还需创建libs目录,这个是用来存放本地的依赖Jar包,其他的所需Jar包在Gradle中配置完后,项目构建时会从Maven Center Repository中下载配置的依赖包。接下来就需要在根目录下创建build.gradle文件了,该文件是Gradle构建时所需的文件。

配置build.gradle文件

先贴出该项目的build.gradle文件配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse'
apply plugin: 'eclipse-wtp'
apply plugin: 'idea'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '0.0.1'
repositories {
flatDir {dirs "libs"}
mavenCentral()
}
ext {
springVersion = '4.2.2.RELEASE'
junitVersion = '4.12'
hibernateVersion = '5.0.3.Final'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile (
"org.springframework:spring-webmvc:${springVersion}",
"org.springframework.data:spring-data-jpa:1.9.0.RELEASE",
"org.hibernate:hibernate-core:${hibernateVersion}",
"org.hibernate:hibernate-entitymanager:${hibernateVersion}",
"org.hibernate:hibernate-ehcache:${hibernateVersion}",
"commons-dbcp:commons-dbcp:1.4",
"commons-fileupload:commons-fileupload:1.3.1",
"mysql:mysql-connector-java:5.1.37",
"com.fasterxml.jackson.core:jackson-core:2.6.3",
"com.fasterxml.jackson.core:jackson-databind:2.6.3",
"com.fasterxml.jackson.core:jackson-annotations:2.6.3",
"org.slf4j:slf4j-log4j12:1.7.12",
"log4j:log4j:1.2.17"
)
providedCompile (
"javax.servlet:javax.servlet-api:3.1.0"
)
runtime (
'javax.servlet:jstl:1.2'
)
testCompile ( "junit:junit:${junitVersion}")
}
tasks.withType(JavaCompile){
options.encoding = "utf-8"
}
tasks.withType(Javadoc){
options.encoding = "utf-8"
options.charSet = "utf-8"
}

上面的配置具体每一项的作用这里就不一一介绍了。其中 apply plugin就是应用gradle插件,这里用了IDEA和Eclipse等插件。 最主要的是dependencies,里面的配置是不同编译阶段所需的依赖包。从上面可以看到该项目所依赖的Spring web mvc和hibernate等相关依赖的配置。

构建项目命令

由于这里使用的是Intellij IDEA15进行开发,所以通过以下命令构建IDEA项目:

1
gradle idea

命令运行后,需要等待一段时间下载项目所需的依赖包。构建完后可以看到根目录下多出了几个跟IDEA项目相关的文件,这下可以通过IDEA导入该项目开发了。导入时会提示选择web模块,直接默认勾选,点击OK就可以。

Web项目配置

项目结构一览

进入IDEA开发界面后,接下来就是进行Spring Web MVC的配置。这里先列出项目搭建完后的src目录结构。
src directory structure
其中,整个项目的入口是 WebAppInitializer 这个类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class WebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(MvcConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}

该类声明了Spring Web MVC的DispatcherServlet,通过这个调度Servlet来实现Web访问。

Spring Web MVC 配置

Spring Web MVC的相关配置都在MvcConfig这个类中。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Configuration
@EnableWebMvc
@Import(JPAConfig.class)
@ComponentScan(basePackages = {"project.package.controller"})
public class MvcConfig extends WebMvcConfigurerAdapter {
/**
* 资源访问处理,一般为静态资源
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
/**
* 视图处理
*
* @return
*/
@Bean(name = "viewResolver")
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
return bean;
}
/**
* 配置JSON,当注解@ResponseBody时,自动转换成Json格式返回
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
/**
* 定义文件上传处理器
*
* @return
*/
@Bean(name = "multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
return resolver;
}
}

其中每个函数具体的作用注释都给出了。主要注意的是类开头的@Import(JPAConfig.class),这句话引入Hibernate JPA的相关配置。

Hibernate JPA配置

通过JPAConfig配置,使得项目可以使用Hibernate并连接到MySQL。具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@Configuration
@EnableTransactionManagement
@PropertySource(value = "classpath:jdbc.properties")
@ComponentScan({"project.package"})
@EnableJpaRepositories("project.package.persist")
public class JPAConfig {
@Resource
@Autowired
private Environment env;
/**
* 配置数据源
* @return
*/
@Bean(name = "dataSource")
public DataSource dataSource() {
BasicDataSource datasource = new BasicDataSource();
datasource.setDriverClassName(env.getProperty("jdbc.driver"));
datasource.setUrl(env.getProperty("jdbc.url"));
datasource.setUsername(env.getProperty("jdbc.username"));
datasource.setPassword(env.getProperty("jdbc.password"));
datasource.setInitialSize(Integer.valueOf(env.getProperty("dbcp.initialSize")));
datasource.setMaxActive(Integer.valueOf(env.getProperty("dbcp.maxActive")));
datasource.setMaxIdle(Integer.valueOf(env.getProperty("dbcp.maxIdle")));
datasource.setMinIdle(Integer.valueOf(env.getProperty("dbcp.minIdle")));
return datasource;
}
/**
* Hibernate相关属性配置
* @return
*/
private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
return properties;
}
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
factory.setJpaVendorAdapter(jpaVendorAdapter);
factory.setDataSource(dataSource());
factory.setPackagesToScan("com.grandland.glms.server.persist");
factory.setJpaProperties(hibProperties());
return factory;
}
@Bean(name = "transactionManager")
public JpaTransactionManager jpaTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return jpaTransactionManager;
}
}

该类主要是配置数据源连接,这里选择了dbcp连接池,配置连接MySQL,并支持事务,同时支持Spring Data JPA。在类的开头可以看到@PropertySource(value = "classpath:jdbc.properties"),这句话是将jdbc的相关配置注入到该类中,注入后可以通过Environment访问到相应的属性值。配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#mysql setting
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/your_database?useUnicode=true&characterEncoding=UTF-8
jdbc.username=username
jdbc.password=password
#hibernate settings
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
hibernate.format_sql=false
#dbcp settings
dbcp.initialSize=20
dbcp.maxActive=100
dbcp.maxIdle=50
dbcp.minIdle=10

一个MVC示例

创建User实体表

这里采用通过Spring data jpa来自动生成表,在包project.package.persist.entity中创建相应的实体类User。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String userName;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}

该类声明了三个属性,其中id是主键,并且自增。接下来还需实现对应的JpaRepository,这样才能对Entity进行相应的数据库操作。在project.package.persist.dao中创建UserDAO接口。

1
2
3
4
@Repository
public interface UserDAO extends JpaRepository<User, Integer>{
}

这里只是继承了Spring提供的JpaRepository接口,可以在这里自定更多的函数。这里就不详细介绍,具体可以查看相应的Spring data jpa开发文档。

定义User业务逻辑

project.package.service中创建UserService类提供对User的业务逻辑操作函数接口。

1
2
3
4
5
6
7
8
9
10
11
@Service
public class UserService {
@Autowired
private UserDAO userDAO;
public List<User> findAll(){
return userDAO.findAll();
};
}

这里只提供了一个方法,列出User表中的所有用户。可根据需要进行定义更多业务。

定义视图控制器

视图控制器对应的包是project.package.controller,添加UserController类,来控制视图展示逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value="/", method = RequestMethod.GET)
public ModelAndView index(){
ModelAndView mav = new ModelAndView("home");
mav.addObject("userList",userService.findAll());
return mav;
}
}

从代码中可以看到,这里用到了UserService类,并调用了获取所有用户的方法。并将获得的结果注入到ModelAndView中。这里的home是对应的JSP展示页面,由于前面Spring Web MVC的配置,框架能够在对应的目录下找到home.jsp文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<title>Spring Web MVC + Hibernate</title>
<meta charset="utf-8">
</head>
<body>
<table border="1" style="width:50%;text-align:center;margin:30px auto;border-collapse:collapse">
<tr>
<th>Id</th>
<th>Name</th>
<th>Password</th>
</tr>
<c:forEach var="user" items="${userList}" >
<tr>
<td>${user.id}</td>
<td>${user.userName}</td>
<td>${user.password}</td>
</tr>
</c:forEach>
</table>
</body>
</html>

这里用到了JSTL标签库,具体使用方法参照官网。下图是访问的界面显示:
Spring Web MVC + Hibernate

总结

这篇文章从头到尾记录了我搭建Spring Web MVC + Hibernate + MySQL项目的经过,由于把涉及到的代码都放上了,所以文章看起来很长。这几天配置这个项目也是花了一些时间,主要是跟之前项目的xml配置不同,采用了完全java的配置,其中也是碰到了一些问题。特别是第一次用Intellij IDEA进行项目开发,这个IDEA的功能确实比Eclipse强大太多了,编码时更加智能,界面更酷炫,我就不吐槽MacBook下用Eclipse开发经常出现程序卡顿、死机的问题了。建议大家也尝试一下这个IDE,除非你是Eclipse的重度用户,推荐下载高级版本,这里提倡正版,当然有其他手段能获得,你懂的。之前下过社区版,简直了,连个Tomcat都不能用(可能我不知道去哪配置 ^_^)。最后希望这篇文章能对你有帮助,在搭建中遇到任何问题可以联系我,源代码就不提供了,还要用于项目开发,见谅~