Struts2

2017-07-19  本文已影响0人  yzw12138

一、概念

Struts是流行和成熟的基于MVC设计模式的Web应用程序框架。
使用Struts的目的:
为了帮助我们减少在运用MVC设计模型来开发Web应用的时间。
MVC模式
MVC是模型视图控制器(Model View Contoller),一种软件设计典范,用一种业务逻辑,数据,界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同,不需要重新编写业务逻辑。

二、Struts2环境搭建

<filter>
<filter-name>struct2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

这里写完后按住ctrl点击鼠标左键如果可以跳转则证明正确

<!--filter的映射-->
<filter-mapping>
<filter-name>struct2</filter-name>
<url-pattern>/*</url-pattern>
<!--/*是所有的都需要过滤-->
</filter-mapping>

映射与文件的filter-name应该保持一致

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="helloword" class="imooc.acton.StrutsAction">
            <result>/result.jsp</result>
        </action>
    </package>
</struts>

三、工作原理及过程

四、核心配置文件

Paste_Image.png Paste_Image.png Paste_Image.png
struts.xml模板文件
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>

    <!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用 -->
    <include file="struts-default.xml"></include>
    
    
    <!-- package提供了将多个Action组织为一个模块的方式
        package的名字必须是唯一的 package可以扩展 当一个package扩展自
        另一个package时该package会在本身配置的基础上加入扩展的package
        的配置 父package必须在子package前配置 
        name:package名称
        extends:继承的父package名称
        abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
        namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
     -->
    <package name="com.kay.struts2" extends="struts-default" namespace="/test">
        <interceptors>
            <!-- 定义拦截器 
                name:拦截器名称
                class:拦截器类路径
             -->
            <interceptor name="timer" class="com.kay.timer"></interceptor>
            <interceptor name="logger" class="com.kay.logger"></interceptor>
            <!-- 定义拦截器栈 -->
            <interceptor-stack name="mystack">
                <interceptor-ref name="timer"></interceptor-ref>
                <interceptor-ref name="logger"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        
        <!-- 定义默认的拦截器 每个Action都会自动引用
         如果Action中引用了其它的拦截器 默认的拦截器将无效 -->
        <default-interceptor-ref name="mystack"></default-interceptor-ref>
        
        
        <!-- 全局results配置 -->
        <global-results>
            <result name="input">/error.jsp</result>
        </global-results>
        
        <!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
             name:action名称
             class: 对应的类的路径
             method: 调用Action中的方法名
        -->
        <action name="hello" class="com.kay.struts2.Action.LoginAction">
            <!-- 引用拦截器
                name:拦截器名称或拦截器栈名称
             -->
            <interceptor-ref name="timer"></interceptor-ref>
        
            <!-- 节点配置
                name : result名称 和Action中返回的值相同
                type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
             -->
         <result name="success" type="dispatcher">/talk.jsp</result>
         <!-- 参数设置 
             name:对应Action中的get/set方法 
         -->
         <param name="url">http://www.sina.com</param>
        </action>
    </package>
</struts>
Paste_Image.png

五、Struts用法

<action name="addAction" method="add" class="com.imooc.action.HelloWorldAction">
<result>/add.jsp</result>

2、感叹号方式(不推荐)

<struts>
      <package name="default" namespace="/" extends="struts-default">
          <action name="helloWorld" class="com.Action.HelloWorldAction">
               <result >/result.jsp</result>
               <result name="add">/add.jsp</result>
               <result name="update">/update.jsp</result>
         </action>
      </package>
     <!--constant标签的value选项设置为true时,表示开启感叹号方式-->
      <constant name="struts.enable.DynamicMethodInvocation"value="true"></constant>
</struts>

在浏览器中调用不同方法: http://localhost:8080/HelloWorld/HelloWorld!add(或update).action
3、通配符方式
第一个代替{1},第二个代替{2},result里的name是Action的返回值,action的里method是Action里的方法名,调用某个方法时最后目标就输入 {1}_{2}.action;这样可以访问多个Action里的方法.

<action name="*_*" method="{2}" class="com.imooc.action.{1}Action">
      <result >/result.jsp</result>
      <result name="add">/{2}.jsp</result>
      <result name="update">/{2}.jsp</result>
 </action>

在浏览器中调用不同方法:http://localhost:8080/HelloWorld/HelloWorld_add.action

<struts>
      <!--当添加不通包的字配置文件时,添加包名<include file="/a/helloword.xml"> -->
      <include file="helloword.xml"> </include>
      <constant name="struts.i18n.encoding" value="UTF-8"> </constant>
</struts>

helloword配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="*_*" method="{2}" class="com.imooc.action.{1}Action">
               <result >/result.jsp</result>
               <result name="add">/{2}.jsp</result>
               <result name="update">/{2}.jsp</result>
        </action>
    </package>
</struts>
<default-action-ref name="index"></default-action-ref><br>
<action name="index">
     <result>/error.jsp</result>
</action>
<constant name="struts.action.extension" value="action,do,struts2"></constant>

3.在过滤器中配置intt-param参数:

<init-param>
  <param-name>struts.action.extension</param-name>
  <param-value>do,action,strtus2</param-value>
</init-param>
<!--传递用户登录信息-->
<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="name">
    密码:<input type="password" name="password">
    <input type="submit" value="提交"/>
</form>

当传递的参数比较少是,用此种方法。创建一个登录action类,用来处理页面跳转。

public class LoginAction extends ActionSupport {
    //接受页面传来的值
    private String name;
    private String password;
    
    public String login(){
        System.out.println(name);
        return SUCCESS;
    }
    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;
    }   
}

在配置文件中添加一个action。

<action name="LoginAction" method="login" class="imooc.action.LoginAction">
            <result>/success.jsp</result>
        </action>

2、使用DomainModel接受参数,创建实体类定义需要接受的属性,并set/get方法,在Action中创建实体类名属性。并在界面进行指定。
当传递的参数过多时,用此种方法。
定义一个User类,用来接受参数。

public class User {
    private String name;
    private String password;
    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;
    }
}

在Action中创建User类对象来接受参数,此时User不需要实例化。

public class LoginAction extends ActionSupport {

    private User user;
    public String login(){
        System.out.println(user.getName());
        return SUCCESS;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
}

在登录界面设置参数传递目标。

<form action="LoginAction.action" method="post">
        <!--将name值传递给user对象-->
    用户名:<input type="text" name="usre.name">
    密码:<input type="password" name="user.password">
    <input type="submit" value="提交"/>
</form>

3、使用ModelDriver接受参数,在Action中实现ModelDriver<实体类名>接口,并实现方法返回当前需要转换的对象,删除set/get方法,并对 对象 进行实例化,并取消指定。
将LoginAction类继承一个ModelDriven接口,实现接口的getModel()方法,此时User必须实例化。

public class LoginAction extends ActionSupport implements ModelDriven<User>{

    private User user=new User();
    public String login(){
        System.out.println(user.getName());
        return SUCCESS;
    }
    @Override
    public User getModel() {
        // TODO 自动生成的方法存根
        return user;
    }   
}

登录界面不需要再用user进行传递。

<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="name">
    密码:<input type="password" name="password">
    <input type="submit" value="提交"/>
</form>

实际应用中,最好使用第三种方法,即使user对象改变,也不需要改登录界面的那么值。

Paste_Image.png Paste_Image.png
处理结果类型-result标签下还有param标签:
1)location:该属性定义了该视图对应的实际视图资源
2)parse:该参数指定是否可以再实际视图名字中使用OGNL表达式,默认值为TRUE,支持OGNL(Object-Graph Navigation Language)表达式
ognl表达式可以在jsp页面去写,也可以在struts2页面中去写,在实际开发中是不常用的,默认情况下ognl是允许的,是打开状态
<param name="parse">true</param>
<param name="location">...地址</param>
ognl表达式使用:
<param name="location">/${#request.path}.jsp</param>
在action类中对应的方法中写request.setAttribute("path","返回的jsp页面名称");
<action name="LoginAction" method="login" class="imooc.action.LoginAction">
    <result>/success.jsp</result>
    <result name="input">login.jsp</result>
</action>

自动跳转到input界面方式有两种,其一是传入的参数类型转换错误,另一种是添加表单错误。
第一种:User类中添加一个int类型的年龄属性,如果在登录界面输入的年龄为字符串类型,点击提交后,页面直接跳转到input设置的登录界面。
第二种:在Action中添加addFieldError()方法,只要此方法获得值机会返回input界面。

public class LoginAction extends ActionSupport implements ModelDriven<User>{

    private User user=new User();
    public String login(){
        if(user.getName()==null||"".equals(user.getName()))
            this.addFieldError("name", "用户名不能为空");
            return INPUT;
    }
    @Override
    public User getModel() {
        // TODO 自动生成的方法存根
        return user;
    }
}

还可以通过重写validate方法来实现上述功能。

@Override
public void validate() {
        if(user.getName()==null||"".equals(user.getName()))
            this.addFieldError("name", "用户名不能为空");
    }

在登录界面设置

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!--添加次行代码后才能实现-->
<%@ taglib prefix="s" uri="/struts-tags" %>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>???????</title>
</head>
<body>
<form action="LoginAction.action" method="post">
    用户名:<input type="text" name="name"><s:fielderror name="name"></s:fielderror>
    密码:<input type="password" name="password">
    <input type="submit" value="提交"/>
</form>
</body>
</html>

结果类型input的效果
1.当参数类型转换错误时,如age输入框中的类型是字母等情况,方法自动返回input
2.当action中存在addFiledError时:
1)addFileError放在一般执行方法,addFieldError("", "");语句后面有返回input的语句
2)addFileError放在validate()中
3.FileError的表现形式:
在jsp页面中使用<s:fielderror/>标签,该标签name属性为addFieldError方法中的参数fieldName,在jsp页面中使用struts标签,
需要导入标签库 语句:<%@ taglib prefix="s" uri="/struts-tags" %>

六、拦截器

Paste_Image.png Paste_Image.png Paste_Image.png
/*
 * 计算执行Action花费的时间
 */
public class TimerInterceptor extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // 1.执行Action之前
        long start = System.currentTimeMillis();
        // 2.执行下一个拦截器,如果已经是最后一个拦截器,则执行目标Action
        String result = invocation.invoke();
        // 3.执行Action之后
        long end = System.currentTimeMillis();
        System.out.println("执行Action花费的时间:" + (end - start) + "ms");
        return result;
    }
}
Paste_Image.png Paste_Image.png
上一篇 下一篇

猜你喜欢

热点阅读