目录
1. J2EE简介 2. JAVA EE应用的分层模型 3. 搭建Struts2 Demo应用 4. struts2流程 5. struts2的常规配置 6. 实现Action 7. 配置Action 8. 配置处理结果 9. 配置struts2的异常处理 10. convention插件与"约定"支持 11. 使用struts2的国际化 12. 使用struts2的标签库
1. J2EE简介
0x1: JavaBeans
JavaBeans是Java语言中可以重复使用的软件组件,它们是一种特殊的Java类,将很多的对象封装到了一个对象(bean)中。特点是
1. 可序列化 2. 提供无参构造器 3. 提供getter方法和setter方法访问对象的属性 4. Bean可以控制它的属性、事件和方法是否暴露给其他程序 5. Bean可以接收来自其他对象的事件,也可以产生事件给其他对象 6. 有软件可用来配置Bean 7. Bean的属性可以被序列化,以供日后重用
javabeans从本质上来讲是一个规范性的概念,要成为JavaBean类,则必须遵循关于命名、构造器、方法的特定规范。有了这些规范,才能有可以使用、复用、替代和连接JavaBeans的工具。反过来说,如果一个java类满足了这些规范,就可以称之为javabeans
package player; public class PersonBean implements java.io.Serializable { /** * name 属性(注意大小写) */ private String name = null; private boolean deceased = false; /** 无参构造器(没有参数) */ public PersonBean() { } /** * name 属性的Getter方法 */ public String getName() { return name; } /** * name 属性的Setter方法 * @param value */ public void setName(final String value) { name = value; } /** * deceased 属性的Getter方法 * 布尔型属性的Getter方法的不同形式(这里使用了is而非get) */ public boolean isDeceased() { return deceased; } /** * deceased 属性的Setter方法 * @param value */ public void setDeceased(final boolean value) { deceased = value; } }
TestPersonBean.java:
import player.PersonBean; /** * <code>TestPersonBean</code>类 */ public class TestPersonBean { /** * PersonBean 类测试方法的main函数 * @param ARGS */ public static void main(String[] args) { PersonBean person = new PersonBean(); person.setName("张三"); person.setDeceased(false); // 输出: "张三[活着]" System.out.print(person.getName()); System.out.println(person.isDeceased() ? " [已故]" : " [活着]"); } }
testPersonBean.jsp
<% // 在JSP中使用PersonBean类 %> <jsp:useBean id="person" class="player.PersonBean" scope="page"/> <jsp:setProperty name="person" property="*"/> <html> <body> 姓名:<jsp:getProperty name="person" property="name"/><br/> 已故与否?<jsp:getProperty name="person" property="deceased"/><br/> <br/> <form name="beanTest" method="POST" action="testPersonBean.jsp"> 输入姓名:<input type="text" name="name" size="50"><br/> 选择选项: <select name="deceased"> <option value="false">活着</option> <option value="true">已故</option> </select> <input type="submit" value="测试这个JavaBean"> </form> </body> </html>
虽然JavaBean和Java之间已经有了明确的界限,但是在某些方面JavaBean和Java之间仍然存在很容易混淆的地方,比如说重用,Java语言也可以为用户创建可重用的对象,但它没有管理这些对象相互作用的规则或标准,用户可以使用在Java中预先建立好的对象,但这必须具有对象在代码层次上的接口的丰富知识。而对于JavaBean,用户可以在应用程序构造器工具中使用各种JavaBean组件,而不需要编写任何代码。这种同时使用多个组件而不考虑其初始化情况的功能是对当前Java模型的重要扩展,所以也可以说JavaBean是在组件技术上对Java语言的扩展
如果真的要明确的定义,那么JavaBean的定义是:JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作
Relevant Link:
http://zh.wikipedia.org/wiki/JavaBeans http://eduunix.ccut.edu.cn/index2/edu/%C7%E5%BB%AA%B4%F3%D1%A7%BC%C6%CB%E3%BB%FA%BF%CE%B3%CC/JAVA%B1%E0%B3%CC%D3%EF%D1%D4/text/ch09/se01/9_1_2.htm
0x2: POJO(pure old java object)
关于POJO,我们首先明确一句话
A JavaBean is a POJO that is serializable, has a no-argument constructor, and allows access to properties using getter and setter methods that follow a simple naming convention.
POJO(pure old java object)是普通java类,有一些private的参数作为对象的属性,然后针对每一个参数定义get和set方法访问的接口。仅此而已,不能有别的更多的动作了
POJO其实是比javabean更纯净的简单类或接口。POJO严格地遵守简单对象的概念,而一些JavaBean中往往会封装一些简单逻辑。
JavaBean是一种JAVA语言写成的可重用组件。它的方法命名,构造及行为必须符合特定的约定:
1.这个类必须有一个公共的缺省构造函数 2.这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范 3.这个类应是可序列化的
简而言之,当一个POJO可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,它就是一个JavaBean
Relevant Link:
http://en.wikipedia.org/wiki/Plain_Old_Java_Object http://my.oschina.net/pacoyang/blog/151695
0x3: SSH与EJB区别
EJB是一种javabean的组合规范,SSH是3个框架jar包的组合。
EJB本身是JavaEE的规范由容器厂商负责实现,也就是使用EJB,需要使用JavaEE服务器。而用SSH,直接用Web服务器, SSH中要解决的目标和EJB是一致的。EJB是大型的,SSH是轻量级的。
Relevant Link:
http://blog.csdn.net/jojo52013145/article/details/5783677
2. JAVA EE应用的分层模型
0x1: Struts 2简介
Struts 2由传统的Struts 1、webwork两个经典MVC框架发展起来,与传统的Struts 1相比
1. Struts 2允许使用普通的、传统的java对象作为action 2. action的execute()方法不再与servlet api耦合,因而更易测试 3. 支持更多的视图技术 4. 基于AOP(Aspect-Oriented Programming)思想的拦截器机制,提供了更好的可扩展性 5. 更强大、更易用的输入校验功能 6. 整合的ajax支持 ...
0x2: MVC简介
MVC思想将一个应用分成三个基本部分,这三个部分以最小的耦合协同工作,从而提高应用的可扩展性及可维护性
1. Model(模型) 2. View(视图) 3. Controller(控制器)
在经典的MVC模式中,事件由控制器处理,控制器根据事件的类型改变模型或视图,每个模型对应一系列的视图列表,这种对应关系通常采用注册来完成,即:把多个视图注册到同一个模型,当模型发生改变时,模型向所有注册过的视图发送通知,接下来,视图从对应的模型中获得信息,然后完成视图显示的更新
概括起来,MVC有如下特点
1. 多个视图可以对应同一个模型,可以减少代码的复制及代码的维护量,一旦模型发生改变,也易于维护 2. 模型返回的数据与显示逻辑分离。模型数据可以应用任何的显示技术 1) JSP页面 2) Velocity模版 3) Excel文档 3. 应用被分隔为三层,降低了各层之间的耦合,提供了应用的可扩展性 4. 控制层的概念也很有效,由于它把不同的模型和不同的视图组合在一起,完成不同的请求。因此,控制层可以说是包含了用户请求权限的概念 5. MVC更符合软件工程化管理的思想。不同的层各司其职,每一层的组件具有相同的特征,有利于通过工程化和工具化产生管理程序代码
MVC思想将应用中各组件按功能进行分类,不同的组件使用不同技术充当,甚至推荐了严格分层,不同组件被严格限制在其所在层内,各层之间以松耦合的方式组织在一起,从而提供了良好的封装
0x3: Domain Object(领域对象)
此层由系列的POJO(Plain Old Java Object,普通的、传统的Java对象)组成,这些对象是该系统的Domain Object,往往包含了各自所需要实现的业务逻辑方法
0x4: DAO(Data Acess Object 数据访问对象)
此层由系列的DAO组件组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。
在经典Java EE应用中,DAO层也被改称为EAO层,EAO层组件的作用与DAO层组件的作用基本相似。只是EAO层主要完成对实体(Entity)的CRUD操作,因此简称为EAO层
0x5: PO(persistant object 持久对象)
持久对象,可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作.
0x6: VO(value object 值对象)
通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要。
0x7: DTO(data access object 数据访问对象)
此对象用于访问数据库。通常和PO结合使用,DAO中包含了各种数据库的操作方法。通过它的方法,结合PO对数据库进行相关的操作
我们通过DAO将POJO持久化为PO,用PO组装出来VO、DTO
0x8: BO(business object 业务对象)
封装业务逻辑的java对象,通过调用DAO方法,结合PO、VO进行业务操作
Relevant Link:
http://www.oecp.cn/hi/yongtree/blog/122 http://blog.sina.com.cn/s/blog_9af0d32b0101030l.html http://my.oschina.net/pacoyang/blog/151695 http://www.cnblogs.com/xiaoluojava/archive/2010/05/07/1729992.html
3. 搭建Struts2 Demo应用
0x1: 创建web应用
为了让web应用具有struts 2支持功能,必须将struts 2框架的核心类库(JAR包)增加到web应用中
/HelloWorldStruts2/WebContent/WEB-INF/lib
commons-fileupload-1.3.1.jar commons-io-2.2.jar commons-lang-2.4.jar commons-lang3-3.2.jar commons-logging-1.1.3.jar commons-logging-api-1.1.jar freemarker-2.3.22.jar javassist-3.11.0.GA.jar ognl-3.0.6.jar struts2-core-2.3.24.jar xwork-core-2.3.24.jar
0x2: web.xml
通常,所有的MVC框架都需要Web应用加载一个核心控制器,对于Struts2框架而言,需要加载FilterDispatcher,只要Web应用负责加载FilterDispatcher,FilterDispatcher将会加载Struts2框架,因为Struts2将核心控制器设计成Filter,而不是一个普通Servlet。故为了让Web应用加载FilterDispatcher,只需要在web.xml文件中配置FilterDispatcher即可
/HelloWorldStruts2/WebContent/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Struts 2</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterorg.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
从本质上讲,struts2并不是一个新的东西,struts2是基于J2EE框架上的一层封装,使开发者更容易地进行J2EE的开发,struts2是一个MVC开发框架,从逻辑上位于spring、hibernate的上层
我们知道,以上配置仅仅修改了web.xml文件仅仅完成了为web应用增加struts2支持,而struts2是基于过滤器实现的,要使用strucs2功能至少还需要一个struts.xml文件
0x3: struts.xml
/HelloWorldStruts2/WebContent/WEB-INF/classes/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> <constant name="struts.devMode" value="true" /> <package name="helloworld" extends="struts-default"> <action name="hello" class="com.tutorialspoint.struts2.HelloWorldAction" method="execute"> <result name="success">/HelloWorld.jsp</result> </action> </package> </struts>
0x4: index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Hello World</title> </head> <body> <h1>Hello World From Struts2</h1> <form action="hello"> <label for="name">Please enter your name</label><br/> <input type="text" name="name"/> <input type="submit" value="Say Hello"/> </form> </body> </html>
J2EE struts2采用了充分的面向对向、封装、解耦的设计,将后端的处理逻辑全部放到了javabeans实现,而将前台的展示由JSP实现,JSP和javabeans之间的纽带通过action实现,所有的用于处理后端业务逻辑的javabeans都继承了ActionSupport类
/HelloWorldStruts2/src/com.tutorialspoint.struts2
package com.tutorialspoint.struts2; public class HelloWorldAction { private String name; public String execute() throws Exception { return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
0x5: HelloWorld.jsp
如果execute方法返回"success", 然后我们把用户引到HelloWorld.jsp
/HelloWorldStruts2/WebContent/HelloWorld.jsp
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> Hello World, <s:property value="name"/> </body> </html>
Relevant Link:
http://www.yiibai.com/struts2/struts2_examples.html http://blog.csdn.net/xiazdong/article/details/7214967 http://www.360doc.com/content/11/0519/08/987036_117818681.shtml
4. struts2流程
0x1: struts2应用开发步骤
梳理一下struts2应用的开发步骤
1. 在web.xml文件中定义核心filter来拦截用户请求 由于web应用是基于请求/响应架构的应用,所以不管哪个MVC web框架,都需要在web.xml中配置该框架的核心filter或servlet,这样才可以让框架介入web应用中 /* <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterorg.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> */ 2. 如果需要以POST方式提交请求,则定义包含表单数据的JSP页面,如果仅仅只是以GET方式发送请求,则无须经过这一步 3. 定义处理用户请求的Action类 这一步是所有MVC框架中必不可少的,因为这个Actino就是MVC中的C,即控制层,该控制器负责调用Model里的方法来处理请求 /* MVC框架的底层机制是,核心servlet或filter接收到用户请求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Action实例,并调用Action的指定方法来处理用户请求,这就产生了一个问题: 当servlet或filter拦截用户请求后,它应该如何知道创建哪个Action的实例 1) 利用配置文件 2) 利用约定 */ 4. 我们知道,在MVC框架中,控制器实际上由2个部分共同组成 1) 即拦截所有用户请求,处理请求的通用代码都由核心控制器完成 2) 实际的业务控制(诸如调用model,返回处理结果等),则由Action处理 5. 配置Action 对于java领域的大部分MVC框架而言,都经常使用XML文件来配置管理,配置Action就是指定哪个请求对应哪个Action进行处理,从而让核心控制器根据该配置来创建合适的Action实例,并调用该Action的业务控制方法,例如 /* <action name="hello" class="com.tutorialspoint.struts2.HelloWorldAction" method="execute"> <result name="success">/HelloWorld.jsp</result> </action> 指定了如果用户请求URL为login,则使用com.tutorialspoint.struts2.HelloWorldAction来处理,值得注意的是,struts2的convention插件借鉴了Rails框架的优点,开始支持"约定优于配置"的思想,也就是采用约定方式来规定用户请求地址和Action之间的对应关系 */ 6. 配置处理结果和物理视图资源之间的对应关系 当Action处理用户请求结束后,通常会返回一个处理结果(简单字符串),我们可以认为该名称是逻辑视图名,这个逻辑视图名需要和指定物理视图进行关联 /* <action name="hello" class="com.tutorialspoint.struts2.HelloWorldAction" method="execute"> <result name="success">/welcome.jsp</result> <result name="input">/login.jsp</result> <result name="error">/error.jsp</result> </action> */ 7. 编写视图资源,如果Action需要把一些数据传给视图资源,则可以借助于OGNL表达式
0x2: struts2的流程