1、Struts2的结果视图:
a.局部视图
<package name="p1" extends="default">
<action name="demo1" class="com.example.action.Demo1Action">
<result>/demo1.jspresult>
action>
<action name="demo2">
action>
package>
b.全局视图:
<package name="default" extends="struts-default">
<global-results>
全局视图:访问动作时,如果没有局部视图,则找全局视图
<result name="success" type="dispatcher">/demo1.jspresult>
global-results>
package>
2、result元素的配置:
属性:
name:逻辑视图名称。它对应的是动作方法的返回值。默认值:success。
type:到达目标的形式。默认值:dispatcher。转发。
Struts2提供的结果类型(result type属性)
在struts-default.xml中有定义,可以看看源码就知道
chain:用户转发到另外一个动作。
dispatcher(默认):用于转发到另外一个JSP页面。
freemarker:用于转发到另外一个freemarker模板。(页面静态化)
velocity:用于转发到另外一个velocity模板。
httpheader:用于输出http协议的消息头。
xslt:XML有关的样式
redirect(常用):用于重定向到另外一个JSP页面。
redirectAction(常用):用于重定向到另外一个动作。
stream(常用):用于文件下载(日后再讲。文件上传和下载)
plainText:以纯文本的形式展现页面。输出源码。
3、自定义结果视图:(输出页面上的验证码)
例如我们自定义一个 captcha 输出结果类型
步骤:
a.编写一个类,直接或间接实现com.opensymphony.xwork2.Result接口。一般继承org.apache.struts2.dispatcher.StrutsResultSupport类
public class CaptachaResult extends StrutsResultSupport{
private int width = 120;
private int height = 80;
private int numCount = 4;
private int grLineNum = 100;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setNumCount(int numCount) {
this.numCount = numCount;
}
public void setGrLineNum(int grLineNum) {
this.grLineNum = grLineNum;
}
//实现这个方法,输出你的结果即可
protected void doExecute(String finalLocation, ActionInvocation invocation)
throws Exception {
ValidateCode vc = new ValidateCode(width, height, numCount, grLineNum);
BufferedImage image = vc.getBuffImg();
//输出即可
HttpServletResponse response = ServletActionContext.getResponse();
ImageIO.write(image, "jpeg", response.getOutputStream());
}
}
b.声明结果类型,然后才能使用(struts.xml配置)
<package name="p3" extends="struts-default">
<result-types>
<result-type name="captcha" class="com.example.results.CaptachaResult">result-type>
result-types>
<action name="captcha">
<result name="success" type="captcha">
<param name="width">200param>
result>
action>
package>
c.使用
我们在jsp页面中使用
<body>
<form action="">
username:<input/><br/>
password:<input/><br/>
验证码:<input name="code" size="4"/><img src="${pageContext.request.contextPath}/captcha.action"/><br/>
<input type="submit" value="登录"/>
form>
body>
界面上就可以显示4位数字的随机验证码了。
4、封装请求参数-动态参数注入-方式1:
动态参数注入:(请求参数,用户输入的)。
用Action动作类作为模型对象:
例如:
jsp页面:
<body>
<form action="${pageContext.request.contextPath}/regist.action" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
form>
body>
struts.xml配置:
<package name="p1" extends="struts-default">
<action name="regist" class="com.example.action.UserAction" method="regist">
<result>/success.jspresult>
<result name="login">/login.jspresult>
action>
package>
动作类:
public class UserAction extends ActionSupport {
private String username;
private String password;
public String getUsername() {
return username;
}
//框架会按照表单的name值,调用对应的setter属性
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String regist(){
System.out.println(username+":"+password);
if("wzhting".equals(username)&&"sorry".equals(password))
return SUCCESS;
else
return LOGIN;
}
}
这种方式是直接用动作类来封装请求的参数
5、封装请求参数-动态参数注入-方式2(推荐):
动作类和模型分开
a.编写一个javabean用来封装请求的参数
Person.java:
public class Person implements Serializable {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Person [username=" + username + ", password=" + password + "]";
}
}
b.编写动作类:
PersonAction.java:
public class PersonAction extends ActionSupport {
private Person person = new Person();//这种方法可以直接new个Person对象初始化,也可以不用。
//private Person person;//如果不new,框架也会帮你new出来
public Person getPerson() {
System.out.println("getter");
return person;
}
public void setPerson(Person person) {
System.out.println("setter");
this.person = person;
}
public String regist(){
System.out.println(person);
//如果用户 hehe 密码123 就成功
if("hehe".equals(person.getUsername())&&"123".equals(person.getPassword()))
return SUCCESS;
else
return LOGIN;
}
}
c.编写struts.xml配置文件:
<package name="p2" extends="struts-default" namespace="/person">
<action name="regist" class="com.example.action.PersonAction" method="regist">
<result>/success.jspresult>
<result name="login">/login1.jspresult>
action>
package>
d.编写jsp页面:**(特别注意使用person.username)**
<body>
<form action="${pageContext.request.contextPath}/person/regist.action" method="post">
用户名:<input type="text" name="person.username"/><br/>
密码:<input type="password" name="person.password"/><br/>
<input type="submit" value="登录"/>
form>
body>
这种方式就是动作和模型分开了,比较清晰。
优点;动作类写起来简单点;
弊端:页面需要用到命名空间person.username
6、封装请求参数-动态参数注入-方式3:
模型驱动:ModelDriven
配置的要求就要高一点
a.编写一个javabean用于封装参数:(对属性字段要求比较高)
Customer.java:
//属性和form中的字段名一致
public class Customer implements Serializable {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
b.编写一个动作类:**(这个地方要求比较高)**
CustomerAction.java:
public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{
private Customer customer = new Customer();//注意一定要初始化这个地方
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String regist(){
System.out.println(customer);
if("hehe".equals(customer.getUsername())&&"123".equals(customer.getPassword()))
return SUCCESS;
else
return LOGIN;
}
//此方法会在动作方法执行前先执行;得到当前对应的模型对象并把模型对象压入值栈的栈顶。setUsername先调用栈顶对象的该方法。
public Customer getModel() {
return customer;
}
}
<package name="p3" extends="struts-default" namespace="/customer">
<action name="regist" class="com.example.action.CustomerAction" method="regist">
<result>/success.jspresult>
<result name="login">/login2.jspresult>
action>
package>
d.编写jsp页面:(页面写起来就不用customer.username了,相对简单)
<body>
<form action="${pageContext.request.contextPath}/customer/regist.action" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
form>
body>
优点:页面不需要用到命名空间contomer.username了。
弊端:动作类写法相对麻烦点,写javabean的时候属性要和这个页面的这个name值对应起来。
个人推荐使用第二种方式。
7、封装请求参数-静态参数注入:
动作类:
public class StudentAction extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String regist(){
System.out.println(name);
return null;
}
}
struts.xml配置:
<package name="p4" extends="struts-default" namespace="/student">
<action name="regist" class="com.example.action.StudentAction" method="regist">
<param name="name">游客param>
action>
package>