Struts2笔记

Struts2框架

Struts2 用来替换 Servlet — 升级版(对于原始Servlet技术的封装)

框架:半成品,解决现有软件开发中所存在的通用问题,为了提升开发效率。

Servlet中存在哪些问题?

  1. 接收数据冗余
    1. String s = request.getParameter(""); 冗余
    2. 需要将接收的数据进行数据类型的转换。
    3. post请求的数据提交,需要编码过滤器。
  2. 跳转路径硬编码在源文件中(写死了)

一、第一个Struts2程序

1、编码思想

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2qR4CyQp-1594711299913)(E:\JavaWeb\Struts\笔记\思想.png)]

localhost:8989/项目名称/url-pattern servlet

localhost:8989/项目名称/struts.xml 中action标签的name属性值

2、代码开发

1. 搭建开发环境

1、 jar包
		九个jar包

2、 准备struts.xml的配置文件
		位置: 必须是src的根目录

3、 在web.xml中配置struts2的核心过滤器   (没有配置    404)
	apache: www.apache.org
    <filter>
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.
                      StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts</filter-name>
        <url-pattern>/*</url-pattern>
     </filter-mapping>

2. java编码

实现 Action接口
import com.opensymphony.xwork2.Action;

public class MyAction implements Action {

	@Override
	public String execute() throws Exception {
		System.out.println("--------Hello Wolrd----------");
		return "success";
	}

}

3.struts.xml的配置

<!-- 包  struts.xml中的package 和  java src中package没有任何关系 -->
	<package name="day1" extends="struts-default">
		<!-- localhost:8989/Struts_Day1/first -->
		<action name="first" class="com.baizhi.action.MyAction">
            <!-- name="类中execute方法的返回值" -->
			<result name="success">/index.jsp</result>
		</action>
	</package>

支持 路径 + .action 结尾的后缀名
http://localhost:8989/Struts_Day1/first.action

二、跳转

两种跳转: forward 请求转发 、redirect重定向

<result name="success" type="使用的跳转方式">目标路径</result>
Action —> jsp 跳转
1. 默认是forward 请求转发跳转方式
    <!--  type="dispatcher" -->
	<result name="success" type="dispatcher">页面</result>

2. redirect 重定向
	<!--  type="redirect" -->
	<result name="success" type="redirect">页面</result>
Action —> Action跳转
1. forward 请求转发
    <!--  type="chain" -->
    <action name="first" class="com.baizhi.action.MyAction">
        				<!--  second:另一个action的name属性-->
        <result name="success" type="chain">second</result>
    </action>

    <action name="second" class="com.baizhi.action.MyAction2">
        <result name="success">/index.jsp</result>
    </action>

2. redirect 重定向
	 <!--  type="redirectAction" -->
    <action name="first" class="com.baizhi.action.MyAction">
        				<!--  second:另一个action的name属性-->
        <result name="success" type="redirectAction">second</result>
    </action>

    <action name="second" class="com.baizhi.action.MyAction2">
        <result name="success">/index.jsp</result>
    </action>

跳转四个小分类(本质上都是forward和redirect)

action --> jsp dispatchar(默认) / redirect

action --> action chain /

注意: 如何获取request等对象?

使用工具类 ServletActionContext

HttpServletRequest request = ServletActionContext.getRequest();

三、package标签

对于整个项目中的Action进行分类管理

1、namespace 命名空间
<!-- 包  struts.xml中的package 和  java src中package没有任何关系 -->
<!-- name="day1" 随便写 只要配置文件中没有明明冲突即可        -->

访问路径: localhost:8989/项目名称/namespace/action标签name的属性值
		  localhost:8989/Struts_Day1/d/first.action

    <package name="day1" extends="struts-default" namespace="/d">
        <!-- localhost:8989/Struts_Day1/first.action -->
        <action name="first" class="com.baizhi.action.MyAction">
            <result name="success" type="redirectAction">second</result>
        </action>

        <action name="second" class="com.baizhi.action.MyAction2">
            <result name="success">/index.jsp</result>
        </action>
    </package>
2、Streuts 挎包跳转的问题

只针对Action ----> Action的跳转

<package name="day1" extends="struts-default" namespace="/d1">
    <action name="first" class="com.baizhi.action.MyAction">  
        <result name="success" type="redirectAction">
             <!-- 声明跳转到的 package的 namespace名称 和 具体的action标签的name -->
        	<param name="namespace">/d2</param>
            <param name="actionName">second</param>
        </result>
    </action>
</package>

<package name="day2" extends="struts-default" namespace="/d2">
    <action name="second" class="com.baizhi.action.MyAction2">
        <result name="success">/index.jsp</result>
    </action>
</package>


注意:在挎包跳转中  <result name="xxxx" type="有几个可选值?">
    							只能写:  chain / redirectAction

四、Struts2中接收数据 — 使用成员变量

使用成员变量接收数据!!!!

Struts2的Action对象是否也是单例呢?

​ 每一次访问Action对象 都会调用Action中的无参构造方法,Action不是单例对象。

login.jsp
<form action="xxxxxxx" method="post">
	<input type="text" name="username"/>
	<input type="text" name="age"/>
	<input type="text" name="date"/>
</form>

Servlet 中
	保证存在编码过滤器
	String username = request.getParameter("username");
	String age = request.getParameter("age");
	int a = Integer.parseInt(age);
	String date = request.getParameter("date");
	Date d = new simpleDateFormate("yyyy-MM-dd").parse(date);
1. 接收简单类型的数据  八种基本类型+String+Date

        class  MyAction implements Action{
            private String username;
            private int age;
            // yyyy-MM-dd HH:mm:ss
            private Date date;
            set/get方法
            // 接收中文数据的默认格式是utf-8
            public String execute()throws Exception{
                username / age / date
                return "success";
            }
        }
        
2. 使用自定义对象类型接收数据
		User对象   id   name  password
		
		 class  MyAction implements Action{	 
            private User u;         
            set/get方法

            public String execute()throws Exception{
               System.out.print(user);
                return "success";
            }
         }
         
		 页面 .jsp      name = 成员变量名称.属性
		 <input type="text" name="u.id"/>
		 <input type="text" name="u.name"/>
	     <input type="text" name="u.password"/>	 
	     
3.  批量删除 接收集合类型的数据
		 <input type="checkbox" name="ids"/>
		 <input type="checkbox" name="ids"/>
	     <input type="checkbox" name="ids"/>	 
	     Servlet中
	     	String[] strs = request.getParametervalues();

		 Struts中  使用集合类型接收
		 	private List<Integer> ids ;
			set/get;

五、DMI开发方式

Action 开发 必须去实现Action接口!!!

Action数量的不可控, 使用DMI开发方式去减少Action的数量。

继承 ActionSupport类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C2wJmiQw-1594711299915)(E:\JavaWeb\Struts\笔记\DMI.png)]

配置Struts.xml 两种情况

1、配置方式一:

<package name="day2" extends="struts-default">
	<action name="login" class="com.baizhi.action.MyAction" method="loginMethod">
		<result name="loginSuccess">/index.jsp</result>
	</action>
	<action name="register" class="com.baizhi.action.MyAction"
            							method="registerMethod">
		<result name="registerSuccess">/index.jsp</result>
	</action>
</package>

localhost:8989/项目名称/action标签中的name属性值

2、配置方式二:

<package name="day2" extends="struts-default">
   	   name=“my_*”
   <action name="*" class="com.baizhi.action.MyAction" method="{1}">
       <result name="loginSuccess">my_</result>
       <result name="registerSuccess">/index.jsp</result>
   </action>
</package>

method=“{1}”  使用 方法名 去替换 name属性值中的 *

localhost:8989/项目名称/action标签中的name属性值 *    ----->  方法名称
localhost:8989/项目名称/loginMethod
localhost:8989/项目名称/my_loginMethod

注意: 同一个Action中 方法之间的返回值必须不一样!!!!

六、使用成员变量替换request作用域

替换了request作用域存入数据的代码,而不是取代了作用域,底层还是使用request作用域完成的数据传递。

public class MyAction2 implements Action{
    //使用成员变量替换request作用域
	private String key ="value";
	@Override
	public String execute() throws Exception {
		System.out.println("-----------第二个Action-----------");
		
		//HttpServletRequest request = ServletActionContext.getRequest();
		//request.setAttribute("key", "value");
		return "success";
	}
	
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	
}
 <h3>${requestScope.key}</h3>
	
  request.setAttribute(String name, object value);
  key = 成员变量的名称  = String name

七、文件的上传

1、 页面如何选择文件进行发送

2、 Action如何就收发送的数据文件

3、 服务器如何去保存文件

1、页面
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name=""/>
    <input type="submit"/>
</form>

1. type = "file"
2. enctype="multipart/form-data"
2、Action接收数据
import java.io.File;   
//Action中接收前台提交的数据
    private  File  upload;

    public File getUpload() {
        return upload;
    }
    public void setUpload(File upload) {
        this.upload = upload;
    }
3、 服务器保存文件
使用IO流将内存中的文件数据写入服务器硬盘中

 // 创建流   创建去读单位大小  使用循环依次写入硬盘中   -1    关闭资源

    InputStream is = new FileInputStream(upload);
    OutputStream os = new 
        FileOutputStream("F:\\apache-tomcat-7.0.64\\webapps\\Struts_Day3\\b.txt");
    byte[] b = new byte[2048];
    int len = 0;
    while(true){
        len = is.read(b, 0, b.length);
        if(len==-1){
            break;
        }else{
            os.write(b);
        }
    }
    is.close();
    os.close();
    return "success";
问题

1、文件名称以及文件类型无法动态获取

Action 中 定义成员变量

    private String 上传的文件名称+FileName;    //获取文件的上传名称
    private String 上传的文件名称+ContentType; //获取文件的互联网类型

    set/get 方法

2、不使用原始的IO流进行文件的上传 效率有一定问题

FileUtils.copyFile(upload, 
   new File("F:\\apache-tomcat7.0.64\\webapps\\Struts_Day3\\file\\"+uploadFileName));

FileUtils.copyFile(上传的文件对象,new File(服务器保存文件的路径))

**上传的文件大小设置 ** 默认2m

Struts.xml
<constant name="struts.multipart.maxSize" value="20971520000"></constant>

3、上传路径动态获取

//获取项目所在服务器的真实路径
//name 具体的文件夹名称
private String name;
set/get方法
String realPath = ServletActionContext.getServletContext().getRealPath(name);



Strust.xml中
<action name="upload" class="com.baizhi.action.MyAction" method="upload">
	<!-- 上传文件的目标文件夹名称  -->
    <param name="name">f</param>
	<result name="success">/index.jsp</result>
</action>

成员变量

​ 1、接收数据 2、替换request作用域传递数据 3、从struts.xml文件中获取数据信息

文件上传代码
//Action中接收前台提交的数据
private  File  upload;
//获取上传文件的文件名称      文件名对象upload + FileName;  自动获取文件名称
private String uploadFileName;
//文件名对象upload + ContentType;  获取文件的互联网类型
private String uploadContentType;
//定义成员变量  从strtus.xml文件中读取数据    动态从配置文件中读取到的文件名称
private String name;
	

public String upload()throws Exception {
    //动态获取文件的保存路径                                                                 //将文件夹名称提取出来写在struts.xml的配置文件中
    String realPath = ServletActionContext.getServletContext().getRealPath(name);
    //copyFile  文件的复制  将源文件 复制到 制定的目标路径中
    FileUtils.copyFile(upload, new File(realPath+"\\"+uploadFileName));

    return "success";
}

八、拦截器

Action中存在代码冗余的问题,强制登录。

1、开发步骤

拦截器的开发

实现 interceptor接口

public class MyInterceptor implements Interceptor{
	//三个方法
	public String intercept(ActionInvocation ai) throws Exception {
		System.out.println("-----------intercept------------");
		ai.invoke();   //相当于 chain.doFilter()  放行			
		return null;
	}
}

拦截器的配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lnCBAPfc-1594711299917)(E:\JavaWeb\Struts\笔记\拦截器配置.png)]

注意: 拦截器只在本包中生效 package标签中有效

使用DMI的第二种配置方式会减少部分拦截器配置的冗余。

2、配置补充

如果程序中存在多个拦截器应该如何进行配置 ?

拦截器栈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zytt3vz3-1594711299918)(E:\JavaWeb\Struts\笔记\拦截器栈1.png)]

每一个Action标签都是用拦截器栈 冗余

默认拦截器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0BAsHnp6-1594711299919)(E:\JavaWeb\Struts\笔记\默认拦截器栈.png)]

如何拦截器中存在跳转判断应该如何书写 ?

例如:当强制登录中没有进行过登录操作,则需要跳转回登录页面。

拦截器中的返回值 retrun “xxxx”; 跳转配置需要写在Action标签中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eBDEcbHv-1594711299920)(E:\JavaWeb\Struts\笔记\拦截器中的跳转.png)]

全局跳转

拦截器进行拦截跳转 可能存在多个Action标签中使用配置相同的访问跳转路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w1iux95w-1594711299922)(E:\JavaWeb\Struts\笔记\全局跳转.png)]

注意: 当使用自定义拦截器的时候有可能会和Struts2框架定义的系统拦截器产生冲突。

在使用配置用户自定义拦截器栈是优先声明系统默认拦截器。

<interceptor-stack name="myStack">
    	<!--优先声明系统默认拦截器-->
		<interceptor-ref name="defaultStack"></interceptor-ref>
		<interceptor-ref name="login"></interceptor-ref>
</interceptor-stack>
3、方法拦截器
public class MyMethodInterceptor extends MethodFilterInterceptor{ //抽象类
	@Override
	protected String doIntercept(ActionInvocation ai) throws Exception {
		System.out.println("-------方法拦截器----------");
		ai.invoke();
		return null;
	}
}

配置

<!-- 配置方法拦截器的时候并不是拦截action中的所有 而是对部分方法进行拦截  -->
		<interceptors>
			<interceptor name="my" 
                         class="com.baizhi.interceptor.MyMethodInterceptor">
                <!--  excludeMethods  非包含  -->
				<param name="includeMethods">my*</param>
			</interceptor>
			
			<interceptor-stack name="myStack">
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<interceptor-ref name="my"></interceptor-ref>
			</interceptor-stack>
		</interceptors>

注意: 在Struts2中进行拦截器开发步骤

1、 拦截器 实现 interceptor接口

​ 方法拦截器 继承 MethodFilterinterceptor抽象类

​ 2、 配置

​ 2.1 声明拦截器 (如果是方法拦截器还需要声明包含或非包含方法)

​ 2.2 定义拦截器栈 (添加系统默认拦截器 defaultStack)

​ 2.3 使用拦截器栈

​ 2.3.1 在action标签中配置

​ 2.3.2 使用默认的拦截器栈

九、文件下载

提交文件名称,从服务器中将文件通过流进行输出。

//文件所在文件夹的名称
private String name;
//浏览器提交的需要下载的文件名称  同时向struts.xml中进行赋值操作
private String fileName;

public InputStream getInputStream()throws Exception{
    //获取文件所在服务器的真实路径
    String realPath = ServletActionContext.getServletContext().getRealPath(name);
    //name 文件在服务器中的路径
    return new FileInputStream(realPath+"\\"+fileName);
}

<package name="down" extends="struts-default">
    <!-- action中没有method属性 -->
    <action name="download" class="com.baizhi.action.DownLoadAction">
        <param name="name">file</param>
        <!-- type="stream" 输出不再是跳转而是流对象 -->
        <result type="stream">
             <!-- contentType 输出文件的互联网类型 -->
            <param name="contentType">image/png</param>
            <param name="bufferSize">4096</param>
            <!-- contentDisposition 保存方式 -->
            <!-- inline 浏览器预览 -->
            <!-- attachment;filename=${fileName} 使用附件的形式进行保存 -->
            <param name="contentDisposition">attachment;filename=${fileName}</param>
        </result>
    </action>
</package>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U6EDxxFn-1594711299923)(E:\JavaWeb\Struts\笔记\下载.png)]

 1. 成员变量 如何接收数据? 怎么做的 拦截器!!!
 2. 成员变量为什么可以替换request作用域?

type=“stream” 输出不再是跳转而是流对象 -->


image/png
4096



attachment;filename=${fileName}



[外链图片转存中...(img-U6EDxxFn-1594711299923)]





  1. 成员变量 如何接收数据? 怎么做的 拦截器!!!
  2. 成员变量为什么可以替换request作用域?























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值