Struts2


title: Struts2

Struts2

简介:控制器框架

控制器框架:简化servlet原本收参,传参,跳转的过程

Struts2使用

在web.xml文件中配置

<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>

配置action的访问路径(struts.xml)

struts.xml在src下

<!-- package:给请求分类,在正常的项目开发中,将项目分成多个模块,例:用户管理模块,商品管理模块。。。。
	 用户管理模块:登陆,注册,注销。。。。
	 一般情况下,会将同一个模块的功能写在同一个package中
	 属性:    name:给当前包起名字,名字随便起,同一个struts.xml中不能重复
-->

<package name="p1"  extends="struts-default" >
    <!-- action : 一个action配置一个请求路径,在一个package中可以写多个action 
                   属性:  name:配置请求路径,注意,不要加“/”
            class:当该action被请求时,执行哪个类   默认执行类中的execute方法     
   -->
    <action name="first" class="com.baizhi.action.FirstAction">
        <!-- result: action执行完之后的跳转配置
     属性   name:execute方法的返回值
    -->
        <result name="ok">/index.jsp</result>
    </action>
</package>

struts.xml详解

package标签中的namespace属性
<package name="p1"  extends="struts-default" namespace="/hero" >
		<!-- action : 一个action配置一个请求路径,在一个package中可以写多个action 
		                 属性:  name:配置请求路径,注意,不要加“/”
		          class:当该action被请求时,执行哪个类   默认执行类中的execute方法     
		 -->
		<action name="first" class="com.baizhi.action.FirstAction">
			<!-- result: action执行完之后的跳转配置
				 属性   name:execute方法的返回值
			 -->
			<result name="ok">/index.jsp</result>
		</action>
	</package>

作用:在p1包下的所有action请求,请求路径要加上namespace的值

例:要请求上述的first -》Action
lcoalhost:8989/webappName/hero/first
action中的method属性
<!--action中没有method属性,默认为execute方法,写了method属性,执行的是method中的方法-->
<action name="first" class="com.baizhi.action.FirstAction" method="a">
			<!-- result: action执行完之后的跳转配置
				 属性   name:execute方法的返回值
			 -->
			<result name="ok">/index.jsp</result>
</action>


public class FirstAction extends ActionSupport {
	@Override
	public String execute() throws Exception {
		//请求的具体内容
		System.out.println("-------sturts do-------");
		
		
		//返回字符串
		//内容随便写,作用一会儿在配置struts.xml的时候有用
		return "ok";
	}
	public String a() {
		System.out.println("我是a,我被执行了,哈哈哈啊哈。。。。。。");
		return "ok";
	}
}
<!--如果添加了method属性,那么在action中自定义的方法,必须为公开无参的,返回值为String的方法,方法名要和method中的一致-->
result标签中的type属性
  1. 作用:确定跳转方式(转发,重定向)

    • action转发到jsp

      <result name="ok" type="dispatcher" ></result>
      
    • action重定向导jsp

      <result name="ok" type="redirect">/XXX.jsp</result>
      
    • action转发到action(不常用)

      <result name="ok" type="chain">action的name属性值</result>  注意:不能加“/“
      
    • action重定向导action

      同包重定向
      <result name="ok" type="redirectAction">action的name属性值</result>  注意:不能加“/“
      
      特例:跨包重定向
      <action name="login" class="com.baizhi.action.UserAction" method="login">
      			<!-- 登陆成功   跨包重定向查询所有的action    -->
      			<result name="loginOk" type="redirectAction" >
      				<param name="namespace">/pro</param>
      				<param name="actionName">selectAll</param>
      			</result>
      </action>
      
Struts接收请求参数
  • 使用servlet接收请求参数

    String value = request.getParameter("key");
    
  • 在struts中获取request对象

    public String a() {
        HttpServletRequest request = ServletActionContext.getRequest();
    
        String name = request.getParameter("name");
        System.out.println(name);
    
        System.out.println("我是a,我被执行了,哈哈哈啊哈。。。。。。");
        return "ok";
    }
    
  • 用struts方式接收
    接收简单类型

步骤:

  1. 在action中定义一个属性,属性名与参数的key相同

  2. 给此属性生成标准的get和set方法

  • 标准get/set的生成过程:属性首字母大写,其他字母不变,然后最前面添加get/set
private Stirng userName;
public String getUserName(){}
public void setUserName(String userName){}


private String eName;
public String getEName(){}
public void setENname(){}
public class FirstAction {
	private String name;
	private int age;
	public String a() {
		System.out.println("我是a,我被执行了,哈哈哈啊哈。。。。。。");
		System.out.println("这是前端传来的值:"+name);
		System.out.println("这是前端传来的age+1的值:"+(age+1));
		return "ok";
}

	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}
接收对象类型

接收对象

  1. 创建标准实体类
  • 标准实体类:无参构造方法噶,所有属性的标准get和set方法
  • 只能多不能少
  1. 在action中创建对象属性,提供get和set
  2. 在前端要给对象赋值,前端的key的写法为对象名.属性名

image-20200923163625567

接收集合数组
  1. 定义标准实体类

  2. 在action中创建一个集合属性(数组属性,提供get/set)

public class FirstAction {
	
	private List<Integer> ids;
	
	
	public String a() {
		System.out.println("我是a,我被执行了,哈哈哈啊哈。。。。。。");
		System.out.println(ids);
		return "ok";
	}
	
	
	public List<Integer> getIds() {
		return ids;
	}
	public void setIds(List<Integer> ids) {
		this.ids = ids;
	}	
	
}
<form action="${pageContext.request.contextPath }/hero/first">
    <input type="checkbox" name="ids" value="1" /><br/>
    <input type="checkbox" name="ids" value="2" /><br/>
    <input type="checkbox" name="ids" value="3" /><br/>
    <input type="checkbox" name="ids" value="4" /><br/>
    <input type="checkbox" name="ids" value="5" /><br/>
    <input type="checkbox" name="ids" value="6" /><br/>
    <input type="checkbox" name="ids" value="7" /><br/>
    <input type="checkbox" name="ids" value="8" /><br/>
    <input type="submit" />
</form>

Struts操纵作用域保存内容

request

  1. 在action中定义属性,提供get/set方法

  2. 在重写的action方法中给此属性赋值,就相当于,把内容存入了request中,key为属性名,值为你存入的值

public class ProductAction {
	private User user;

	public String selectAll() {
		//创建user对象
		User u = new User(1, "贾莎莎", "666666");
		//将对象赋值给属性
		//相当于往req中保存一个键值对   键为user   值为u对象      “user”=user[id=1,name="asa",pwd="66666"]
		user = u;
		System.out.println("----------查询所有---------");
		return "selectAllOk";
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	
}
<body>
	<h1>我是展示商品页面</h1>	
	${requestScope.user }
</body>

session

//获取session
HttpServletRequest request = SerlvetActionContext.getRequest();
HttpSession session = request.getSession();

//存
session.setAttribute("key",value);

//取
session.getAttribute("key");

Struts运行流程

image-20200924100009427

如果想要强制登陆过滤器起效果,就必须保证强制登陆过滤器要先于核心过滤器被执行,

过滤器执行顺序与其在web.xml中的配置顺序有关,谁先被配置谁想被执行

结论:强制登陆的filter必须要放在struts核心过滤器之前

通配符

目前在struts.xml中的action配置过于繁琐,通常一个package中会有很多action标签

<package name="product" extends="struts-default" namespace="/pro">
		<!-- 查询所有的action -->
		<action name="selectAll" class="com.baizhi.action.ProductAction" method="selectAll">
			<!-- 转发到查询所有的页面  show.jsp -->
			<result name="selectAllOk" type="dispatcher">/show.jsp</result>
		</action>
		<!-- 添加的action -->
		<action name="insert" class="com.baizhi.action.ProductAction" method="insert">
			<!-- 重定向到查询所有的action -->
			<result name="insertOk" type="redirectAction">selectAll</result>
		</action>
		<!-- 删除的action -->
		<action name="delete" class="com.baizhi.action.ProductAction" method="delete">
			<!-- 重定向到查询所有的action -->
			<result name="deleteOk" type="redirectAction">selectAll</result>
		</action>
		<!-- 修改的action -->
		<action name="update" class="com.baizhi.action.ProductAction" method="update">
			<!-- 重定向到查询所有的action -->
			<result name="updateOk" type="redirectAction">selectAll</result>
		</action>
	</package>
<package name="product" extends="struts-default" namespace="/pro">
		<!-- 查询所有的action -->
		<action name="pro_*" class="com.baizhi.action.ProductAction" method="{1}">
			<!-- 转发到查询所有的页面  show.jsp -->
			<result name="selectAllOk" type="dispatcher">/show.jsp</result>
			 <result name="Ok" type="redirectAction">pro_selectAll</result>
		</action>
	</package>

验证码

导入糊涂工具包,要求JDK1.8以上

代码实现:

public class CodeAction {
	private ByteArrayInputStream stream;
	
	public String code() {
		//画验证码
		CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 50, 4, 4);
		//返回给img标签
		//需要用到流
		stream = new ByteArrayInputStream(captcha.getImageBytes());
		
		//将验证码对象放入session中
		HttpSession session = ServletActionContext.getRequest().getSession();
		session.setAttribute("realCode", captcha);
		return "codeOk";
	}
	public ByteArrayInputStream getStream() {
		return stream;
	}
	public void setStream(ByteArrayInputStream stream) {
		this.stream = stream;
	}
}
<package name="code" extends="struts-default">
   <action name="code" class="com.baizhi.action.CodeAction" method="code">
       <result name="codeOk" type="stream">
           <!-- 指明传送内容的格式 -->
           <param name="contentType">image/jpeg</param>
           <!-- 指明流的名字,在action中流属性的名字 -->
           <param name="inputName">stream</param>
           <!-- 流缓存大小 -->
           <param name="bufferSize">2048</param>
       </result>
   </action>
</package>
//登陆的action
public class UserAction {
	private String userCode;
	public String login() {
		//判断用户输入的验证码是否正确
		//	1.从session中取验证码
		HttpSession session = ServletActionContext.getRequest().getSession();
		CircleCaptcha captcha = (CircleCaptcha)session.getAttribute("realCode");
		if(captcha.verify(userCode)) {
			//验证码正确
			return "loginOk";
		}else {
			//验证码错误
			return "loginBuOk";
  		}
		//判断用户密码
		
	}
	public String Regist() {
		System.out.println("-------注册成功-------");
		return "registOk";
	}
	public String getUserCode() {
		return userCode;
	}
	public void setUserCode(String userCode) {
		this.userCode = userCode;
	}
	
}

action的生命周期

  1. 问题:之前我们说过不能在serlvet中定义属性,原因是多个用户使用同一个servlet对象,定义属性会出现临界资源,导致线程不安全,但现在我们在action却可以定义属性,这是为什么
  2. 创建:每一个action请求过来时都会创建一个新的action对象
    销毁:当本次请求结束时,action对象立即被销毁

在一个请求发送过来时,会创建一个action对象,并且执行请求对应的方法,当方法执行完时,对象会马上被销毁

不同用户发送的请求,action对象不一样

相同用户发送的两次请求,action对象不一样

结论:由于每次请求使用的action对象不同,所以在action中定义属性,不会产生临界资源,不会发生线程不安全的问题

Struts拦截器

拦截器:当一个请求请求某个action时,拦截器会拦截此请求,先执行拦截器中的内容,并且决定是否让该请求放行,去执行原本要请求的action

步骤

1.自定义类,实现interceptor接口

public class MyInterceptor implements Interceptor {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		//拦截器被销毁时调用
	}

	@Override
	public void init() {
		// TODO Auto-generated method stub
		//拦截器被创建时调用
	}

	@Override
	public String intercept(ActionInvocation ai) throws Exception {
		// TODO Auto-generated method stub
		//拦截器的具体实现
		System.out.println("我是拦截器,我被调用了,哈哈哈啊哈哈。。。。。");
		
		//放行
		//invoke方法有返回值,返回值的内容为action方法的返回值内容
		String invoke = ai.invoke();
		
		return invoke;
	}

}

2.struts.xml中注册拦截器

<package name="p1" extends="struts-default">
		<!-- 注册拦截器 -->
		<interceptors>
			<interceptor name="myInt" class="com.baizhi.interceptor.MyInterceptor"></interceptor>
		</interceptors>
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<result name="ok">/index.jsp</result>
		</action>
</package>

3.使用拦截器

<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<!-- 使用拦截器 -->
			<interceptor-ref name="myInt"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>

拦截器详解

当有多个拦截器时执行先后

在action中,谁先被使用,谁先运行,跟注册顺序无关

<package name="p1" extends="struts-default">
		<!-- 注册拦截器 -->
		<interceptors>
			<interceptor name="myInt" class="com.baizhi.interceptor.MyInterceptor"></interceptor>
			<interceptor name="bInt" class="com.baizhi.interceptor.BInterceptor"></interceptor>
		</interceptors>
		
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<!-- 使用拦截器 -->
			<interceptor-ref name="bInt"></interceptor-ref>
			<interceptor-ref name="myInt"></interceptor-ref>
			<result name="ok">/index.jsp</result>
			
		</action>
</package>


结果:bInt先执行,myInt后执行
拦截器栈

当有多个action同时需要相同的多个拦截器时,可以使用拦截器栈

<package name="p1" extends="struts-default">
		<!-- 注册拦截器 -->
		<interceptors>
			<interceptor name="myInt" class="com.baizhi.interceptor.MyInterceptor"></interceptor>
			<interceptor name="bInt" class="com.baizhi.interceptor.BInterceptor"></interceptor>
			<!-- 拦截器栈 -->
			<interceptor-stack name="myStack">
				<interceptor-ref name="myInt"></interceptor-ref>
				<interceptor-ref name="bInt"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<!-- 使用拦截器栈 -->
			<interceptor-ref name="myStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
		
		<action name="b" class="com.baizhi.action.TestAction" method="mb">
			<interceptor-ref name="myStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
</package>
父包

在不同的包中需要使用到相同拦截器

<package name="father" extends="struts-default">
		<!-- 注册拦截器 -->
		<interceptors>
			<interceptor name="myInt" class="com.baizhi.interceptor.MyInterceptor"></interceptor>
			<interceptor name="bInt" class="com.baizhi.interceptor.BInterceptor"></interceptor>
			<!-- 拦截器栈 -->
			<interceptor-stack name="myStack">
				<interceptor-ref name="myInt"></interceptor-ref>
				<interceptor-ref name="bInt"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
	</package>
	
<package name="p1" extends="father">
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<!-- 使用拦截器 -->
			<interceptor-ref name="myStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
		<action name="b" class="com.baizhi.action.TestAction" method="mb">
			<interceptor-ref name="myStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
</package>
	
	<package name="p2" extends="father">
		<action name="testB" class="com.baizhi.action.TestBAction" method="testB">
			<interceptor-ref name="myStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
	</package>

p1,p2包都继承了father包,那么在father包中所定义的所有内容,p1和p2包都能使用
设置默认使用拦截器
<struts>
	<package name="father" extends="struts-default">
		<!-- 注册拦截器 -->
		<interceptors>
			<interceptor name="myInt" class="com.baizhi.interceptor.MyInterceptor"></interceptor>
			<interceptor name="bInt" class="com.baizhi.interceptor.BInterceptor"></interceptor>
			<!-- 拦截器栈 -->
			<interceptor-stack name="myStack">
				<interceptor-ref name="myInt"></interceptor-ref>
				<interceptor-ref name="bInt"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
  设置默认使用拦截器
		<default-interceptor-ref name="myStack"></default-interceptor-ref>
	</package>
	
<package name="p1" extends="father">
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<result name="ok">/index.jsp</result>
		</action>
		<action name="b" class="com.baizhi.action.TestAction" method="mb">
			<result name="ok">/index.jsp</result>
		</action>
</package>
	
	<package name="p2" extends="father">
		<action name="testB" class="com.baizhi.action.TestBAction" method="testB">
			<result name="ok">/index.jsp</result>
		</action>
	</package>
</struts>

注意:如果action中显示配置了使用拦截器,那么默认拦截器就失效了

最终问题

配置了自定义拦截器之后,action不能收参了?

struts自动收参的代码,写在了一个拦截器里,被配置在了struts-default包中,配置为默认使用的拦截器

当你在某个action中显示配置使用自定拦截器,默认拦截器就失效了,导致不能收参

解决办法;手动显示的配置使用默认拦截器即可

<package name="p1" extends="father">
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<interceptor-ref name="bInt"></interceptor-ref>
      struts的默认拦截器
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
		<action name="b" class="com.baizhi.action.TestAction" method="mb">
			<result name="ok">/index.jsp</result>
		</action>
</package>

显示配置了使用拦截器,那么默认拦截器就失效了

最终问题

配置了自定义拦截器之后,action不能收参了?

struts自动收参的代码,写在了一个拦截器里,被配置在了struts-default包中,配置为默认使用的拦截器

当你在某个action中显示配置使用自定拦截器,默认拦截器就失效了,导致不能收参

解决办法;手动显示的配置使用默认拦截器即可

<package name="p1" extends="father">
		<action name="a" class="com.baizhi.action.TestAction" method="ma">
			<interceptor-ref name="bInt"></interceptor-ref>
      struts的默认拦截器
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result name="ok">/index.jsp</result>
		</action>
		<action name="b" class="com.baizhi.action.TestAction" method="mb">
			<result name="ok">/index.jsp</result>
		</action>
</package>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值