Struts学习笔记_Action

一,struts运行机制:

 二,namesapce

1,  packsge 解决重名问题

2 , namespace决定了action的访问路径,默认为"",可以接收所有路径的action
namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action, /xxx/index.action,或者/xxx/yyy/index.action.
namespace最好也用模块来进行命名

3, 具体视图的返回可以由用户自己定义的Action来决定
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可
或者实现Action接口
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法

<package name="front" extends="struts-default" namespace="/">
        <action name="index" class="com.bjsxt.struts2.front.action.IndexAction3">//当访问action时,会找到class内容,通过IndexAction3的execute()方法返回的内容
            <result name="success">/ActionIntroduction.jsp</result>                //与result 中的name比对与来决定视图的内容
        </action>
    </package>
public class IndexAction3 extends ActionSupport {
    
    @Override
    public String execute() {
        return "success";
    }
}

4, struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath

<%
  String path = request.getContextPath();

  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  //相当于http://localhost:8080/...
%>

Head里面


<base href="<%=basePath%>" /》


 

5, Action执行的时候并不一定要执行execute方法可以在配置文件中配置Action的时候用method=来指定执行哪个方法

<struts>
    <constant name="struts.devMode" value="true" />
    <package name="user" extends="struts-default" namespace="/user">
        <action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add">
            <result>/user_add_success.jsp</result>
        </action>
        
        <action name="user" class="com.bjsxt.struts2.user.action.UserAction">
            <result>/user_add_success.jsp</result>
        </action>
    </package>
</struts>

  也可以在url地址中动态指定(动态方法调用DMI)(推荐) 

<a href="<%=context %>/user/userAdd">添加用户</a>

    <a href="<%=context %>/user/user!add">添加用户</a>

    前者会产生太多的action,所以不推荐使用

6, 使用通配符,将配置量降到最低
不过,一定要遵守"约定优于配置"的原则

    <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">

            <result>/Student{1}_success.jsp</result>

        </action>

       

        <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">

            <result>/{1}_{2}_success.jsp</result>

            <!-- {0}_success.jsp -->

        </action>

 

7, 参数传递的四个方法:

  • 使用action属性接受参数name=a&age=2;
使用action属性接收参数<a href="user/user!add?name=a&age=8">添加用户</a>
public class UserAction extends ActionSupport {
    
    private String name;
    private int age;
    
    public String add() {
        System.out.println("name=" + name);
        System.out.println("age=" + age);
        return SUCCESS;
    }

    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;
    }
    
    
}
  • 域模型  user.name=a&user.age=2;
使用Domain Model接收参数<a href="user/user!add?user.name=a&user.age=8">添加用户</a>
public class UserAction extends ActionSupport {
    
    private User user;
    //private UserDTO userDTO;
    public String add() {
        System.out.println("name=" + user.getName());
        System.out.println("age=" + user.getAge());
        return SUCCESS;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
}
  • DTO(数据传输对象),

DTO用于解决传入参数和DomainModel中属性不匹配问题。可以先将传入参数传入到DTO中,再将相应的参数传入搭配DomainModel中。

如何是用户登录,希望有一个用户名,一个密码,一个确认密码。可是我们的用户域模型通常只有两个属性:用户名,密码。

那么用域模型就不可以了。那么如何解决这个问题呢?

1、答:可以直接用属性接收,如果喜欢用域模型,则再建立一个user。

2、除了上面方法外,,还有一种方式,就是再定义一个DTO(data transfer object)数据传输对象。,由这个对象,再生成域对象。

 public class UserDTO {

    private String name;

    private String password;

    private String confirmingpassword;

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public String getPassword() {

       return password;

    }

    public void setPassword(String password) {

       this.password = password;

    }

    public String getConfirmingpassword() {

       return confirmingpassword;

    }

    public void setConfirmingpassword(String confirmingpassword) {

       this.confirmingpassword = confirmingpassword;

    }

 

}

在UserAction类中用UserDTO属性

public class UserAction extends ActionSupport {  

       private User user;

       //private UserDTO userDTO;

       public String add(){

              System.out.println("name="+user.getName());

              System.out.println("age="+user.getAge());

              return SUCCESS;

       }

       public User getUser() {

              return user;

       }

       public void setUser(User user) {

              this.user = user;

       }

}

这样前台输入进来的参数,就与UserDTO相匹配了。

然后在UserAction里面处理完之后,再根据UserDTO ,生成User对象。

方法就是从UserDTO里面拿到相应的参数,添加到User里面。

UserDTO就是把参数传递过来,在new User时,再把参数传递给User对象。
  • ModelDriven

实现了ModelDriven接口,当接收到参数时,先new一个action,发现它实现了ModelDrven接口,然后就会调用GetModel()方法并返回User类型的user

使用ModelDriven接收参数<a href="user/user!add?name=a&age=8">添加用户</a>
public class UserAction extends ActionSupport implements ModelDriven<User>{
    
    private User user = new User();
    
    public String add() {
        System.out.println("name=" + user.getName());
        System.out.println("age=" + user.getAge());
        return SUCCESS;
    }

    @Override
    public User getModel() {
        return user;
    }
    
}

8,  传中文参数

    在strust.xaml 中

<constant name="struts.i18n.encoding" value="GBK" /> <!-- internationalization -->

9, 使用addFieldError方法和s:fieldError标签简单处理数据校验

定义一个action

public class UserAction extends ActionSupport {
    private String name;
    
    public String add() {
        if(name == null || !name.equals("admin")) {
            this.addFieldError("name", "name is error"); //通过addFieldError方法把内容写到值栈中,在Jsp中s:fieldError标签或s:property读取
            this.addFieldError("name", "name is too long"); //一个name可有多个值
            return ERROR;
        } 
        return SUCCESS;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
}

在jsp中

<?xml version="1.0" encoding="GB18030" ?>
<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<%@taglib uri="/struts-tags" prefix="s" %> <!-- 添加标签的url ,指向标签所在标签库,prefix指定所用标签的前缀-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
<title>Insert title here</title>
</head>
<body>
    User Add Error!
    <s:fielderror fieldName="name" theme="simple"/>   <!-- 读取值栈中的值方法1-->
    <br />
    <s:property value="errors.name[0]"/>   <!-- 读取值栈中的值方法2,用来去valuestack和context的属性-->
    <s:debug></s:debug><!-- 调试,查看值栈内容-->
</body>
</html>

10,访问web元素

取得Map类型request,session,application的引用

方法一:依赖于容器

public class LoginAction1 extends ActionSupport {
    
    private Map request;
    private Map session;
    private Map application;
    
    public LoginAction1() {
        request = (Map)ActionContext.getContext().get("request");
        session = ActionContext.getContext().getSession();        //actionContext 放置action执行时的内容
        application = ActionContext.getContext().getApplication();
    }
    
    public String execute() {
        request.put("r1", "r1");
        session.put("s1", "s1");
        application.put("a1", "a1");
        return SUCCESS; 
    }
    
    
}

在jsp中

<body>
    User Login Success!
    <br />
    <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br /> <!-- 取得Stack Context中的request-->
    <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
    <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />
    <s:property value="#attr.a1"/><br /><!--不怎么用-->
    <s:property value="#attr.s1"/><br />
    <s:property value="#attr.r1"/><br />
    <s:debug></s:debug>
    <br />
</body>

方法二;DI/IOC,实现了RequestAware,SessionAware, ApplicationAware接口,让struts给我们拿到request。。。(最常用,其他可以不纪)

public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {
    
    private Map<String, Object> request;
    private Map<String, Object> session;
    private Map<String, Object> application;
    
    //DI dependency injection
    //IoC inverse of control
    public String execute() {
        request.put("r1", "r1");
        session.put("s1", "s1");
        application.put("a1", "a1");
        return SUCCESS; 
    }

    @Override
    public void setRequest(Map<String, Object> request) {
        this.request = request;
    }

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
    }

    @Override
    public void setApplication(Map<String, Object> application) {
        this.application = application;
    }
    
    
}

在jsp中

<body>
    User Login Success!
    <br />
    <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br /> <!-- 取得Stack Context中的request-->
    <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
    <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />
    <s:property value="#attr.a1"/><br /><!--不怎么用-->
    <s:property value="#attr.s1"/><br />
    <s:property value="#attr.r1"/><br />
    <s:debug></s:debug>
    <br />
</body>

 获取真实类型 HttpServletRequest, HttpSession, ServletContext的引用(不常用)

方法一:依赖于容器

public class LoginAction3 extends ActionSupport {
    
    private HttpServletRequest request;
    private HttpSession session;
    private ServletContext application;
    
    public LoginAction3() {
        request = ServletActionContext.getRequest();
        session = request.getSession();
        application = session.getServletContext();
    }
    
    public String execute() {
        request.setAttribute("r1", "r1");
        session.setAttribute("s1", "s1");
        application.setAttribute("a1", "a1");
        return SUCCESS; 
    }
    
}

方法二:DI/IOC

public class LoginAction4 extends ActionSupport implements ServletRequestAware {
    
    private HttpServletRequest request;
    private HttpSession session;
    private ServletContext application;
    
    
    
    public String execute() {
        request.setAttribute("r1", "r1");
        session.setAttribute("s1", "s1");
        application.setAttribute("a1", "a1");
        return SUCCESS; 
    }



    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
        this.session = request.getSession();
        this.application = session.getServletContext();
    }
    
}

11,incluse

<struts>
    <constant name="struts.devMode" value="true" />
    <include file="login.xml" />
</struts>

 12,默认的action

<struts>
    <constant name="struts.devMode" value="true" />
    
    <package name="default" namespace="/" extends="struts-default">
        <default-action-ref name="index"></default-action-ref> //放访问的路径不存在时,会跳转到默认的界面
        <action name="index">
            <result>/default.jsp</result>
        </action>
    </package>
</struts>

 

Action总结

  1. 实现一个Action的最常用方式:从ActionSupport继承
  2. DMI动态方法调用   user!add
  3. 通配符配置 * {1} {2} …

    a)         *_*

  4.接收参数的方法(一般用属性或者DomainModel来接收)

  5.简单参数验证addFieldError

    a)         一般不使用Struts2的UI标签

  6.访问Web元素

  a)         Map类型

                         i.              IoC

                       ii.              依赖Struts2

  b)         原始类型

                         i.              IoC

                       ii.              依赖Struts2

  7.包含文件配置

  8.默认action处理

原文地址:https://www.cnblogs.com/enjoy-life-clh/p/4077567.html