Struts2 核心技术简记

Struts2简述

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。

javaWeb中的三层架构 : 
表现层:MVC,struts2框架其实是对表现层的MVC作了优化 
控制层:service 

持久层:dao

Struts2 基本配置

导入基本包

Struts2中jar包有很多,但我们不需要导入全部只需要导入一些基本的即可。


配置web.xml
  <filter>
    <filter-name>action2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>action2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
配置核心配置文件struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
 "http://struts.apache.org/dtds/struts-2.5.dtd">
 <struts>
 	<constant name="struts.i18n.encoding" value="UTF-8"></constant>
 	<package name="demo" extends="struts-default" namespace="/">
 		<action name="loginAction" class="ynk.itcast.action.CheckAction">
 			<result name="success">/index.jsp</result>
 		</action>
 	</package>
 </struts>

package:可以为任意值

extends:固定struts-default,也可以继承自己写的包名

namespace:默认为/,可不写

配置文件中常用的常量
 struts.i18n.encoding:该常量指定struts2应用默认使用的字符集。 

            struts.objectFactory.spring.autoWire:和spring框架整合有关。 

            struts.multipart.parser:指定文件上传用的组件。默认为jakarta(即common-fileupload上传组件) 

            struts.multipart.saveDir:指定上传文件的临时保存路径  

            struts.multipart.maxSize:指定上传中整个请求所允许上传的最大字节数。 

            struts.action.extension:指定struts2需要处理的请求后缀。默认值为.action或者什么都不写 

            struts.serve.static.browserCache:设置浏览器是否缓存静态内容,当应用处于开发阶段时,我们希望不缓存,可设置为false  

            struts.enable.DynamicMethodInvocation:设置struts2是否支持动态方法调用,默认值为true 

            struts.devMode:设置struts2是否使用开发模式。如果设置为true,为开发模式,修改struts.xml配置文件不需要重启服务器,会显示更多更友好的错误提示。 

            struts.ui.theme:指定视图主题。 

            struts.url.includeParams:指定struts2生成url时是否包含请求参数。有none,get和all三个值。分别对应不包含,仅包含get类型请求参数和包含全部请求参数。 

常量修改

<constant name="struts.i18n.encoding" value="UTF-8"></constant>

result标签中的type属性

1.chain:用来处理Action链,被跳转的action中仍能获取上个页面的值,如request信息。
2.dispatcher:用来转向页面,通常处理JSP(默认)
3.freemaker:处理FreeMarker模板  
4.httpheader:控制特殊HTTP行为的结果类型    
5.stream:向浏览器发送InputSream对象,用来处理文件下载,还可用于返回AJAX数据
6.velocity :处理Velocity模板
7.xsl: 处理XML/XLST模板
8.plainText:显示原始文件内容,例如文件源代码   
9.plaintext:显示原始文件内容,例如文件源代码   
10.redirect:重定向到一个URL ,被跳转的页面中丢失传递的信息,如request   
11.redirectAction :重定向到一个Action ,跳转的页面中丢失传递的信息,如request   
Action的方法调用

创建Action只需要继承ActionSupport类即可

method属性调用
<action name="loginAction" class="ynk.itcast.action.CheckAction" method="Login">
     <result name="success">/index.jsp</result>
</action>

执行Action时会调用method里的属性值方法,如果不填method属性,则默认调用execute()方法

使用通配符动态调用
<action name="*_Action" class="ynk.itcast.action.CheckAction"method="{1}">
 	<result name="success">/welcome.jsp</result>
 	<result name="input">/regist.jsp</result>
</action>

method中的{1}的值为第一个*匹配到的值,此action可匹配任何以 _Action 结尾的action

定义全局视图
 <global-results>
    <result name="mainpage">/main.jsp</result>
 </global-results>

即无论是哪个action,只要返回的是mainpage都跳转到main.jsp页面

分文件编写配置文件
struts2可以将一个配置文件分解成多个配置文件,从而进行模块化的设计,也提高了配置文件的可读性。
            将不同的模块写在不同的配置文件中
            <struts>
                <include file="struts-student.xml"/>
                <include file="struts-teacher.xml"/>
                .......
            </struts>   


Struts2 数据封装

属性封装传递

action中

	private String username;
	private String userpassword;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getUserpassword() {
		return userpassword;
	}
	public void setUserpassword(String userpassword) {
		this.userpassword = userpassword;
	}

jsp中

<form action="test">
    	用户名:<input type="text" name="username">
    	密码:<input type="text" name="userpassword">
    		<input type="submit" value="登陆" name="btn">
    </form>

action中的属性名称要和jsp中的name一致

表达式封装(应用于属性为对象或List集合)

属性为对象

Bean中

public class User{
   private String username;
   private String userpassword;

    ....get/set方法。。。。
}

Aaction中

private User user;
 ....get/set方法....

jsp中

 <form action="test">
    	用户名:<input type="text" name="user.username">
    	密码:<input type="text" name="user.userpassword">
    		<input type="submit" value="登陆" name="btn">
    </form>
属性为List

Aaction中

private List<User> list;
....get/set方法....

jsp中

 <form action="test">
    	用户名:<input type="text" name="list[0].username">
    	密码:<input type="text" name="	list[0].userpassword">
    		<input type="submit" value="登陆" name="btn">
  </form>
模型驱动封装

将action实现ModelDriven接口

action中

public class CheckAction extends ActionSupport implements ModelDriven<User>{
	private User user=new User();
	public User getModel() {
		return user;
	}
     //.....省略
}

getModel为接口中的方法,注意:一定得将属性user实例化。

jsp页面表单中的input中的name属性值与user中的属性值相同。

Struts2获取域对象Request,Response,Session

使用ActionContext对象获取
//获取request对象方法
ActionContext context=ActionContext.getContext();
HttpServletRequest request=(HttpServletRequest) context.get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);

//获取request对象方法
HttpServletResponse response=(HttpServletResponse) context.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);
	
//获取session对象
Map<String, Object> session=context.getSession();

ServletActionContext对象获取

	//获取request对象方法
	HttpServletRequest request2=ServletActionContext.getRequest();
其他域对象获取方式相似
ServletRequestAware接口获取
public class testaware extends ActionSupport implements ServletRequestAware,SessionAware{

	HttpServletRequest request;
	Map<String, Object> session;
	
	public void setSession(Map<String, Object> arg0) {
		this.session=arg0;
	}
	public void setServletRequest(HttpServletRequest arg0) {
		this.request=arg0;
	}
        //response省略
}

ActionContext,Valuestack,StackContext联系

ActionContext:一次Action调用都会创建一个ActionContext,ActionContext是Action上下文

ValueStack(值栈):Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlCont设为OGNL的根对象。

StackContext(map):stack上下文,它包含一系列对象,包括request、session、attr、applicationmap等。




ValueStack是一个list,ContextMap是一个Map型的数据结构,它是以键值对的形式的存储数据的。

我们在JSP页面中访问value stack的内容时,是不用加#,而如果是访问stack context的其他对象则要加上#。

<s:property value="name"/>  Action中有name属性,或者有User属性其中User里有name属性,存值在ValueStack里,不用加#
<s:property value="#request.testValue"/> 取request域里的testValue值,request域在StackContext里,需加#


获取值栈
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
stack.set("setValue", "set方法值");
stack.push("push方法值"); //push方法存的为数值形式
获取值栈set与push方法的值
   <s:property value="setValue"/>
   <s:property value="[0].top"/>  //top是值栈里的数组

ValueStack(值栈)中获取list集合
Action中有属性 private List<User> list;

遍历集合list


Struts2校验器

手工编码校验器

例子:

public class CheckAction extends ActionSupport implements ModelDriven<User>{
	private User user=new User();
	public User getModel() {
		return user;
	}
	//Regist对应的校验方法
	public void validateRegist() {
		if(user.getPasswordAge()==null||user.getPasswordAge().equals("")){
			this.addActionError("确认密码不能为空");
		}else if(!user.getPassword().equals(user.getPasswordAge())){
			this.addActionError("两次密码不一样");
		}
	}
	public String Regist() {
		System.out.println("注册成功");
		ActionContext context=ActionContext.getContext();
		ValueStack stack=context.getValueStack();
		stack.set("mess", user.getName()+"注册成功!!");
		return SUCCESS;
	}
	//Login对应的校验方法
	public void validateLogin() {
		//验证数据库信息,
		//省略
		System.out.println("验证数据库信息");
	}
	public String Login() {
		System.out.println("登陆成功");
		ActionContext context=ActionContext.getContext();
		ValueStack stack=context.getValueStack();
		stack.set("setValue", "set方法值");
		stack.push("push方法值");
		
		HttpServletRequest request=ServletActionContext.getRequest();
		request.setAttribute("testValue", "获取成功");
	
		return SUCCESS;
	}
	//统一校验方法
	public void validate() {
		if(user.getName()==null||user.getName().equals("")){
			this.addActionError("用户名不能为空");
		}else if(user.getPassword()==null||user.getPassword().equals("")){
			this.addActionError("密码不能为空");
		}else if(user.getName().length()>7){
			this.addActionError("用户名过长,只能7个字符");
		}
	}	
}

1.执行此Action时都会先执行validate()方法。然后执行execute()方法。

2.当核心文件配置访问此action的Login()方法时,会先执行ValidateLogin()方法,然后执行validate方法,最后才执行          Login方法。

3.当校验器执行 this.addActionError("message“); 执行停止,默认返回input。

基于xml配置文件的校验器

xml配置文件的校验器的名称是固定的,当action类名称为xxx时,配置文件名称为xxx-validation.xml,和action在同一目录。

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE validators PUBLIC
  		"-//Apache Struts//XWork Validator 1.0.3//EN"
  		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
	<field name="name">
		<field-validator type="requiredstring">
			<message>用户名不能为空</message>
		</field-validator>
	</field>
	<field name="password">
		<field-validator type="requiredstring">
			<message>密码不能为空</message>
		</field-validator>
	</field>
	<field name="dates">
		<field-validator type="date">
		<param name="min">1990-01-01</param>
		<param name="max">1999-01-01</param>
		   <message>
		  	    日期格式不正确 	最小为${min},最大为${max}
		   </message>
		</field-validator>
	</field>
</validators>

<message>标签为错误时的提示信息,<field>标签中的name的值要跟action中的类属性值一致。

校验器常用值


Struts2拦截器

拦截器:动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在             一个action执行前阻止其执行。

过滤器和拦截器的区别

1.过滤器:过滤器理论上可以过滤任意内容,比如html,jsp,servlet,图片路径等;

2.拦截器:只能拦截action;

3.拦截器是基于java反射机制的,而过滤器是基于函数回调;拦截器不依赖与servlet容器,过滤器依赖与servlet容器

拦截器的实现
Interceptor接口
Interceptor接口定义三个方法,在intercept方法中写逻辑
public class TestInterceptor implements Interceptor{
	public void destroy() {
		// TODO Auto-generated method stub
	}
	public void init() {
		// TODO Auto-generated method stub
	}
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("Interceptor执行。。。。");
		invocation.invoke();//通过方法
		return null;
	}	
}
AbstractInterceptor抽象类

AbstractInterceptor实现了Interceptor接口,继承时只需要重写intercept方法即可

public class TestInterceptor extends AbstractInterceptor{
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("Interceptor执行。。。。");
		invocation.invoke();
		return null;
	}	
}
MethodFilterInterceptor类
public class TestInterceptor extends MethodFilterInterceptor{
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		String name=invocation.getInvocationContext().getName();//返回调用的action名称
		System.out.println(name);
		invocation.invoke();//执行invoke()方法后执行action,执行action后继续往下执行
		return null;
	}
}

MethodFilterInterceptor方法实现了AbstractInterceptor抽象类,会自动执行doIntercept()方法,只需要重写它即可。

struts_default.xml中配置
<!-- 配置拦截器 -->
 	<package name="interceptor" extends="struts-default">
 		<interceptors>
 			<interceptor name="testInterceptor" class="ynk.itcast.intorceptor.TestInterceptor"></interceptor>
 		</interceptors>
 	</package>
 	<!-- action包继承拦截器的包 -->
 	<package name="demo" extends="interceptor" namespace="/">
 		<action name="loginAction" class="ynk.itcast.action.CheckAction" method="Login">
 			<result name="success">/welcome.jsp</result>
 			<result name="input">/index.jsp</result>
 			<!-- 引用拦截器 -->
 			<interceptor-ref name="checkInterceptor"></interceptor-ref>
 			<interceptor-ref name="testInterceptor"></interceptor-ref>
 			<!-- 默认拦截器,当定义拦截器时得手动添加默认拦截器 -->
 			<interceptor-ref name="defaultStack"></interceptor-ref>
 		</action>
 	</package>

也可:

package name="interceptor" extends="struts-default">
 		<interceptors>
 			 	<interceptor name="checkInterceptor" class="ynk.itcast.intorceptor.CheckInceterceptor"></interceptor>
	 			<interceptor name="testInterceptor" class="ynk.itcast.intorceptor.TestInterceptor"></interceptor>
	 			<interceptor-stack name="totalInterceptor">
	 				<interceptor-ref name="checkInterceptor"></interceptor-ref>
		 			<interceptor-ref name="testInterceptor"></interceptor-ref>
		 			<!-- 默认拦截器,当定义拦截器时得手动添加默认拦截器 -->
		 			<interceptor-ref name="defaultStack"></interceptor-ref>
	 			</interceptor-stack>		
 		</interceptors>
 	</package>
 	<!-- action包继承拦截器的包 -->
 	<package name="demo" extends="interceptor" namespace="/">
 		<action name="loginAction" class="ynk.itcast.action.CheckAction" method="Login">
 			<result name="success">/welcome.jsp</result>
 			<result name="input">/index.jsp</result>
 			<!-- 引用拦截器 -->
 			<interceptor-ref name="totalInterceptor"></interceptor-ref>
 		</action>
 	</package>

Interceptor,AbstractInterceptor实现的拦截器默认拦截所有方法,而MethodFilterInterceptor可配置xml文件选择拦截的方法

具体实现是在action中的 interceptor-ref 标签中定义参数。

<interceptor-ref name="testInterceptor">
     <param name="includeMethods">login,register</param>
 </interceptor-ref>
表示只拦截login和register方法。当name值为 excludeMethods 时表示除了login和register方法,其他都拦截。

文件S


Struts2上传文件

jsp页面中:

enctype默认值为 application/x-www-form-urlencoded 基于文件传输的要改为multipaart/form-data 且为post 方式。

    <form action="uploadAction1" method="post" enctype="multipart/form-data">
   	<input type="file" name="file">
   	<input type="submit" value="提交">
   </form>

Bean:

利用Struts2文件上传时,默认执行fileUpload拦截器,将文件信息自动赋值

public class UploadFile{
	private File file;
	private String fileFileName; //命名格式固定:xxxFileName
	private String fileContentType;  //命名格式:xxxContentType
          //....省略get.set方法
}

action:

public class uploadAction1 extends ActionSupport implements ModelDriven<UploadFile>{

	UploadFile file=new UploadFile();
	
	public UploadFile getModel() {
		// TODO Auto-generated method stub
		return this.file;
	}
	@Override
	public String execute() throws Exception {	
		
		//项目目录加上/a 赋值给path
		String path=ServletActionContext.getServletContext().getRealPath("\\a");
		
		File pathFile=new File(path);
		if(!pathFile.exists()){
			pathFile.mkdir();
		}
		
		//根据pathFile和文件fileFileName新建目标文件
		File goalFile=new File(pathFile,file.getFileFileName());
		if(!goalFile.exists()){
			goalFile.createNewFile();
		}
		//将源文件copy到目标文件
		FileUtils.copyFile(file.getFile(), goalFile);
		//也可用下面语句,将源文件修改名称后放到pathfile目录
		/*file.getFile().renameTo(new File(pathFile, file.getFileFileName()));*/
		
		return SUCCESS;
	}

}

此例子中类属性为Bean类型,使用了模型驱为UploadFile类型的file属性封装数据。其中,UploadFile中的fileName为上传的文件名,fileContentType为文件类型。

当不用模型驱动时可设置action的三个类属性也可封装数据

   private File file;
   private String fileName;
   private String fileContentType;

xml配置文件

<param>标签未 fileUpload拦截器的allowedeTypes属性赋值,即允许上传的文件格式,非此类格式时返回input。

<package name="action" extends="struts-default">         
	    <action name="*" class="ynk.itcast.action.{1}">  
	      <result name="success">/welcome.jsp</result>
	      <result name="input">/index.jsp</result>
	      <interceptor-ref name="defaultStack">
	      	<param name="fileUpload.allowedTypes">
	      		image/bmp,image/png,image/gif,image/jpeg,image/jpg
	      	</param>
	      </interceptor-ref>
	    </action>  
    </package>  

另:

maximumSize:表示上传文件大小的上限,单位是byte。默认2MB。
allowedTypes:表示允许上传文件的类型,每个类型之间用逗号分隔开(ie: text/html, image/jpg)。
allowedExtensions:表示允许上传以这些后缀结尾的文件,每个后缀之间用逗号分隔开(ie: .html, .jpg)。
多文件上传

实现多文件上传时只需要将action的类属性设为数组 如File[] file;String[] fileName 即可,然后将其遍历,jsp表单中type为file的input标签的name一致。

Struts2文件下载

先进入index Action 为 fileFileNames 赋值;

indexAction:

public class indexAction extends ActionSupport{
	
	private String[] fileFileNames;

	public String[] getFileFileNames() {
		return fileFileNames;
	}
	public void setFileFileNames(String[] fileFileNames) {
		this.fileFileNames = fileFileNames;
	}
	@Override
	public String execute() throws Exception {
			String path=ServletActionContext.getServletContext().getRealPath("\\download");
			File pathFile=new File(path);
			fileFileNames=pathFile.list();  //将pathFile路径下的所有文件名返回给数组fileFileNames
		        return SUCCESS;
	}
}

index.jsp:

遍历fileFileNames

<s:iterator value="fileFileNames" var="fileFileName">
   	<a href="downloadAction?fileFileName=<s:property value='fileFileName'/>"><s:property value="fileFileName"/></a>
  </s:iterator>

DownloadAction:

public class DownloadAction extends ActionSupport{
        //需要下载的文件名    
	private String fileFileName;

	public String getFileFileName() throws Exception {
		return URLEncoder.encode(fileFileName, "UTF-8");  //转码,如果不转中文在下载时会没有文件名
	}
	public void setFileFileName(String fileFileName){
		this.fileFileName = fileFileName;
	}
	
	public String execute() throws Exception {
		return SUCCESS;
	}
	public InputStream getDownloadFile() {
		return ServletActionContext.getServletContext().getResourceAsStream("\\download\\"+fileFileName);//获取文件流
	}
}

xml配置文件:

type类型为stream;

inputName标签里的download表示获取文件流的方法;

contentDisposition中的attchment表示下载文件而不是打开;filename的值为下载时的文件名。

   <package name="action" extends="struts-default">         
	    <action name="downloadAction" class="ynk.itcast.action.DownloadAction">  
	      <result name="success" type="stream">
	      	<param name="inputName">downloadFile</param><!--  调用的方法 -->
	      		<!-- attchment表示为下载而不是打开,filename后接下载的文件名 -->
	      	<param name="contentDisposition">attchment;filename=${fileFileName}</param> 
	      </result> 
	    </action>  
	   	<action name="index" class="ynk.itcast.action.indexAction">
	   		<result name="success">/index.jsp</result>
	   	</action>
    </package>

Struts2异常信息

addActionError

添加错误信息:

this.addActionError("错误信息1");

显示信息标签为:

 <s:actionerror/>
addActionMessage

添加错误信息:

this.addActionMessage("错误信息1");

显示信息标签为:

<s:actionmessage/>
addFieldError


添加错误信息:

this.addFieldError("error", "错误信息");
this.addFieldError("error1", "错误信息1");

显示全部信息标签为:

<s:fielderror/>

或:

<s:fielderror>
     <s:param>error</s:param>
     <s:param>error1</s:param>
</s:fielderror>

END。。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值