Struts2的配置文件:
下面是它的配置顺序
web.xml
Default.properties
Struts-default.xml
Struts-plugin.xml
Struts.xml
<package name="one-package" extends="struts-default">
<action name="one" class="cn.struts2.action.OneAction">
<result>/jsps/show.jsp</result>
</action>
</package>
1:extends="struts-default"继承且使用系统包中定义的资源
<package name="one-package" extends="struts-default">
<global-results>
<!-- 如果没有,则找当前这个包中有没有全局的结果定义
如果当前包中没有定义,则去父包中找有没有名称叫name=success的结果定义
-->
<result>/jsps/show.jsp</result>
</global-results>
<action name="one" class="cn.struts2.action.OneAction">
</action>
</package>
<package name="two-package" extends="one-package">
<action name="two" class="cn.struts2.action.TwoAction">
<!-- 如果在twoAction的返回success字符串将会查找名称为name=success的result -->
</action>
</package>
2:namespace
<!-- namespace的默认值=/(当前项目的根),如果写入其他的值,则访问里面的的action为:
http://ip:port/project/aaa/two[.action]
-->
<package name="two-package" extends="one-package" namespace="/aaa">
<action name="two" class="cn.struts2.action.TwoAction">
<!-- 如果在twoAction的返回success字符串将会查找名称为name=success的result -->
</action>
</package>
3:action
action可以是:
1:pojo简单java对象
如:
package cn.struts2.action;
public class OneAction {
public String execute(){
System.err.println("Hello:"+this);
return "success";
}
}
2:可以实现接口Action
public class OneAction implements Action {
@Override
public String execute(){
System.err.println("Hello:"+this);
return SUCCESS;///可以直接使用Action中定义的常量
}
}
3:可以继承一个类:ActionSupport
好处是:
1:可以使用常量。
2:提供验证功能。
3:可以访问国际化的信息。
提供验证功能。
public interface Validateable {
/**
* Performs validation.
*/
void validate();
}
public class OneAction extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute(){
System.err.println("2:Hello:"+this);
return SUCCESS;///可以直接使用Action中定义的常量
}
@Override
public void validate() {
System.err.println("1......先 验证");
if(name==null){
addFieldError("name", "姓名不能为空");
}
}
}
<action name="one" class="cn.struts2.action.OneAction">
<result name="success">/jsps/show.jsp</result> //验证成功
<result name="input">/index.jsp</result> //验证不成功
</action>
表单:
<s:fielderror></s:fielderror> 显示错误信息
<form action="one" method="post">
name:<input name="name" type="text"><br>
<input type="submit">
</form>
访问国际化信息:
两种方式配置国际化文件:
@Override
public void validate() {
System.err.println("1......先 验证");
if (name == null || name.trim().equals("")) {
addFieldError("name", getText("nameError"));
}
}
引用方式:
<!-- 配置资源文件 -->
<constant name="struts.custom.i18n.resources" value="msg"></constant>
4:关于action的扩展名
<action name="one" class="cn.struts2.action.OneAction">
则可以通过以下的方式来访问:
http://ip:port/project/one
http://ip:port/project/one.action
在s2的常量里面配置了对*.action的识别:
struts.action.extension=action,,
修改这个常量:
<!-- 修改默认的扩展名 -->
<constant name="struts.action.extension" value="action,,"></constant>
5:动态的调用某些个方法
public class OneAction {
public String say() {
System.err.println("say.....");
return Action.SUCCESS;
}
public String hi() {
System.err.println("hi.....");
return Action.SUCCESS;
}
public String execute() {
System.err.println("execute...");
return Action.SUCCESS;
}
}
1:配置的方式,默认的是execute
<action name="one" class="cn.struts2.action.OneAction">
<result>/jsps/show.jsp</result>
</action>
<action name="onehi" class="cn.struts2.action.OneAction" method="hi">
<result>/jsps/show.jsp</result>
</action>
<action name="onesay" class="cn.struts2.action.OneAction" method="say">
<result>/jsps/show.jsp</result>
</action>
缺点:配置太多。
2:使用通配置符号 *
<!-- 在struts2.3.x版本中直接使用*即可,但是到了struts2.5版本中必须要声明方法可以这样去调用 -->
<package name="one-package" extends="struts-default" strict-method-invocation="false">
<action name="one*" class="cn.struts2.action.OneAction" method="{1}">
<result>/jsps/show.jsp</result>
</action>
</package>
能不能在name里面使用/符号
<!-- 修改默认的扩展名 -->
<constant name="struts.action.extension" value="action,,"></constant>
<!-- 配置在name中,可以带 有斜线 -->
<constant name="struts.enable.SlashesInActionNames" value="true"></constant>
<!-- 配置资源文件 -->
<constant name="struts.custom.i18n.resources" value="msg"></constant>
<!-- 在struts2.3.x版本中直接使用*即可,但是到了struts2.5版本中必须要声明方法可以这样去调用 -->
<package name="one-package" extends="struts-default" strict-method-invocation="false">
<action name="one/*" class="cn.struts2.action.OneAction" method="{1}">
<result>/jsps/show.jsp</result>
</action>
</package>
3:直接使用struts2的 !(棒符号)实现动态的方法调用
struts.enable.DynamicMethodInvocation = false 是否支持!符号
<!-- 是否支持!符号 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
http://localhost/20160615/one!hi.action
6:接收参数
req.getPamater(...)/getParameterValue(..)
两种方式:
1: 属性驱动
Get/set方法
2:模型驱动
实现一个接口:ModelDriven
public class OneAction {
private String name;
private Integer age;
private String[] hobby;// List<String>/Set<String>
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
http://localhost/20160615/one?name=Jack&age=90&hobby=football&hobby=mtv信息: Server startup in 3785 ms
execute...OneAction [name=Jack, age=90, hobby=[football, mtv]]
接收JavaBean - 通过属性驱动:
public class OneAction {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute() {
System.err.println("execute..." + user);
return Action.SUCCESS;
}
}
http://localhost/20160615/one?user.age=90&user.name=Jack&user.hobby=climb
模型驱动:
public class OneAction implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
public String execute() {
System.err.println("execute..." + user);
return Action.SUCCESS;
}
}
http://localhost/20160615/one?name=Jack&age=89&hobby=music&hobby=reading
7:Struts2的容器ValueStack(值栈)
ValueStack两部分组成:
1:栈- Stack
2:上下文对象 Map
什么时间会创建这个栈对象:
当用户每次请求时。
查看ValueStack的结构:
<s:debug/>
如果你的类还实现的ModelDriven则栈中的数据会发生改变:
、
public class OneAction implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
8:Struts2对request对象的包装
修改了getAttribute方法,让当前的获取从ValueStack中获取值。
9:访问域对象
S2为了解藕,将所有对象声明成Map类型。
1:使用解耦的方式来访问域对象
1:使用工具类的静态的方法ActionContext - 重点
ActionContext req = ActionContext.getContext();
req.put("addr", "山东济南在req");
//获取Session
Map<String, Object> session =
req.getSession();
session.put("addr", "地址在Session中");
//获取Application
Map<String, Object> app =
req.getApplication();
app.put("addr", "地址在App中");
2:使用注入的方式来访问
public class OneAction implements ModelDriven<User>, RequestAware, SessionAware, ApplicationAware {
@Override
public void setRequest(Map<String, Object> request) {
request.put("addr", "1111");
}
@Override
public void setApplication(Map<String, Object> application) {
application.put("addr", "33333");
}
@Override
public void setSession(Map<String, Object> session) {
session.put("addr", "22222");
}
2:使用耦合的方式来访问原生的对象
1:使用工具类ServletActionContext
HttpServletRequest req =
ServletActionContext.getRequest();
req.setAttribute("addr", "100");
HttpSession session = req.getSession();
session.setAttribute("addr", "200");
ServletContext app = ServletActionContext.getServletContext();
app.setAttribute("addr", "300");
2:使用注入方式
public class OneAction implements ServletRequestAware, ServletContextAware {
@Override
public void setServletRequest(HttpServletRequest request) {
}
@Override
public void setServletContext(ServletContext context) {
}
10:result
在struts2中,转换到某个页面,都是Result做的<result>/jsps/show.jsp</result>
每一个Result都一个类:
这个类是:
public interface Result extends Serializable {
public void execute(ActionInvocation invocation) throws Exception;
}
result的声明过程:
<result>/jsps/show.jsp</result>
<result name=”success” type=”disatcher”>/jsps/show.jsp</result>
<result name=”success” type=”dispatcher”>
<param name=”location”>/jsps/show.jsp</param>
</result>
type是在struts-default包中定义的 结果类型:
1:chain(转发到另一个Action)/dispatcher(转发到另一个页面)
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
- location (default) - the location to go to after execution (ex. jsp). 转发到哪一个页面
- parse - true by default. If set to false, the location param will not be parsed for Ognl expressions. 是否在location中接收 OGNL表达式。
<result>
<param name="location">/jsps/show.jsp?nm=${name}</param>
<param name="parse">false</param>
</result>
2:redirect重定向到一个页面,redirectAction重定向到一个Ation
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
3:plainText显示为文本
4:自定义Result显示验证码
步1:开发一个自定义的Result
public class ImgResult implements Result {
@Override
public void execute(ActionInvocation invocation) throws Exception {
HttpServletResponse resp =
ServletActionContext.getResponse();
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().print("Hello"+Math.random());
}
}
步2:配置到struts.xml中去
<result-types>
<result-type name="img" class="cn.result.ImgResult"></result-type>
</result-types>
步3:使用这个result
<!-- 默认的class : ActionSupport -->
<action name="abc">
<result type="img"></result>
</action>
package cn.result;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
public class ImgResult implements Result {
@Override
public void execute(ActionInvocation invocation) throws Exception {
// 1:声明图片的大小
int width = 60;
int height = 30;
// 2:
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setFont(new Font("ST", Font.BOLD, 18));
Random r = new Random();
// 声明一个字符串,用于保存4个字符
String sCode = "";
for (int i = 0; i < 4; i++) {
String a = "" + r.nextInt(10);
sCode += a;// 串联字符串
g.setColor(new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)));
g.drawString(a, i * 15, 10 + r.nextInt(20));
}
// 放到session中去
ActionContext.getContext().getSession().put("sCode",sCode);
for (int i = 0; i < 5; i++) {
g.setColor(new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)));
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
g.dispose();
// 输出图片到浏览器
HttpServletResponse response =
ServletActionContext.getResponse();
response.setContentType("image/jpeg");
ImageIO.write(img, "JPEG", response.getOutputStream());// 字节码
}
}
5:如何在Struts2框架下使用ajax
请求一个Action.method() : String 这个字符串可不是指的JSON/XML/TExt/而是
<reuslt name=”xxx”/>
解决的方案是:
1:声明一个公共的页面 json.jsp 里面的代码:${jsonString}
将这个jsp配置成
<global-results>
<result name=”json”>/json.jsp</result>
...
在action中:
Public String execute(){
Actioncton.getContext().put(“jsonString”,”{}.....”);
Return “json”;
2:可以开发一个Result只从栈顶获取数据转成json串显示
public class JsonResult implements Result {
@Override
public void execute(ActionInvocation invocation) throws Exception {
Object obj = ActionContext.getContext().getValueStack().peek();
String json = JSONArray.toJSONString(obj);
HttpServletResponse resp =
ServletActionContext.getResponse();
resp.setContentType("text/plain;charset=UTF-8");
resp.getWriter().print(json);
}
}
public String execute() {
System.err.println("2:执行:execute..." + name);
name = "Alex" + Math.random();
User user = new User();
user.setName("JackMary李四");
user.setAge(89);
user.setHobby(Arrays.asList(new String[] { "AAA", "BB" }));
ActionContext.getContext().getValueStack().push(user);
return Action.SUCCESS;
}