Java Web项目实战第1篇之环境搭建
写在前面的话
从今天开始一个Java Web实战项目,参考自 http://blog.csdn.net/eson_15/article/details/51277324 这个博客(非常感谢博主的分享精神)。本博客系列文章也会参考前面博客中项目的进度来写,因此标题可能高度相似,章节结构也可能相似,只是内容排版和行文上会有些区别。
现在开始记录我开发的过程,争取每一个项目中的每一个知识点都有一个比较详细的记录,对每个知识点尽可能记录总结好1. 基本原理,2.框架/工具使用配置, 2.框架/工具/解决方案的基本用法。技术能力需要在实践中得到提高,概念也需要从实践中才能深刻理解,但是光做项目不够,还需要做总结,消化做过的项目,才能真正变成自己的知识。
需要说明的是本博客是边开发变记录, 因此很多东西可能不会很准确,也不会很全面, 后续会逐步订正和完善的。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
下面开始本项目第一篇,环境的搭建,本项目主要使用主流框架SSH来完成。 搭建环境的整体步骤是是,
- 搭建好Java Web基础环境, 创建基本的web.xml配置文件
- 导入Spring框架Jar包,创建webContext.xml等配置文件,同时在web.xml中配置监听器(listener)来监听Spring容器对象的创建,这样就将Spring框架集成进了Java Web项目。
- 导入Hibernate框架Jar包,Hibernate大部分配置都将直接写入Spring的配置文件中,这样就将Hibernate也集成进了Java Web项目
- 导入Struts2框架Jar包,需要创建struts.xml用来配置Action, 同时在web.xml中配置过滤器(filter), 拦截器 (interceptor) 用来接管HTTP请求,这样就将struts2集成进了Java Web项目。
一、搭建Java Web基础环境
这个步骤需要注意的是做好java web的基本设置,例如编码之类。以及tomcat的一些基本配置。
1.tomcat的基本配置
下载tomcat,也可以下载xampp集成包,因为里面带有mysql使用方便。解压tomcat目录结构如下,
如果单独配置tomcat,我们需要使用如下一些配置文件
1 bin:二进制执行文件。里面最常用的文件是startup.bat,如果是 Linux 或 Mac 系统启动文件为 startup.sh。 启动tomcat后 2 conf:配置目录。里面最核心的文件是server.xml。可以在里面改端口号等。默认端口号是8080,也就是说,此端口号不能被其他应用程序占用。 3 lib:库文件。tomcat运行时需要的jar包所在的目录 4 logs:日志 5 temp:临时产生的文件,即缓存 6 webapps:web的应用程序。web应用放置到此目录下浏览器可以直接访问 7 work:编译以后的class文件。
如果启动上面的startup.bat, 在浏览器输入 http://localhost:8080/, 则可以看到tomcat的控制台页面(经典的汤姆猫页面),本篇暂不对tomcat的管理页面做介绍,因为本项目将使用Eclipse集成tomcat搭建web服务器。
如果要在Eclipse中集成tomcat,则不需要改动以上配置,直接在Eclipse中新建一个server,将路径指向tomcat的根目录即可,并且无需进入tomcat的bin目录去启动tomcat,而是直接在Eclipse中启动。
在Eclipse搭建基本的Java Web运行环境步骤如下,
- 在windows->show view->server中,添加tomcat的根目录。 Eclipse将自动配置和部署tomcat,不需要手工拷贝class文件。
- 新建一个java dynamic web 应用程序, 其target runtime选择刚才配置好的tomcat, 并勾选自动生成web.xml
- 完成前面2步,我们看到在新建的web工程的build path中,已经添加了apache tomcat library了, 此时就可以在WebContent中新建一个index.jsp, 启动tomcat,然后测试这个jsp文件(Run As->Run on Server).
这样就算是配置了好了一个能运行的java web应用了, 注意上面的web.xml如果没有自动生成, 可以直接拷贝 tomcat根目录的webapps\examples\WEB-INF\web.xml来用;
如果上面的tomcat library没有导入进web工程, 也可以手动在build path->libraries->Add libraries->Server Runtime中添加tomcat。
2. Eclipse配置全局的编码类型
如果不尽早统一编码, 由于后续需要往工程中添加jsp, java, xml 等多种不同类型的文件, 同时还需要连接数据库, 不同编码的数据在不同载体中传输存储,势必会引起乱码问题, 因此需要尽早统一编码。
在Eclipse中,默认编码是ISO-8859-1,不支持中文,可以设置全局的缺省字符编码(即默认编码),设置步骤如下。
a. windows->preference->general->workspace, 设置textfile encoding 为UTF-8
b.windows->preference->general->content types, 将右边所有文件都设置为UTF-8
c. 如果以上方法不起作用,还可以尝试直接找到相应类型的文件设置编码,如下
二、搭建Spring环境
1.基本的Spring 容器环境搭建
Spring中的jar包多达六七十个,但我们并不需要使用全部jar包。
按照Spring4.2.4 reference大致可以分为,core, aop, message, data access, web, test这6个模块, 我们也可以在Eclipse中分别创建不同的user library, 参考上面博客的分法,我也创建了如下library.
当我们导入core和aop两个library之后,就已经可以进行Spring最基本的IOC特性的测试了,下面是一个简单的测试用例。
2. Spring test模块简介
Spring的test模块中,org.springframework.test.context.junit4包提供在Junit下进行Spring集成测试的功能, 其中SpringJUnit4ClassRunner类提供了Spring容器,注解功能。
要在Junit中做基本的Spring容器测试,只需要在测试类头部添加注解 @RunWith(SpringJUnit4ClassRunner.class)
Junit默认会从类加载目录加载applicationContext.xml配置文件,当然也可以通过类头部的 @ContextConfiguration(locations="classpath*:testSpringContext.xml") 自定义配置文件,
如果在测试类中定义一个自动装配的容器对象
@Autowired
private ApplicationContext ctx
则此容器对象就能自动根据Junit测试类默认的spring配置文件或者自定义的配置文件进行初始化,
此时就能直接在测试类中使用Spring容器对象去加载Spring中的bean了! 一个基本的Junit集成Spring测试类如下,
1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration(locations="classpath*:testSpringContext.xml") 3 public class TestSpring { 4 @Autowired 5 private ApplicationContext ctx; 6 7 @Test 8 public void testSpringIoc() { 9 TestBean tb = (TestBean)ctx.getBean("testBean"); 10 tb.test(); 11 } 12 }
现在就在当前的J2eeShop工程中通过Junit测试Spring容器的基本功能,
先创建一个测试Bean,
1 package test; 2 3 public class TestBean implements java.io.Serializable { 4 private String name; 5 private int age; 6 public String getName() { 7 return name; 8 } 9 public void setName(String name) { 10 this.name = name; 11 } 12 public int getAge() { 13 return age; 14 } 15 public void setAge(int age) { 16 this.age = age; 17 } 18 public void test() { 19 System.out.println("this is TestBean.test()"); 20 System.out.println("name="+this.getName()+",age="+this.getAge()); 21 } 22 }
从spring的文档中拷贝一个配置文件模板内容,在6.2.1 Configuration metadata章节就有一个,然后配置一个最基本的测试bean
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 9 10 <context:component-scan base-package="test" /> 11 12 <bean id="testBean" class="test.TestBean"> 13 <property name="name" value="zhangsan" /> 14 <property name="age" value="25" /> 15 </bean> 16 </beans>
创建一个Junit测试类,
1 package test; 2 3 import static org.junit.Assert.*; 4 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.context.ApplicationContext; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 12 @RunWith(SpringJUnit4ClassRunner.class) 13 @ContextConfiguration(locations="classpath*:testSpringContext.xml") 14 public class TestSpring { 15 @Autowired 16 private ApplicationContext ctx; 17 18 @Test 19 public void testSpringIoc() { 20 TestBean tb = (TestBean)ctx.getBean("testBean"); 21 tb.test(); 22 } 23 }
执行结果,
this is TestBean.test()
name=张三,age=25
3. 在Web工程中集成Spring
我们上面的步骤仅仅是单独地配置了Web环境和Spring环境,并没有将两者集成起来。 我们在web.xml中配置<context-param>, 用来指定Spring容器的配置文,添加一个<listener>,用来监听Spring容器对象。
1 <context-param> 2 <param-name>contextConfigLocation</param-name> 3 <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/daoContext.xml</param-value> 4 </context-param> 5 6 <listener> 7 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 8 </listener>
这样,当Java web应用启动时, 会负责根据Spring配置文件来初始化一个Sping的容器对象。
4. Java Web加载Spring原理及简单测试
像上面那样将Spring集成到Java web中后,Spring容器就会随着java web应用的启动而启动,但是整个过程的基本原理是怎样的呢。
要弄清楚这个问题,需要先搞清楚java web应用,即servlet在tomcat中的启动过程。
4.1 Java Web应用程序的启动过程
以下文章详细描述了servlet在tomcat中的工作原理,
Servlet 工作原理解析 - https://www.ibm.com/developerworks/cn/java/j-lo-servlet/
Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析 - https://www.ibm.com/developerworks/cn/java/j-lo-tomcat2/
tomcat从启动到为一个java web应用提供服务的过程非常复杂,我将上面的内容高度抽象成下五步,
- tomcat启动过程中, 创建web容器(Container)。
- 向Container添加web应用,创建servlet容器(servletContext),一个web应用就对应一个servlet容器,即一个servletContext对象。
- 初始化servletContext:包括解析tomcat配置(server.xml等)以及web应用程序配置(主要是web.xml),加载servlet class文件等。
- 根据web.xml文件,初始化其中的filter, servlet, listener等
- 启动http服务,响应客户端请求
4.2 servlet事件监听及spring容器加载
前面说了java web应用程序的启动过程,那么集成在java web中的spring容器又是如何加载的呢?
我们知道tomcat会使用观察者/广播订阅的设计模式来通知事件的发生,当一个servlet容器(即创建了servletContext对象)启动,即发生了一个servlet容器创建事件,
tomcat中的web容器会将这个事件通知给相应监听对象。
在4.1节的第4步中,servletContext对象将会根据web.xml配置创建listener对象,我们在第3节中在web.xml配置了一个ContextLoaderListener监听器,
这是spring提供的一个监听器,servlet容器在初始化的时候会根据web.xml配置创建这样的监听器对象,这个监听器有什么作用呢?
查看这个监听器的源码如下,
1 public class ContextLoaderListener extends ContextLoader 2 implements ServletContextListener 3 { 4 ... 5 public void contextInitialized(ServletContextEvent event) 6 { 7 initWebApplicationContext(event.getServletContext()); 8 } 9 ... 10 }
可见这个监听器实现了servlet包中的ServletContextListener接口,并重写其中的contextInitialized方法,
根据servlet技术描述,servlet中的ServletContextListener实现类的实例可以监听servlet容器的启动(即创建servletContext对象)事件,并回调contextInitialized方法。
也就是说当上面的java web应用启动之后,将会通知spring的这个监听类对象,并回调被spring监听类重写的contextInitialized方法,
而在这个由spring监听器重写的回调方法中,进行了spring容器的初始化!即创建spring容器对象WebApplicationContext,并将此对象保存在servlet容器(即servletContext对象)中。
至此,java web容器完成了所有初始化工作,同时加载了spring容器,可以在web应用中直接使用注册在spring中的bean了,
上面过程比较复杂,下面再简要总结一下java web应用加载spring容器的过程,
- servlet容器创建spring listener对象
- web容器发出servlet容器启动成功的通知,spring的listener对象监听到事件
- spring的listener对象进行spring容器的初始化,并将spring容器保存进servlet容器中
- servlet容器加载了spring容器,此时可以直接在servlet实例中使用spring容器中的bean了
4.3 直接在jsp中测试spring和java web的集成
当我们完成了java web应用于spring的集成配置之后,就可以进行简单的测试了,我们可以直接在jsp中通过WebApplicationContextUtils获取spring容器对象,
index.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@page import="org.springframework.web.context.WebApplicationContext" %> 4 <%@page import="org.springframework.web.context.support.WebApplicationContextUtils" %> 5 <%@page import="test.TestBean" %> 6 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 7 <html> 8 <head> 9 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 10 <title>Insert title here</title> 11 </head> 12 <body> 13 <h1>Hello World</h1> 14 <% 15 WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); 16 TestBean tb = (TestBean) ctx.getBean("testBean"); 17 out.println("<h1>"+tb.getName()+"</h1>"); 18 tb.setName("lisi"); 19 %> 20 </body> 21 </html>
关键代码,
1 <% 2 WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); 3 TestBean tb = (TestBean) ctx.getBean("testBean"); 4 out.println("<h1>"+tb.getName()+"</h1>"); 5 tb.setName("lisi"); 6 %>
执行结果,可以看我们并没有显式地初始化spring容器,而是用工具WebApplicationContextUtils(本质上是获取由servlet容器初始化的spring容器)到了spring容器对象,将spring容器中的testBean的属性打印出来了,
到这里,spring框架就整合到了java web项目中,下一步是要整合Hibernate框架。
三、搭建Hibernate环境
首先也是导入Hibernat的必要jar包,以及Hibernate提供的一些第三方工具包(例如数据池C3P0和二级缓存ehcache),