Struts2入门这一篇就够了

前言

这是Strtus的开山篇,主要是引入struts框架...为何要引入struts,引入struts的好处是什么,以及对Struts2一个简单的入门....php

为何要引入struts?

既然Servlet可以完成的事,咱们为啥要用框架呢??html

  • 框架帮咱们封装了不少经常使用的功能
    • 把Web带过来的参数自动封装到JavaBean中[之前,咱们刚开始学的时候是单个单个来获取参数的,后来咱们又使用了BeanUtils写工具方法来帮咱们封装]。如今,咱们使用了Struts2的话,那么框架内部就能帮咱们封装了。
  • 更加灵活[不用把路径等信息写死在程序上],对于路径咱们使用配置文件来进行管理,若是目录发生了变化,也不用一个一个去修改每一个程序的路径。
  • 每一个Servlet中都有doGet和doPost这样的方法,不必的。咱们抽取出来,经过配置文件来把这两个方法替换掉,那么咱们的程序就会更加优雅了。

因而乎,struts2就应运而生了。java


自定义struts

在正式讲解struts以前,咱们来看一下,以咱们如今的水平,可以怎么优化它。。web

以用户的登录注册案例来进行说明apache

传统的用户登录注册

  • dao
public class UserDao {

    public User login(User user) {

        if ("aaa".equals(user.getUsername()) && "123".equals(user.getPsd())) {

            System.out.println("登录成功!");
            return user;

        } else {
            System.out.println("登录失败!");
            return null;
        }
    }

    public void register(User user) {

        System.out.println("注册成功!" + user.getUsername());
    }


}
复制代码
  • service
public class UserService {

    private UserDao userDao = new UserDao();

    public User longin(User user) {
        return userDao.login(user);
    }

    public void register(User user) {
        userDao.register(user);
    }

}
复制代码
  • loginServlet
@javax.servlet.annotation.WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet")
public class LoginServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //获得用户带过来的数据,封装到Bean对象中
        String username = request.getParameter("username");
        String psd = request.getParameter("psd");

        User user = new User();
        user.setPsd(psd);
        user.setUsername(username);

        try {
            //调用Service方法
            UserService userService = new UserService();
            userService.longin(user);

            //登录成功跳转到首页
            request.getRequestDispatcher("/index.jsp").forward(request, response);

        } catch (Exception e) {
            e.printStackTrace();

            //登录失败,跳转到相关的提示页面
            request.setAttribute("message","登录失败了!!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        this.doPost(request, response);

    }
}

复制代码
  • registerServlet
@javax.servlet.annotation.WebServlet(name = "RegisterServlet",urlPatterns = "/RegisterServlet")
public class RegisterServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //获得用户带过来的数据,封装到Bean对象中
        String username = request.getParameter("username");
        String psd = request.getParameter("psd");

        User user = new User();
        user.setPsd(psd);
        user.setUsername(username);

        try {
            //调用Service方法
            UserService userService = new UserService();
            userService.register(user);

            //注册成功跳转到登录界面
            request.getRequestDispatcher("/login.jsp").forward(request, response);

            //注册成功,我也能够跳转到首页
            //request.getRequestDispatcher("/index.jsp").forward(request, response);

        } catch (Exception e) {
            e.printStackTrace();

            //注册失败,跳转到相关的提示页面
            request.setAttribute("message","注册失败了!!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        this.doPost(request, response);

    }
}
复制代码
  • login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>


  <form action="${pageContext.request.contextPath}/LoginServlet" method="post">

    用户名:<input type="text " name="username">
    密码:<input type="password " name="psd">
    <input type="submit" value="登录">
  </form>
  </body>
</html>

复制代码
  • register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>


  <form action="${pageContext.request.contextPath}/RegisterServlet" method="post">

    用户名:<input type="text " name="username">
    密码:<input type="password " name="psd">
    <input type="submit" value="注册">
  </form>
  </body>
</html>
复制代码

上面的代码已经通过了测试,是能够跑起来的。安全


①:跳转页面的路径是写死的。我在注册成功了之后,我可以跳转到首页上,也能够跳转到登录的界面上。若是我要选择其中的一个,就必须修改源代码...服务器

②:一个功能对应一个Servlet,太麻烦了...写了LoginServlet,还要写RegisterServlet....微信


新型的用户登录注册

咱们会发现,不管什么Servlet上最终仍是跳转到相对应的JSP页面的...也就是说,第一和第二步骤【封装数据、调用Service】咱们能够封装起来...只要返回uri给Servlet跳转到JSP页面就行了app


LoginAction

返回的uri分两种状况:框架

  • 若是是转发,那么返回的是RequestDispatcher对象
  • 若是是重定向,那么返回的是字符串
/** * Created by ozc on 2017/4/26. * <p> * 一个Action对应一个Servlet,Action负责处理具体的请求 */
public class LoginAction {


    public Object login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        Object uri ;

        //获得用户带过来的数据,封装到Bean对象中
        String username = request.getParameter("username");
        String psd = request.getParameter("psd");

        User user = new User();
        user.setPsd(psd);
        user.setUsername(username);

        try {
            //调用Service方法
            UserService userService = new UserService();
            userService.longin(user);

            //登录成功跳转到首页
            request.getSession().setAttribute("user", user);

            //跳转到首页的时候须要重定向
            //response.sendRedirect(request.getContextPath() + "/index.jsp");

            //若是是重定向,那么返回的是字符串
            uri = "/index.jsp";
            return uri;

        } catch (Exception e) {
            e.printStackTrace();

            //登录失败,跳转到相关的提示页面
            request.setAttribute("message","登录失败了!!!");
            //request.getRequestDispatcher("/message.jsp").forward(request, response);

            //若是是转发,那么返回的是RequestDispatcher对象
            uri = request.getRequestDispatcher("/message.jsp");
            return uri;
        }
    }
}

复制代码
  • LoginServlet就能够写成这样了:
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //获得LoginAction对象
        LoginAction loginAction = new LoginAction();
        Object uri = loginAction.login(request, response);


        //是重定向
        if (uri instanceof String) {
            response.sendRedirect(request.getContextPath() + uri);
        } else {

            //是转发,强转成是RequestDispatcher对象
            ((RequestDispatcher) uri).forward(request, response);
        }
    }

复制代码

RegisterAction

  • RegisterAction
/** * Created by ozc on 2017/4/26. * * 一个Action对应一个Servlet,Action负责处理具体的请求 */
public class RegisterAction {


    public Object register(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        Object uri ;

        //获得用户带过来的数据,封装到Bean对象中
        String username = request.getParameter("username");
        String psd = request.getParameter("psd");

        User user = new User();
        user.setPsd(psd);
        user.setUsername(username);

        try {
            //调用Service方法
            UserService userService = new UserService();
            userService.register(user);

            //登录成功跳转到登录页面
            uri = request.getRequestDispatcher("/login.jsp");
            return uri;

        } catch (Exception e) {
            e.printStackTrace();

            //注册失败,跳转到相关的提示页面
            request.setAttribute("message","注册失败了!!!");
            //request.getRequestDispatcher("/message.jsp").forward(request, response);

            uri = request.getRequestDispatcher("/message.jsp");
            return uri;
        }
    }
}

复制代码
  • RegisterServlet
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //获得RegisterAction
        RegisterAction registerAction = new RegisterAction();

        Object uri = registerAction.register(request, response);

        //是重定向
        if (uri instanceof String) {
            response.sendRedirect(request.getContextPath() + uri);
        } else {

            //是转发,强转成是RequestDispatcher对象
            ((RequestDispatcher) uri).forward(request, response);
        }
    }

复制代码

思考

到目前为止,咱们搞了两个Action类来封装Servlet的逻辑代码,咱们再次看回Servlet的代码。

这里写图片描述

这里写图片描述

能够很清楚地发现:两个实现不一样功能的Servlet仅仅是调用的Action不一样....若是是仅仅调用的Action不一样【经过反射来调用不一样的Action】,那么咱们应该**想到使用一个Servlet来管理整个项目,**也就是说:整个web项目只有一个核心的控制器

问题:

①:咱们在以前是直接指明Servlet的映射路径了,如今要ActionServlet处理全部的请求,咱们只要定一个规则:只要后缀为.action的,那么都交由核心控制器ActionServlet来控制....

②:如今所有的请求已经交由ActionServlet控制,那怎么知道调用的是哪一个Action???咱们能够经过请求的uri,好比:http://localhost:8080/login.action,其中login就表明的是调用LoginAction..也就是说login=LoginAction,咱们能够经过properties文件来配置..

③:如今咱们已经知道了调用的是哪一个Action了,可是Action可能不只仅只有一个方法,咱们还要在调用的时候,指定的方法名是什么.这很简单,通常咱们都是职责分工明确的,method=login....而且,调用的Action和具体的方法也是有关系的,不多是孤立存在的。所以,咱们的配置文件是不能使用properties的,须要使用XML

④:在调用方法的时候,是返回一个Object的uri的,uri的类型多是String、也能够能是RequestDispatcher、而且返回的结果可能有几种状况的【可能跳转到首页,也可能跳转到登录界面】

⑤:Action调用的方法和返回的uri也是是有关系的!.....不一样的Action调用不一样的方法,返回的uri也是不一样的....

⑥:要跳转到哪一个页面上,能够经过标识量来识别....好比:success表示成功执行,若是要重定向那么多加个type类型,若是不重定向就没有type类型..路径使用path来表示..所以,在具体的Action中,就不须要返回具体的uri,只要返回一个标识量便可


画一张图来梳理一下思路:

这里写图片描述


XML配置

咱们能够写出这样的XML配置,当ActionServlet初始化的时候,读取XML配置文件,就知道调用的是什么Action,Action中的什么方法,以及跳转到哪一个页面上了

<?xml version="1.0" encoding="UTF-8" ?>
<mystruts>
    <package>

        <action name="login" className="zhongfucheng.servlet.LoginServlet" method="login">
            <!--是否存在type属性,存在则是重定向,不存在则是转发-->
            <!--result的值表示的就是跳转的路径-->
            <result name="success" type="redirect">/index.jsp</result>
            <result name="fail">/message.jsp</result>

        </action>
        <action name="register" className="zhongfucheng.servlet.RegisterServlet" method="register">
            <!--是否存在type属性,存在则是重定向,不存在则是转发-->
            <!--result的值表示的就是跳转的路径-->
            <result name="success">/message.jsp</result>
            <result name="fail">/message.jsp</result>
        </action>
    </package>

</mystruts>
复制代码

为了更好地管理这些信息,咱们应该使用JavaBean来对它们封装

  • ActionMappingManager-------管理所有的Action
/** * Created by ozc on 2017/4/26. * * 该类管理着所有的Action * * 要管理所有的Action,就须要用一个容器来装载这些Action * * 选择Map集合是最合适的,能够经过key来获得Action,key就是<action name=><action/>中的name属性 * */
public class ActionMappingManager {

    private Map<String, ActionMapping> map = new HashMap<>();
    
    //注意:外界都是经过name来获得对应的Action的,并不会获取获得整个Manager
    public ActionMapping getActionMapping(String name) {
        return map.get(name);
    }

}

复制代码
  • ActionMapping----表示单个的Action
public class ActionMapping {

    //全部的results
    private Map<String, Results> results;

    //关键字name
    private String name;

    //要调用的Action路径
    private String className;

    //Action中的方法
    private String method;

    public Map<String, Results> getResults() {
        return results;
    }

    public void setResults(Map<String, Results> results) {
        this.results = results;
    }

    public String getName() {
        return name;
    }

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

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }
}

复制代码
  • Results---表示的是结果视图
/** * Created by ozc on 2017/4/26. * * 该类表示的是结果视图 * * * */
public class Results {

    //方法返回的标识
    private String name;

    //要跳转的方式
    private String type;

    //要跳转的页面
    private String page;

    public String getName() {
        return name;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getPage() {
        return page;
    }

    public void setPage(String page) {
        this.page = page;
    }
}

复制代码

ActionMappingManager读取配置文件

在ActionMappingManager中,应该读取配置文件,而后把信息所有封装到里边去...

/** * Created by ozc on 2017/4/26. * * 该类管理着所有的Action * * 要管理所有的Action,就须要用一个容器来装载这些Action * * 选择Map集合是最合适的,能够经过key来获得Action,key就是<action name=><action/>中的name属性 * */
public class ActionMappingManager {
    private Map<String, ActionMapping> allAction ;

    public ActionMappingManager() {
        this.allAction = new HashMap<>();

        //读取配置文件信息
        init();

    }


    public void init() {
        /********经过DOM4J读取配置文件信息*********/

        try {
            //获得解析器
            SAXReader saxReader = new SAXReader();

            //读取在类目录下的mystruts.xml文件
            InputStream stream = ActionMappingManager.class.getClassLoader().getResourceAsStream("mystruts.xml");

            //获得表明XML文件的Document对象
            Document document = saxReader.read(stream);

            //经过XPATH直接获得全部的Action节点
            List list = document.selectNodes("//action");

            //获得每一个Action节点
            for (int i = 0; i < list.size(); i++) {
                Element action = (Element) list.get(i);

                //把获得每一个Action的节点信息封装到ActionMapping中
                ActionMapping actionMapping = new ActionMapping();

                String name = action.attributeValue("name");
                String method = action.attributeValue("method");
                String className = action.attributeValue("className");
                actionMapping.setName(name);
                actionMapping.setMethod(method);
                actionMapping.setClassName(className);

                //获得action节点下的全部result节点
                List results = action.elements("result");

                //获得每个result节点
                for (int j = 0; j < results.size(); j++) {
                    Element result = (Element) results.get(j);

                    //把获得每一个result节点的信息封装到Results中
                    Results results1 = new Results();

                    //获得节点的信息
                    String name1 = result.attributeValue("name");
                    String type = result.attributeValue("type");
                    String page = result.getText();

                    results1.setName(name1);
                    results1.setType(type);
                    results1.setPage(page);

                    //把result节点添加到ActionMapping的集合中
                    actionMapping.getResults().put(name1, results1);
                }

                //最后把获得每一个ActionMapping的信息添加到ActionMappingManager中
                allAction.put(name, actionMapping);

            }



        } catch (DocumentException e) {

            new RuntimeException("初始化的时候出错了!“" + e);
        }
    }

    //注意:外界都是经过name来获得对应的Action的,并不会获取获得整个Manager
    public ActionMapping getActionMapping(String name) {
        return allAction.get(name);
    }
}

复制代码

ActionServlet

使用init()方法只加载建立一个ActionManagerMapping对象,并设置在Web容器启动了该Servlet就启动

/** * Created by ozc on 2017/4/26. * * * Web容器一启动的时候,该类就应该加载了,在web.xml文件中配置onloadStart */

public class ActionServlet extends HttpServlet {


    //该对象封装了全部的XML信息
    ActionMappingManager actionMappingManager ;
    @Override
    public void init() throws ServletException {

        //让ActionMappingManager对象只有一个!
        actionMappingManager = new ActionMappingManager();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        try {
            //获得用户的uri
            String uri = request.getRequestURI();

            //截取uri的关键部分-----截完应该是login
            uri = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."));

            //经过uri获得配置文件中的action信息
            ActionMapping actionMapping = actionMappingManager.getActionMapping(uri);

            //获得action的类名,方法名
            String className = actionMapping.getClassName();
            String method = actionMapping.getMethod();

            //经过反射建立出Action的对象,调用对应的方法
            Class t = Class.forName(className);
            Object o = t.newInstance();

            //注意:这里的参数是接口的class,不是单纯的request的class,单纯的class是实现类
            Method m = t.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);

            //调用方法,获得标记
            String returnFlag = (String) m.invoke(o, request, response);


            //经过标记获得result的具体信息
            Results result = actionMapping.getResults().get(returnFlag);
            String type = result.getType();
            String page = result.getPage();

            //判断是重定向仍是转发,为空就是转发,反则是重定向
            if (type == null) {
                response.sendRedirect(page);
            } else {
                request.getRequestDispatcher(request.getContextPath() + page).forward(request, response);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        this.doPost(request, response);

    }
}
复制代码

具体的Action的方法只要返回一个标识量便可,咱们经过标识量来获得具体的跳转页面url和跳转的方法的。。。


效果:

这里写图片描述


自定义MyStruts总结:

因为传统web的Controller模块存在弊端:

  • 一些功能重复使用,代码过于重复了。
  • 跳转的页面写死了。改变需求的时候须要更改源代码

本博文主要模拟Struts的开发流程

  • 使用一个ActionServlet核心控制器来管理所有的Web请求,写XML配置文件,读取配置文件。
  • ActionMapping封装了Action的基本信息,在XML配置文件中就是读取Action的基本信息,封装到JavaBean上,最后使用ActionMapping类的集合统一管理起来。
  • 当用户访问的时候,咱们根据url也就是Action的名称反射出对应的类,来对其进行操做
  • 根据XML文件的配置信息来肯定跳转方法、跳转的url

咱们如今学习的是Struts2,其实Struts1和Struts2在技术上是没有很大的关联的。 Struts2其实基于Web Work框架的,只不过它的推广没有Struts1好,所以就拿着Struts这个名气推出了Struts2框架。

所以,学习Struts2的时候,不了解Struts1是没有任何关系的。

在前面,已经说明了为何要引入Struts框架,其实就是为了提升开发效率...

Struts2框架预先实现了一些功能:

  • 请求数据自动封装
  • 文件上传的功能
  • 对国际化功能的简化
  • 数据效验功能.......等等

Struts2开发步骤

咱们就直接来说解Struts2的开发步骤是什么吧....在了解它的细节以前,先要把配置环境搭好!

引入jar文件

完整的struts中的jar包有80多个,咱们平常开发是不须要那么多个的。通常咱们导入的jar包有8个:

  • commons-fileupload-1.2.2.jar 【文件上传相关包】
  • commons-io-2.0.1.jar【文件上传相关包】
  • struts2-core-2.3.4.1.jar 【struts2核心功能包】
  • xwork-core-2.3.4.1.jar 【Xwork核心包】
  • ognl-3.0.5.jar 【Ognl表达式功能支持表】
  • commons-lang3-3.1.jar 【struts对java.lang包的扩展】
  • freemarker-2.3.19.jar 【struts的标签模板库jar文件】
  • javassist-3.11.0.GA.jar 【struts对字节码的处理相关jar】

这里写图片描述


配置web.xml

在web.xml中配置的过滤器,其实就是在为struts进行初始化工做

值得注意的是:若是该web.xml配置了多个fileter,那么struts的filter须要在最后面!

<!-- 引入struts核心过滤器 -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

复制代码

开发Action

开山篇咱们已经说了,Servlet的业务代码,咱们都使用Action来代替...Action类通常继承着ActionSupport

Action类也叫动做类,处理请求的类。

public class HelloAction extends ActionSupport {

    @Override
    public String execute() throws Exception {

        System.out.println("helloworld");
        
        return "success";
    }
}

复制代码

至于execute()方法是什么,咱们先不要去管它,为啥要返回一个String,咱们也不要去管它....只要记住开发步骤,而且,咱们的Action类是要继承ActionSupport类的

配置struts.xml

至于配置struts.xml,咱们能够在文件中找到相对应的模版代码的...最终修改为下面这个样子就好了:

<?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="hello" extends="struts-default">
    <action name="hello" class="action.HelloAction" method="execute">
        <result name="success">/index.jsp</result>

    </action>
</package>
</struts>

复制代码

看完上面的配置文件,是很是像咱们开山篇写的struts框架的配置文件的....

效果:

在地址栏中直接输入hello,就跳转到index.jsp页面了。而且,execute()中的语句被执行了...

这里写图片描述


Struts2执行流程

咱们来简单地了解一下Struts的执行流程,而后再慢慢对上面的开发步骤的部分进行讲解....

服务器启动

下边我说的都是struts流程的重点:

  • 加载web.xml文件
  • 找到咱们配置的filter中的StrutsPrepareAndExecuteFilter
  • StrutsPrepareAndExecuteFilter在里边执行init()方法
  • 一直到Dispatcher dispatcher = init.initDispatcher(config);,初始化dispatcher
  • 在初始化dispatcher的时候加载struts-default.xml和咱们配置的struts.xml

下面用GIF图来看看它的执行过程:

这里写图片描述

细心的朋友可能会发现,咱们在struts.xml的package节点下,extends了struts-default....那struts-default到底是什么东西呢?

咱们找到它的源码:

这里写图片描述

咱们发现了一大堆的Bean,interceptor,result-type,interceptor-stack...下边我来说解一下它们是干吗用的...

  • bean指定了struts在运行的时候须要建立的对象类型
    • 在运行struts的时候,可能须要建立一些对象,那么就经过Bean来指定
  • interceptor是struts定义的拦截器,一共有32个
    • 前边已经说了,Struts为咱们实现了一些功能,就是经过拦截器来实现的
  • result-type是跳转结果的类型
    • Action业务方法中的返回值,咱们发现几个实用的:redirect【重定向】、dispatcher【转发】、redirectAction【重定向到Action资源】、stream【文件下载的时候用】...跳转结果的类型也在这里定义了
  • interceptor-stack是拦截器的栈
    • 拦截器有32个,咱们可能会使用不少的拦截器,不可能一个一个来调用,因而提供了拦截器栈...其实能够简单当作**文件夹和文件之间的关系 **
  • default-interceptor-ref是默认执行的拦截器栈
  • default-class-ref class是默认的执行Action类

还要补充的就是:默认的拦截器栈有18个拦截器....


拦截器和过滤器

拦截器和过滤器都是拦截资源的

拦截器只拦截Action请求,是struts的概念...

过滤器拦截web的全部资源,是Servlet的概念...


小总结

服务器启动的时候,其实就是加载了web.xml文件,而后调用init()方法去加载struts.xml和struts-default.xml之类的文件.....

注意:此时的拦截器是尚未被调用的


访问阶段

服务器启动的阶段,仅仅是加载了各类的xml文件...那么当咱们访问Action的时候,它的执行流程是怎么的呢?

  • 首先,它会建立咱们在struts.xml中配置的Action对象
  • 接着,它会按照默认的顺序执行18个拦截器【也就是调用默认拦截器栈】
  • 最后,它会执行Action的业务方法【也就是execute(),咱们在struts.xml文件中配置了什么,就执行什么业务方法】

值得注意的是:每访问Action一次,它就会建立一个对象...它并非和Servlet同样只有一个对象...所以它是线程安全的.


深刻讲解struts.xml

这是咱们的struts.xml的内容,相信如今对它也不会太陌生了...

<struts>
<package name="hello" extends="struts-default">
    <action name="hello" class="action.HelloAction" method="execute">
        <result name="success">/index.jsp</result>
    </action>
</package>
</struts>


复制代码

package

package其实就是包,那包用来干什么?包就是用来管理Action

一般来讲,咱们都是一个业务模版对应一个package

name

name是包的名字,值得注意的是,包的名称是不能重复的。


extends

extends表明的是当前包继承着哪一个包。在struts中,包必定要继承着struts-default


abstract

在package中还有abstract这个属性,使用该属性时:代表当前包被其余的包继承...而且,在package下不能有action,不然会出错!


namespace

在package中还有namespace这个属性---名称空间....它是做为路径的一部分的,默认是"/"


actoin

action:配置请求路径与Action类的映射关系


name

name是请求路径的名字


class

class是处理action类的全名


method

method是调用的方法名称


result

result表明的是Action中业务方法返回的值


name

name是action处理返回的值


type

type是跳转的类型


文本值

文本值是跳转的路径


细节

前边已经说了,一个package应该对应一个业务模块..目的就是把职能细分出来...

struts为了让咱们更好地管理xml文件,它还能够这样作:在不一样的模块中用不一样的xml文件进行描述...

这里写图片描述

最后在struts.xml文件中将其引入便可..

<!--struts在运行的时候总会加载这个文件-->
<!--总配置文件总引入其余的文件-->
<struts>
    <include file="privilegeaction/privilege.xml"/>
    <include file="useraction/hello.xml"/>
</struts>

复制代码

若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同窗,能够关注微信公众号:Java3y