Struts2的API&数据封装(二)
一 servlet的api的访问
1 完全解耦和的方式
完全看不到request、response、session。
(1)创建jsp界面
<h1>struts2的servlet的api的访问</h1> <h3>完全解耦和的方式,方式一</h3> <form method="post" action="${pagecontext.request.contextpath}/requestaction.action" > 姓名:<input type="text" name="name"> 密码:<input type="password" name="password"> <input type="submit" value="提交"> </form>
(2)编写action
/** * 访问servlet api的完全解耦和的方式一 */ public class requestaction extends actionsupport { public requestaction() { system.out.println("action对象被创建了"); } @override public string execute() throws exception { actioncontext actioncontext=actioncontext.getcontext(); map<string, object> map = actioncontext.getparameters(); for (string key:map.keyset() ) { string[] values = (string[]) map.get(key); system.out.println(key +" "+arrays.tostring(values)); } //存值 actioncontext.put("attname","attvalue"); actioncontext.getsession().put("sessname","sessvalue"); actioncontext.getapplication().put("appname","appvalue"); return success; } }
(3)struts_xml
<action name="requestaction" class="com.itheima.demo1.requestaction"> <result name="success" type="redirect">/demo1/demo2.jsp</result> </action>
运行效果图
调用put方法相当于往request域中存数据
注意:这种方式只能获得像 request session application集合中的值,不能操作对象的本身的方法
2 使用servlet的api的原生方式(这种必须要会)
编写jsp
<h3>使用原生的方式,方式二</h3> <form method="post" action="${pagecontext.request.contextpath}/requestaction2.action" > 姓名:<input type="text" name="name"> 密码:<input type="password" name="password"> <input type="submit" value="提交"> </form>
编写action
public class requestaction2 extends actionsupport { @override public string execute() throws exception { httpservletrequest request = servletactioncontext.getrequest(); map<string, string[]> map = request.getparametermap(); for (string key:map.keyset() ) { string[] values = map.get(key); system.out.println(key+" "+arrays.tostring(values)); } request.setattribute("attname","attvalue"); request.getsession().setattribute("sessname","sessvalue11"); servletactioncontext.getservletcontext().setattribute("appname","appvalue11"); return success; } }
运行效果图
这种方式既可以操作域中的数据,也可以操作对象的方法
3 接口注入的方式(这种方式很少用,了解)
action类
public class requestaction3 extends actionsupport implements servletrequestaware,servletcontextaware { private httpservletrequest request; private servletcontext context;//可以通过快捷键来生成 public requestaction3() { system.out.println("action被创建了"); } @override public string execute() throws exception { map<string, string[]> map = request.getparametermap(); for (string key:map.keyset() ) { string[] values = map.get(key); system.out.println(key+""+arrays.tostring(values)); } request.setattribute("attname","attvalues111"); request.getsession().setattribute("sessname","sessvalues2"); context.setattribute("appname","appvalues3");//存到application中 return super.execute() ;//这里是返回sucess,可以查看源代码 } @override public void setservletrequest(httpservletrequest request) { this.request=request; } @override public void setservletcontext(servletcontext servletcontext) { this.context=servletcontext; } }
servlet是单例的,只会创建一个对象。而action是多例的,每一次请求都会创建一个对象
action是线程安全的,action是多例的,在类中定义成员变量不会有线程安全的问题
二 配置结果页面
1 全局结果页面
全局结果页面,指的是这个包底下的都有效
<global-results> <result name="success">/demo1/demo2.jsp</result>
</global-results>
2 局部结果页面
局部结果页面,针对当前的action有效
<action name="requestaction" class="com.itheima.demo1.requestaction"> <result name="success" type="redirect">/demo1/demo2.jsp</result> </action>
result就是用于配置页面的跳转的,里面有两个属性 name type
name的默认值是success,假如返回值是success就不需要写了
type属性:页面跳转的类型,前两种类型经常用,记住
dispacher 默认值,请求转发,action转发jsp
redirect 重定向 action重定向jsp
chain 转发 ,action转发到action
redirctaction 重定向,action重定向action (这个案例中就用到了这个)
stream struts2中提供文件下载的功能(了解)
三 数据封装
1 方式一属性驱动:提供set方法
提供属性set方法的方式 (这种方式很少用,比如文件下载,传过来个文件名)
jsp页面
<h1>struts2的数据封装</h1> <h3>方式一属性驱动:提供set方法</h3> <form action="${pagecontext.request.contextpath}/action1" method="post"> <s:fielderror/> 用户名:<input type="text" name="name"/><br> 密码:<input type="text" name="password" /><br> 年龄:<input type="text" name="age"/><br> 生日:<input type="text" name="birthday"/><br> 工资:<input type="text" name="salary"/><br> <input type="submit" value="提交"> </form>
action类
/** * 方式一属性驱动:提供set方法 */ public class action1 extends actionsupport { private string name; private string password; private integer age; private date birthday; private double salary;//工资 //需要提供set方法 public void setname(string name) { this.name = name; } public void setpassword(string password) { this.password = password; } public void setage(integer age) { this.age = age; } public void setbirthday(date birthday) { this.birthday = birthday; } public void setsalary(double salary) { this.salary = salary; } @override public string execute() throws exception { system.out.println(name); system.out.println(password); system.out.println(age); system.out.println(birthday); system.out.println(salary); return none; } }
方式二属性驱动:页面中提供表达式(可以同时向多个对象中同时封装数据)
在action中创建一个私有对象,提供get和set方法,一定要提供get方法
在页面中用user.的方式
jsp界面
<h3>方式二:属性驱动,提供页面表达式</h3> <form action="${pagecontext.request.contextpath}/action2" method="post"> 用户名:<input type="text" name="user.name"/><br> 密码:<input type="text" name="user.password" /><br> 年龄:<input type="text" name="user.age"/><br> 生日:<input type="text" name="user.birthday"/><br> 工资:<input type="text" name="user.salary"/><br> <input type="submit" value="提交"> </form>
编写action
/** * 二 属性驱动:页面中提供表达式 */ public class action2 extends actionsupport { //创建一个私有对象,提供get和set方法,一定要提供get方法 private user user; public user getuser() { //在拦截器中获取到user对象 return user; } public void setuser(user user) { this.user = user; } @override public string execute() throws exception { system.out.println(user); return none; } }
方式三:采用模型驱动的方式(开发中最常用的方式)
模型驱动:只须实现一个接口,提供一个对象,页面不用改
在action中实现模型驱动的接口(modeldriven),后面跟上对象的泛型
使用的对象,必须手动提供对象的实例(new这个对象)
缺点:只能同时向一个对象中封装数据(一般开发中都是同时向一个对象中封装数据)
jsp界面
<h3>方式一:提供set方法</h3> <form action="${pagecontext.request.contextpath}/action3" method="post"> 用户名:<input type="text" name="name"/><br> 密码:<input type="text" name="password" /><br> 年龄:<input type="text" name="age"/><br> 生日:<input type="text" name="birthday"/><br> 工资:<input type="text" name="salary"/><br> <input type="submit" value="提交"> </form>
编写action类
** * 方式三:采用模型驱动的方式 */ public class action3 extends actionsupport implements modeldriven<user> { private user user=new user();//创建实例 @override public user getmodel() { //实例化对象 return user; } @override public string execute() throws exception { system.out.println(user); return none; } }
2 封装复杂数据到list集合中
jsp界面
<h1>struts2封装复杂数据</h1> <h3>封装数据到list集合中</h3> <form action="${pagecontext.request.contextpath}/productaction1.action" method="post"> 商品名称:<input type="text" name="products[0].name"><br> 商品价格:<input type="text" name="products[0].price"><br> 商品名称: <input type="text" name="products[1].name"><br> 商品价格: <input type="text" name="products[1].price"><br> 商品名称: <input type="text" name="products[2].name"><br> 商品价格: <input type="text" name="products[2].price"><br> <input type="submit" value="提交数据">
</form>
编写action
/** * 封装数据到list集合中 */ public class productaction1 extends actionsupport { private list<product> products; public list<product> getproducts() { return products; } public void setproducts(list<product> products) { this.products = products; } @override public string execute() throws exception { system.out.println(products); return none; } }
3封装复杂数据到map集合中
jsp界面
<h3>封装数据到map集合中</h3> <form action="${pagecontext.request.contextpath}/productaction2.action" method="post"> 商品名称:<input type="text" name="map['one'].name"><br> 商品价格:<input type="text" name="map['one'].price"><br> 商品名称: <input type="text" name="map['two'].name"><br> 商品价格: <input type="text" name="map['two'].price"><br> 商品名称: <input type="text" name="map['three'].name"><br> 商品价格: <input type="text" name="map['three'].price"><br> <input type="submit" value="提交数据"> </form>
编写action类
** * 封装数据到map集合中 */ public class productaction2 extends actionsupport { private map<string,product> map; public map<string, product> getmap() { return map; } public void setmap(map<string, product> map) { this.map = map; } @override public string execute() throws exception { //遍历map集合 for (string key :map.keyset() ) { product product = map.get(key); system.out.println(key+" "+product); } return none; } }
4 写程序时遇到的错误
(1)input视图(报了input的异常,可以配一个input)
引入一个struts2的标签库
invalid field value for field "age".
(2)jsp页面中报element is not closed
两个form表单写到了一个表单中