现在JavaEE最热的框架也就属SSH了,但是每种技术所起的作用是什么我仅仅做简单介绍,最终的理解还是靠整个过程的搭建实践才可以明白。(本文搭建完成的SSH代码我已经上传到CSDN资源,有需要的读者可以通过http://download.csdn.net/detail/songdeitao/6730819这个链接进行下载)
- Struts主要是MVC思想的具体实现,
- Spring利用它的IOC和AOP来处理控制业务,
- Hibernate是操作数据库的一种框架,它简化了直接使用jdbc api的代码操作数据库的复杂性和冗余性。
下面便开始整个SSH框架的搭建过程。
本文选取struts-2.3.1,spring-framework-3.2.2,hibernate-4.1.1的搭建过程,首先这几个版本都是比较新的版本,也是通过测试,比较通用稳定的版本。
框架名称 | 版本 | 最后发布时间 | 下载链接 | |
Struts2 | 2.3.1 | 2011-12-13 |
| |
Hibernate | 4.1.1 | 2012-03-08 |
| |
Spring | 3.2.2 | 2013-03-14 |
|
下载完成之后进行解压缩,如图1所示:
图1
环境搭建:MyEclipse8.5+JDK1.6+Apache-tomcat-6.0.33
在整个搭建过程中,我尽量一步步做演示,从Struts开始,然后到Hibernate的整合,然后在整合Spring,整个过程中会遇到常见的异常,然后进行解决,并且总结出注意事项。
首先是最后搭建成功后的目录结构(项目名称为SSHDemo,下文为SSH,这里仅仅呈现的是目录结构,下文将一步步搭建成这样的结果),如图2所示:
图2
下面开始创建项目SSH,打开MyEclipse,File—>New—>Web Project,输入项目名称SSH,如图3所示:
图3
点击Finish完成项目创建,如图4所示:
紧接着需要完成Struts框架的引入,搭建成一个Struts项目,打开解压完成后的struts-2.3.1目录struts-2.3.1\apps\struts2-blank.war,解压缩struts2-blank.war到struts2-blank目录中,
步骤一:进入到struts-2.3.1\apps\struts2-blank\WEB-INF目录下,将其中web.xml文件中的内容全部复制到项目目录结构中web.xml文件中并且替换掉原来的所有内容,修改后的文件内容如下web.xml所示:
web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <!-- Struts2过滤器,将所有的请求进行拦截并进行处理 -->
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
步骤二:将struts-2.3.1\apps\struts2-blank\WEB-INF\lib文件夹中的所有jar包添加到web项目目录结构lib中,添加后如图5所示:
图5
其中jar包以及其作用如下讲解,
jar包(.jar) | 作用 |
asm-3.3 | 操作java字节码的类库 |
asm-commons-3.3 | 提供了基于事件的表现形式 |
asm-tree-3.3 | 提供了基于对象的表现形式 |
commons-fileupload-1.2.2 | Struts 文件的上传和下载功能的实现 |
commons-io-2.0.1 | commons项目(commons项目就是java中一些常用的公共的组件)的io子项目,是处理异常的 |
commons-lang-2.5 | 为java.lang提供扩展 |
freemarker-2.3.18 | 支持freemarker(struts2的UI标签的模板使用FreeMarker编写)的,在webwork中也有 |
javassist-3.11.0.GA | 一个开源的分析、编辑和创建Java字节码的类库(hibernate中也需要,引入其中一个即可) |
ognl-3.0.3 | 支持ognl语言(对象图导航语言(Object Graph Navigation Language))的,struts2框架通过其读写对象的属性,webwork也支持ognl语言 |
struts2-core-2.3.1 | struts2的核心jar包 |
xwork-core-2.3.1 | xwork的核心jar包,由于struts2是webwork的升级版本,所以必定对其有所依赖(struts2在其基础上构建) |
步骤三:将路径struts-2.3.1\apps\struts2-blank\WEB-INF\src\java下的struts.xml文件拷贝到项目总src下,修改后的文件内容如下所示:
struts.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <!--
- 动态方法调用,如果为true,开发时候可以使用,代表可以通过 url地址动态调用执行相应的方法,不推荐,如果为false,
- 不可以动态方法调用,但可以通过进行通配符的设置进行动态方法调用,推荐为false
- -->
- <constant name="struts.enable.DynamicMethodInvocation" value="true" />
- <!-- 开发者模式,为true时候,如果改动配置文件不需要重启服务器就可以自动更新,开发时候建议开启 -->
- <constant name="struts.devMode" value="false" />
- <!-- name代指包名,namespace是命名空间,是在url中照写的部分 -->
- <package name="user" namespace="/" extends="struts-default">
- <!-- name指代url中写在namespace中的部分,class指代将执行的action -->
- <action name="user" class="com.steven.action.UserAction">
- <!-- 如果方法返回success,则执行以下部分 -->
- <result name="success">
- WEB-INF/jsp/welcome.jsp
- </result>
- </action>
- </package>
- </struts>
图6
此时,文件index.jsp,welcome.jsp,UserAction.java,User.java内容分别如下:
index.jsp
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>SSH index</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- <h2>这是一个SSH项目,请点击<a href="user">这里</a> 显示用户列表。</h2>
- </body>
- </html>
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!-- 引入Struts2的标签库 -->
- <%@taglib prefix="s" uri="/struts-tags"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>welcome</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- <table border="1" cellpadding="0" cellspacing="0" width="600"
- style="text-align: center;">
- <tr>
- <th>姓名</th>
- <th>年龄</th>
- <th>生日</th>
- <th>是否是VIP</th>
- </tr>
- <!-- OGNL表达式的输出 -->
- <s:iterator value="#request.userList" var="user">
- <tr>
- <td>
- <!-- EL表达式输出 -->
- ${user.userName }
- </td>
- <td>${user.age }</td>
- <td>
- <!-- struts标签日期格式标签 -->
- <s:date name="#user.birthday" format="yyyy-MM-dd" />
- </td>
- <td>
- <!-- struts2中条件输出 -->
- <s:if test="#user.isVip == true">
- 是VIP
- </s:if>
- <s:else>
- 不是VIP
- </s:else>
- </td>
- </tr>
- </s:iterator>
- </table>
- </body>
- </html>
UserAction.java
- package com.steven.action;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import java.util.Map;
- import org.apache.struts2.interceptor.RequestAware;
- import com.opensymphony.xwork2.ActionSupport;
- import com.steven.entity.User;
- /**
- * 通过继承ActionSupport获得Struts2的已有功能,
- * 通过实现RequestAware获取request(这种方式常用,还有其他三种方式,这里不再赘述)
- * 四种获取request方式请参照http://blog.csdn.net/ms2146/article/details/5406004
- *
- * @author Steven
- *
- */
- public class UserAction extends ActionSupport implements RequestAware {
- private static final long serialVersionUID = 1L;
- private Map<String, Object> request;
- @Override
- public String execute() throws Exception {
- // 创建一个用户集合
- List<User> userList = new ArrayList<User>();
- // 创建用户并添加到用户集合中
- userList.add(new User("Steven", 1, new Date(), true));
- userList.add(new User("Lily", 1, new Date(), false));
- userList.add(new User("Tom", 1, new Date(), false));
- // 将用户存储到ActionContext中(可以通过ognl表达式获取)
- request.put("userList", userList);
- return SUCCESS;
- }
- public void setRequest(Map<String, Object> request) {
- this.request = request;
- }
- }
- package com.steven.entity;
- import java.util.Date;
- /**
- * 实体类
- *
- * @author Steven
- *
- */
- public class User {
- // 用户Id
- private int userId;
- // 用户名
- private String userName;
- // 用户年龄
- private int age;
- // 用户生日
- private Date birthday;
- // 用户是否是会员 true:是 false:不是
- private boolean isVip;
- public User() {
- }
- // 有参构造
- public User(String userName, int age, Date birthday, boolean isVip) {
- this.userName = userName;
- this.age = age;
- this.birthday = birthday;
- this.isVip = isVip;
- }
- public int getUserId() {
- return userId;
- }
- public void setUserId(int userId) {
- this.userId = userId;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public Date getBirthday() {
- return birthday;
- }
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
- public boolean getIsVip() {
- return isVip;
- }
- public void setIsVip(boolean isVip) {
- this.isVip = isVip;
- }
- @Override
- public String toString() {
- return "用户信息: [年龄是" + this.getAge() + ", 生日是" + this.getBirthday()
- + ", 用户编号是" + this.getUserId() + ", 用户名是" + userName
- + isVip(this.getIsVip()) + "]";
- }
- /**
- * 用来进行测试使用
- *
- * @param isVip
- * @return
- */
- public String isVip(boolean isVip) {
- return ", " + (isVip == true ? "是" : "不是") + "会员";
- }
- }
通过MyEclipse部署项目到Tomcat,具体的过程如下:
点击部署按钮,如图7所示:
图7
进行部署操作,如图8,9所示:
图8
图9
部署后启动服务器,如下图10,11所示:
图10
图11
然后打开浏览器,输入URL(http://localhost:8080)观察tomcat是否启动成功,成功如图12所示,成功后URL后添加项目名称SSH,即(http://localhost:8080/SSH)打开首页,如图13所示:
图12
图13
点击这里,即可显示用户列表,如图14所示:
图14
注:至此,struts2的搭建就算是完成了,在这个过程中不难看出struts2的执行原理:
- 客户端通过浏览器填写URL,发送一个请求到服务器端(Tomcat)
- 根据web.xml配置,该请求被FilterDispatcher接收
- 根据struts.xml配置,通过URL,匹配namespace和action name,这里的URL是http://localhost:8080/SSH/user,namespace 为“/”,action name为“user”,找到需要调用的action类UserAction.java和方法(默认执行方法execute()), 并通过IoC(控制反转,以后讲到spring会讲到)方式,将值注入给Aciton
- Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证(本程序没有给出,可以参照其他博客进一步了解Struts的功能)
- Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面
- 将最后的结果返回,即通过HTTP协议响应到客户端浏览器