就业班_JavaEE_day36_38_struts2
一框架概述
半成品、少写代码、提高效率、节约成本
常见框架: SSH SSM
二种开发方式:xml配置文件;注解(常用)
xml作用:
1 数据的存储(现在有数据库代替)
2 作为数据协议进行传输(xml/json)
3 作为配置文件
dtd xsd
二 开发流程
1 导包 可以从blank项目中进行拷贝
2 在web.xml中添加strutsprepareandexecutefilter
过滤器在服务器启动时就创建,并调用init方法,struts中的该过滤器主要用来加载struts自带的配置文件和struts.xml核心配置文件。
3 创建action 有三种方式
A 普通类 public String execute() {}
B 实现Action接口 并实现接口中的execute方法
C 继承ActionSupport类
【通常采用第三种方式】。 action中不指定method,默认访问execute方法。actionsupport的execute默认返回success
4 在struts.xml中配置action
structs2 核心配置文件 struts.xml 放在src下 该文件的名称和位置固定。
action有三种配置方法
A method
<action name="action名字 ,自定义" class="action类全路径" method="action中的方法名">
该方式的缺点是:action类中的方法过多时,将配置多个action。一个方法对应一个action配置
B 通配符 * 【通常采用该方式】
eg: <action name="customer_*" class="action类全路径" method="{1}">
*代表任意,上述写法能匹配任意以customer_开头的访问路径 meithod中{1} 表示占位符,1表示第一个* 。 * 可以写多个,对应method中占位符可以有多个。
C 动态方法
该方法了解,一般不使用。user!add useraction中的add方法
<struct>
<package name="包名称,自定义,要唯一" extends="struts-default" namespace="/"> // extends中的内容固定
<global-result> //全局result
<action name="action名字 ,自定义" class="action类全路径" method="">
<result name="aciton中方法的返回值" type="默认是转发,可以配置为重定向">XXX中间写转发或者重定向的路径</result>
</action>
</package>
</struct>
补充:可以通过在struts.xml中通过include 其它的xml,来实现分模块开发。
package中namesapce不写默认是"",表示任意路径下都可以访问action。如果要配置namespace的话,必须以/开头。
可以配置为/ 或者 /xxx 或者/xxx/yyy 通常package的name和namespace都用模块名来定义。
三 Action中的result配置
1 全局result <globe></globe>中定义result ,需要注意全局的范围只在一个package中有效。
2 局部result 写在action中的就是局部result 如果有同name的,以局部的为准
3 result type 属性 默认是dispatcher 可以配置成redirect
dispatcher 和 redirect 都是针对转发或者重定向到jsp页面
如果是要转发和重定向到action 则使用chain 和 redirectAction 。其中chain不常用。
CTRL + F5 无缓存刷新
四 Action中如何封装表单数据到实体类中
1 原始封装 通过servletActionContext获取到request 一个一个属性进行获取和赋值
2 struts提供了二种封装表单的方式
A 属性封装
1)在action中定义与表单中同名的成员属性,并提供getset方法。
2)在action类中申明实体类,并提供getset方法。 在form表单中 <input type="text" name="user.username"> 对name属性进行表达式定义
B 模型驱动封装 action类通过实现modeldriven接口实现 【通常采用这种方式】。eg:
DemoAction implements ModelDriven {
User form = new User();
public User getModel(){
return form;
}
}
补充:
属性封装和模型驱动封装针对同一表单不能同时使用,如果同时使用,则只有模型驱动封装有效。但是对于不同的表单,可以同时使用。
模型封装和属性封装的区别:
模型封装只能封装一个实体bean,因为实体bean类型在ModelDriven接口泛型中已规定
而表达式封装可以封装多个实体bean 。通过在form中name属性的表达式指向不同的实体bean <input type="text" name="book.bname">
五 Action中的常见API
1 ActionContext 通常通过ActionContext.getContext().getValueStack()来获取值栈
2 ServletActionContext
getRequest() 可以得到HttpServletRequest
有了request就可以得到HttpSession
getServletContext() 可以得到ServletContext
3 接口注入 ServletRequestAware 可以通过该方式获取到request
六 值栈和OGNL
作用: 值栈用来存值,OGNL结合struts标签来取值。
值栈数据结构:
可以通过<s:debug> 来查看 ,主要包含root(root是对象栈)和context(context是一个map),通常我们使用root来存取值。
root对应于ognl中的根 , context对应Ognl中的非根。所以取root中的值不用加#号 ,取context中的值需要加#号
OGNL语法:
# 表示从context中取值
%{} 用于struts的表单标签中,从值栈中取值,%{}
${} 用于在配置文件比如struts.xml中从valuestack中取值。
一个request对应一个action,对应一个actioncontext,对应一个valuestack,action是多实例 。
valuestack保存在request域对象中,所以只能在转发中使用。
如何向值栈中存值 ,有如下三种方式:
1 通过ActionContext 获取到ValueStack对象,然后调用valuestack的set方法设置。 会在栈顶上开辟一个Map 【通常采用这种方式】,因为有key值。
2 通过ActionContext 获取到ValueStack对象,然后调用valuestack的push方法设置。会在栈顶上开辟一个List
3 通过在action中定义一个成员变量,并提供该成员变量的get方法,在action类中的方法中对成员变量赋值,则将值添加进值栈,并且不会在栈顶开辟新空间,
而是将值放在栈顶的action引用。
如何从值栈中取值:
先在jsp中引入struts标签 <%@ taglib uri="/struts-" prefix="s" %>
然后通过<s:property value="OGNL"> 来获取值。
1 取一个字符串
<s:property value="字符串变量的名称"/> eg <s:property value="username"/>
2 取一个对象
<s:property value="成员变量的名称"/> eg <s:property value="user.username"/> <s:property value="user.password"/>
3 取一个list
有三种取法
A <s:property value="list[0].username" /> <s:property value="list[0].password" />
这种方法的前提是你要知道遍历的list个长度。通常不使用。
B <s:iterator value="list">
<s:property value="username"/> <s:property value="password"/>
</s:iterator>
这种方法类似与jstl的foreach标签,但是比jstl的foreach少 var属性
C <s:iterator value="list" var="user">【通常采用该方式】
<s:property value="#user.username"/> <s:property value="#user.password"/>
</s:iterator>
#表示从context中取值,因为加了var之后,struts会将user变量临时存放在context的map中,对context的取值需要用#。
补充:
EL表达式也可以从值栈中取值,因为struts对HttpServletRequest中的getAttribute方法做了增强,当从域对象中取不到值时,会从值栈中取值,并放回域对象中。
这样el表达式就能从域中取到值。
七 struts2-拦截器
1 拦截器的概念只在struts中存在。它封装了很多功能,struts2中定义了很多拦截器,有一组默认拦截器定义。在struts-default.xml中定义。
拦截器在action对象创建之后,在执行方法之前,执行。
拦截器和过滤器的区别:
过滤器可以拦截任何资源
拦截器只能拦截action
2 拦截器底层原理
1 AOP思想 面向切面编程 不改源代码通过配置实现功能的增强 AOP通过动态代理实现。
2 责任链模式 类似web中过滤链 每个方法执行完成后,必须放行才能执行后续方法。
3 自定义拦截器
1 创建类继承MethodFilterInterceptor
2 重写MethodFilterInterceptor中的doIntercept方法
当满足某个条件是进行放行 return invocation.invoke() 相当于放行。doIntercept方法的返回值,与action中result的name对应。
3 注册拦截器,通过配置的方式将action和拦截器关联。
在action所在的package中配置拦截器
在action中引用
配置自定义拦截器后,struts2中的默认拦截器将失效,需要手动配置以下。
<package name="包名称,自定义" extends="struts-default" namespace="/"> // extends中的内容固定 namespace名称空间可以自定义一般写/
<!-- 自定义拦截器-->
<interceptors>
<interceptor name="自定义拦截器名称" class="拦截器的全路径"></interceptor>
</interceptors>
<action name="action名字 ,自定义" class="action类全路径" method="">
<!-- 在action中引用自定义拦截器-->
<interceptor-ref name="自定义拦截器名称"">
<param name="excludeMethods">action中不需要拦截的方法名称,如果有多个,用逗号进行隔开</param>//excludeMethods 这个名字固定
</interceptor-ref>
<!-- 在action手动配置下默认拦截器,使默认拦截器也起作用-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="aciton中方法的返回值" type="默认是转发,可以配置为重定向">XXX中间写转发或者重定向的路径</result>
</action>
<!-- 另外一种写法 设置缺省拦截器 只在当前package下有效-->
<interceptors>
<interceptor name="logininterceptor"
class="com.itheima.strtus2.web.interceptor.LoginInterceptor">
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="logininterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"></default-interceptor-ref>
</package>
<default-interceptor-ref name="myStack"></default-interceptor-ref>可以用来指定package中的action的默认拦截器
在action中不显示指定 <interceptor-ref > 则action会使用默认拦截器defaultStack。
4 可以通过配置不拦截action中某些方法,配置方法见上面action中的定义。
八 struts2配置文件加载顺序【面试】
1.default.properties(常量)
2.struts-default.xml(默认配置) 定义了默认package 默认interceptor 默认class actionsupprot actionsupport中默认execute方法 默认success返回值
3.struts-plugin(struts插件的配置)
4.struts.xml(自定义配置)
5.struts.properties(自定义常量,通常不用,而是在struts.xml中配置)
6.web.xml
九 struts业务流程
请求 request --》 strutsprepareandexecutefilter--》actionmapper--》proxyaction--》actioncontext(interceptor、action)--》interceptor--》action--》result--》interceprot--》response
十 文件上传
form表单 : method=post enctype=multipart/form-data <input type=file name=upload/>
action
File upload;
String uploadContentType;
String uploadFileName;
多文件
action
File[] upload;
String[] uploadContentType;
String[] uploadFileName;
配置文件上传默认大小限制;
配置文件上传类型或者后缀名限制;
<interceptor-ref name="defaultStack">
<!-- 允许的文件MIME类型 -->
<!-- <param name="allowedTypes">image/png,image/jpg</param> -->
<param name="fileUpload.allowedExtensions">chm</param>
</interceptor-ref>
十一 注解开发
导包struts2-convention-plugin-2.3.34.jar 在2.1版本后引入注解
@Namespace("/")
@ParentPackage("struts-default")
@Action(value = "user_login", results = {
@Result(name = "success", location = "/product.jsp"),
@Result(name = "error", location = "/login.jsp") })
插件包中对 action actions struts struts2 package 进行扫描注解。
十二 JSON扩展
fastjson 阿里 jackson 二个用的比较多的jsonjar包
通过JsonResult类来封装json返回值。
public class JsonResult<T> {
private int status;// json状态 1表示成功,0 表示失败
private List<T> list; // list表示内容
private String msg;// 消息描述
}
fastjson
1 fastjson中date 在属性上添加jsonfiled注解来设置样式 @JSONField(format="yyyy-MM-dd")
2 SerializeFilter filter = new PropertyFilter() {
//返回true表示不拦截,返回false表示拦截,不显示该属性。
@Override
public boolean apply(Object obj, String attr, Object value) {
//arg0 表示对象 arg1 表示属性名称 arg2 表示属性值
if(attr.equals("uid")){
return false;
}
return true;
}
};
3 JSONObject.toJSONString(user,filter)
4 JSONArray.toJSONString(集合)
jackson
1 在对象属性上添加jsonignore注解可以过滤掉该属性,不在json中出现。还可以通过编码实现。
2 设置jackson的data格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
3 ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(对象或者集合);
|