课程地位
就业技能结构图
本门课程目标
课程项目展示
· “房屋出租系统”演示
·
相关课程回顾
预习检查
· 根据你的理解,谈谈什么是框架?
· 框架能给我们带来什么好处?
· 举两个框架的例子。
本章任务
本章目标
· 知道使用框架技术的好处
· 掌握MVC控制器实现原理
· 了解常用Java框架的应用优势
为什么需要框架技术
· “框架技术”帮我们更快更好地构建程序:
· 是一个应用程序的半成品
· 提供可重用的公共结构
· 按一定规则组织的一组组件
· 优势:
· 不用再考虑公共问题
· 专心在业务实现上
· 结构统一,易于学习、维护
· 新手也可写出好程序
概念辨析
· 技术、组件、框架和系统
Java流行框架
· 大名鼎鼎的SSH
回顾:三层结构
三层结构在Java中的应用
课程安排
回顾:MVC设计模式
自定义MVC框架
· 问题:实现自定义MVC框架
· 目的:
· 规范Java Web应用开发
· 实现MVC模式(保证视图与模型分离)
· 实现:
· 结构、控制流程与核心组件(Action和Controller)
实现加法器
使用框架的优点
· 这个框架给开发带来了什么好处?
· JSP页面中没有业务逻辑代码,业务和展示彻底分开
· 用户操作抽象成了Action,程序逻辑更清晰
· 整个系统通过统一的入口(Controller Servlet)访问
基于框架开发
· 如何基于这个框架开发用户登录功能?
· 需求描述:
· 输入用户名为“aptech”,密码为“accp5.0”则登录成功;
否则登录失败
· 登录成功转发到my.jsp,登录失败返回index.jsp继续登录
基于框架开发:开发登录功能
这个框架还可以怎样改进?
· 自定义MVC框架的缺点
· 在增加功能时,需要修改Controller Servlet
· AddAction.java 的execute方法中直接引用页面物理路径, 修改页面文件名时需要修改代码
· Struts是一个成熟的MVC实现
· 第一个开源的Java Web框架
· Java Web框架的事实标准
· 利于快速开发稳健的Web应用
总结
· 什么是框架?
· 使用框架有什么好处?
· 什么是MVC模式?
· 使用MVC模式有什么好处?
· 在Java Web开发中,MVC模式中M、V、C都是如何实现的?
· 如何基于自定义MVC框架实现“查询所有用户” 的功能?
1. 下载使用Struts2
下载地址:
2.导入包,一般通过增加User library实现。
右键项目名--->propertise--->User librarys--->Userlibrarys--->New--->AddJARs 如果要导出就选export,下次直接import
也可以放在web-inf中,可以跟项目,但是不能以列表的形式保存。
现在需要的是八个包。commons-io-2.0.1.jar,commons-lang-2.5.jar,commons-fileupload-1.2.2.jar,javassist-3.11.0.GA.jar,ognl-3.0.1.jar,struts-core-1.3.10.jar,xwork-core-2.2.3.jar,freemarker-2.3.16.jar
3.过滤器
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
特别注意复制绝对路径的时候要去掉文件类型
filter>
<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
4.导入struts标签库
<%@ taglib uri="/struts-tags" prefix="s" %>
对应struts-core-1.3.10.jar中的META-INF中的struts-tags.tld的URL
5.struts框架配置文件,文件名struts.xml,如果要引用是使用classes下的,但是src目录下的文件会产生一模一样的文件到classes,所以也可以直接放到src目录下
配置文件命名mess_en_US.properties,mess_zh_CN.properties,中间是字符编码,例如_zh_CN是中文,浏览器的字符编码进行效果查看。
<struts>
//使用配置文件,value和配置文件的前缀对应。name是强制规定的struts.custom.i18n.resources
<constant name="struts.custom.i18n.resources" value="mess">constant>
//pageage只是做区分的,可以随便命名,大项目可以有多个package,名字不可以一样。namespcae是命名空间,也就是前缀。最好继承struts-default
<package name="default" namespace="/abc" extends="struts-default">
//name是servlet名字,class是完整的包名加类名,可以有多个action处理请求。
<action name="login" class="action.LoginAction">
//对应servlet中execute中的返回值。默认是request方式,如果要responce方式,就要把类型改成redirect
<result name="succ">/succ.jspresult>
<result name="fail" type="redirect">/fail.jspresult>
action>
package>
struts>
6.在struts框架下写类
页面有几个参数需要接收就设几个属性。一般要继承ActionSupport类,重写execute方法,如果不用继承就直接写execute方法。默认是对request对象进行操作。el表达式中的${message }!等价于${requestScope.message }!
7.使用简单的struts标签
产生表单
//action和配置文件的actionname一至,如果package中的namespace不是所有路径,还要加上namespace
<s:form action="/login">
//文本框,name是控件名,key是配置文件中的key。
<s:textfield name="loginname" key="uname">s:textfield>
<s:password name="loginpass" key="upass">s:password>
<s:submit key="btn">s:submit>
s:form>
//输出标签,对应配置文件中的key,二进制输出。
<s:property value="%{getText('logintitle')}"/>
//只能在request中才可以,读取serlvet属性。
<s:property value="loginname"/>
8.增加提示信息
windows--->properties--->搜索栏输入catalog--->add
location对应struts-2.2.3\lib\struts2-core-2.2.3下的struts-2.1.7.dtd,例如E:\createprogram\struts-2.2.3\lib\struts2-core-2.2.3\struts-2.1.7.dtd
key type是uri
key是struts中的http://struts.apache.org/dtds/struts-2.1.7.dtd
DOCTYPE struts PUBLIC
"-//ApacheSoftware Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
9新建struts.xml文件。
右键src--->New--->XML(Advanced)--->去掉x-body标签
也可直接建file文件,后缀xml
一、 回顾MVC设计模式
二、 下载使用Struts2
a) 下载地址:
b) 了解文件结构:
i. apps:示例应用
ii. docs:API相关文档
iii. lib:核心类库
iv. src:源代码
c) 在项目中配置Struts2
i. 复制jar文件 commons-io ,commons-fileupload , commons-lang , javassist , core , freemarker , xwork
ii. 配置web.xml (配置核心过滤器)
三、 简单登录处理
i. jsp页面使用struts2标签结合资源文件
ii. 配置struts.xml (资源文件常量)
iii. 创建LoginAction类
四、 Struts2执行流程
五、 Struts2常量配置
a) 参考struts.properties文件
六、 实现Action
a) 编写一个普通Java类,定义属性用于封装HTTP请求中的参数(get/set)
b) 编写请求执行方法 execute
c) 了解Action接口和ActionSupport基类
d) Action访问ServletAPI
i. 使用ActionContext类:常用方法 put,get/setApplication, 静态getContext, getParameters, get/setSession,
ii. 使用ServletActionContext工具类:常用方法getPageContex, getRequest, getResponse, getServletContext
e) 配置Action
i. package :name,extends,namespace
ii. action : name,class,result子节点
目录
处理action请求: 1
普通Action请求: 1
DMI(Dynamic Method Invocation),动态方法调用 2
指定method属性及使用通配符 3
配置处理结果 9
普通配置Action视图资源 9
Action属性值决定物理视图资源 9
使用Struts2标签 10
控制标签 10
if/else if/else标签 10
iterator标签 11
append标签 13
generator标签 14
merge标签 15
subset标签 16
表单标签 17
checkboxlist标签 17
doubleSelect标签 18
optiontransferselect标签 21
select标签 22
radio标签 22
非表单标签 23
actionerror/actionmessage标签 23
处理action请求:
普通Action请求:
*****
当某个包指定了命名空间后,该包下所有的Action处理的URL应该是命名空间+Action名。
如果请求为/barspace/bar.action,系统首先查找/barspace命名空间里名为bar的Action,如果在该命名空间里找到对应的Action,则使用该Action处理用户请求:否则,系统将默认命名空间中查找名为bar的Action,如果找到对应的Action,则使用该Action处理用户请求;如果两个命名空间里都找不到bar的Action,则系统出现错误。
*****
PS:namespace=”/” 代表根命名空间,并不代表默认命名空间, 不配置或配置成namespace=”” 则代表默认命名空间。
DMI(Dynamic Method Invocation),动态方法调用
动态方法调用是指表单元素的action并不是直接等于某个Action的名字,而是以如下形式来指定表单的action属性
action = “ActionName!methodName”
//该路径指向namespace为/zhaojing Action名为login 方法名为doLogin
PS:使用动态方法调用前必须设置Struts2允许动态方法调用,开启系统的动态方法调用是通过设置struts.enable.DynamicMethodInvocation常量完成的,设置该常量的值为true,将开启动态方法调用。(默认为true)
指定method属性及使用通配符
如果在配置
struts.xml
页面配置:
function doSubmit(url){
var f=document.forms[0];
f.action =f.action+url;
}
*****
为了解决action定义冗余问题,struts2还允许使用通配符的方式。
在配置
*****
struts.xml :
页面:
functiondoSubmit(url,tag){
var f=document.forms[0];
f.action =f.action+url+"_"+tag;
}
除以上之外,当
struts.xml配置:
页面配置:
function doSubmit(url,tag){
var f=document.forms[0];
f.action =f.action+url+"Action_"+tag;
}
PS:如第二个*代表要执行的方法,如参数值为空则执行execute方法,否则执行与值同名的相对应方法
实际上,Struts2不仅允许在class属性、name属性中使用表达式,还可以在
通过这种方式,可以避免让浏览者直接访问系统的jsp页面,而是让struts2框架来管理所有用户请求。
*****
当用户请求匹配多个Action时,请求的处理。
假设有URL为abcAction.action的请求,在struts.xml文件中配置了如下三个Action,它们的Action值分别为:abcAction,*Action和*,则这个请求将被名为abcAction的Action处理。
如有defAction.action的请求,同样配置的三个action是abcAction,*Action和*,则这个请求显然不会被name为abcAction的Action处理,剩下的匹配的*Action和*,哪一个action配置在前则由哪一个action处理用户请求。
*****
PS:因为除非请求的URL与Action的name属性绝对相同,否则将按先后顺序来决定由哪个Action来处理用户请求。因此,我们应该将name=”*”的Action配置在最后,否则Struts2将使用该Action来处理所有请求。
配置处理结果
普通配置Action视图资源
//如方法返回值为login则进入/login.jsp(重定向),返回 hello 则进入/index.jsp页面(转发)
//如没有指定任何name属性值,则name属性采用默认值:success;系统会将
Action属性值决定物理视图资源
对于上面表达式的语法,要求在对应的Action实例里应该包含uname属性,否则${uname}表达式值为null.
上面配置要求Action中属性user并且user中包含有属性uname
使用Struts2标签
控制标签
Struts2的非UI标签包括控制标签和数据标签,主要用于完成流程控制。控制标签可以完成流程控制,如分支、循环等。
控制标签:
if 、elseIf/elseif 、else 、append 、generator 、iterator 、merge 、sort 、subset
if/else if/else标签
这三个标签都是用于进行分支控制的,它们都用于根据一个boolean表达式的值,来决定是否计算、输出标签体的内容
老年人
中年人
青年人
少年
iterator标签
主要用于对集合进行迭代,这里的集合包含List,Set和数组,也可以对Map集合进行迭代输出。
status="i"> 当前下标为 : ${i.index}
PS:status属性每次迭代时都会有一个IteratorStatus实例,该实例包含如下几个方法。
int getCount();返回当前迭代了几个元素
int getIndex();返回当前迭代元素的索引
Boolean isEven();返回当前元素顺序是否是偶数
Boolean isFirst();返回当前元素是否是第一个元素
Boolean isLast();返回当前元素是否是最后一个元素
Boolean isOdd();返回当前元素顺序是否是奇数
*****
status="i"> color="red">
通过status的方法来控制样式显示
*****
append标签
append标签用于将多个对象集合拼接起来,组成一个新的集合。
status="i"> color="red"> ***** append标签不仅能将多个list拼接起来,也能将map与list进行拼接 status="i"> color="red"> Key: generator标签 使用generator标签可以将指定字符串按分隔分隔成多个子串,临时生成的子串数据可以用iterator标签进行输出。类似于String对象的split()方法 但此种写法generator标签一结束,集合将不可用.但可以通过定义var属性或id属性来保存集合 : 定义成var 可将集合设置成request范围内的属性。 count 设置集合可保留几个元素 merge标签 类似于append标签,也是用于将多个集合拼接成一个集合,但它采用的方式与append有所区别。 如有三个集合元素,分别使用append和merge方式进行拼接,产生的新集合顺序为: 使用append 集合 1 元素 1 集合 1 元素 2 集合 2 元素 1 集合 2 元素 2 集合 3 元素 1 集合 3 元素 2 使用merge 集合 1 元素 1 集合 2 元素 1 集合 3 元素 1 集合 1 元素 2 集合 2 元素 2 集合 3 元素 2 subset标签 subset标签用于取得集合的子集。 从下标1开始取元素,取2个长度。页面输出的结果为spring hibernate 表单标签 checkboxlist标签 可以一次创建多个复选框,用于同时生成多个的HTML标签。它根据list属性指定的集合来生成多个复选框,因为,使用该标签需指定一个list属性。还有两个常用属性listKey(做为复选框的value) listValue(属性做为复选框的标签) labelposition="top"list="{'Hello','SSH'}"> list="#{'疯狂的java讲义':'2008年9月','轻量级javaEE企业应用实战':'2010年8月'}" listKey="key"listValue="value" > labelposition="top" listKey="author"listValue="bookName"> doubleSelect标签 会生成一个级联列表框(生成两个下拉列表框),当选择第一个的下拉列表时,第二个下拉列表框的内容会随之改变 常用属性:list,listKey,listValue ;doubleList,doubleListKey,doubleListValue,doubleName doubleList="top== '李刚'?{'struts2指南','轻量级JavaEE应用'}:{'javaScript'}" list="{'李刚','David'}"doubleName="book"> PS:使用doubleselect标签时,必须放在 ***** 在默认情况下,第一个下拉列表只支持两项,如果第一个下拉列表框包含三个或更多的值,这里的list和doubleList属性值便不能这样设定 list="#bs.keySet()" doubleName="book"> 实现从数据库读取QX、JD数据的动态级联 配置一个匹配的Action[将qx和jd读取保存到集合] public String execute() { BookService bs = newBookService(); Map List ServletActionContext.getRequest().setAttribute("qxlist",qxlist); for (Qx qx : qxlist) { jdmap.put(qx.getQxid(),bs.getJdByQxid(qx.getQxid())); } ServletActionContext.getRequest().setAttribute("jdmap",jdmap); return"success"; } 页面显示:[top指第一个下拉列表项] list="#request.qxlist"listKey="qxid" listValue="qx" doubleName="jds"doubleListKey="jdid"doubleListValue="jd"> optiontransferselect标签 生成两个列表选择框,并生成系列的按钮用于控制各选项在两个下拉列表之间的移动。 常用属性:addAllToLeftLable ; addAllToRightLable ; addToLeftLable ; addToRightLable ;allowAddAllToLeft ; allAddAllToRight ; allowAddToLeft ; allowAddToRight ;leftTitle ; rightTitle ; allowselectAll ; selectAllLabel ; doubleList ;doubleListKey ; doubleName ; doubleValue ; doubleMultiple ; list ; listKey ;listValue ; name ; value ; multiple list="#bs.booksLeft"doubleName="fb" addAllToLeftLabel="全部左移" addAllToRightLabel="全部右移" allowAddAllToLeft="true"allowAddAllToRight="true" allowAddToLeft="true"allowAddToRight="true" addToLeftLabel="<==" addToRightLabel="==>"listKey="author" listValue="bookName" doubleListKey="author"doubleListValue="bookName"> select标签 用于生成一个下拉列表框,使用该标签必须指定list属性,系统会使用list属性指定的集合来生成下拉列表框的选项。这个list属性指定的集合,既可以是普通集合,也可以是Map集合,还可以是元素对象集合。 listKey="author"listValue="bookName" label="选择图书"> radio标签 与checkboxlist标签的用法几乎完全相同,唯一不同的是checkboxlist生成多个复选框,而radio生成多个单选框 label="选择图书"labelposition="top" name="books" value="'李刚'"> 非表单标签 actionerror/actionmessage标签 这两个标签用法完全一样,作用也几乎完全一样,都是负责输出Action实例里封装的信息:区别是actionerror标签负责输出Action实例的getActionErrors()方法的返回值,而actionmessage标签负责输出getActionMessage()方法的返回值。 action中的配置 super.addActionError("第一个错误信息"); super.addActionError("第二个错误信息"); super.addActionMessage("第一个信息"); super.addActionMessage("第二个信息"); 页面: 显示效果: • 第一个错误信息 • 第二个错误信息 o 第一个信息 o 第二个信息