Struts2【入门】

前言

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

为什么要引入struts?

既然Servlet能够完成的事,我们为啥要用框架呢??

于是乎,struts2就应运而生了。


自定义struts

在正式讲解struts之前,我们来看一下,以我们现在的水平,能够怎么优化它。。

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

传统的用户登陆注册

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());    }}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());
   }


}
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);    }}class UserService {

   private UserDao userDao = new UserDao();

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

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

}
@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);    }}"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);

   }
}
@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);    }}"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);

   }
}
<%@ 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>
<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>
<%@ 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>
<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页面就好了


LoginAction

返回的uri分两种情况:

/** * 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;        }    }}
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;
       }
   }
}
    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);        }    }

       //得到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

/** * 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;        }    }}
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;
       }
   }
}
    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);        }    }

       //得到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的代码。

640?wx_fmt=png
这里写图片描述
640?wx_fmt=png
这里写图片描述

可以很清楚地发现:两个实现不同功能的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,只要返回一个标识量即可


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

640?wx_fmt=png
这里写图片描述

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>
<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来对它们封装

/** * 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);    }}
public class ActionMappingManager {

   private Map<String, ActionMapping> map = new HashMap<>();

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

}
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;    }}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;
   }
}
/** * 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;    }}
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);    }}
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);    }}

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和跳转的方法的。。。


效果:

640?wx_fmt=gif
这里写图片描述

自定义MyStruts总结:

由于传统web的Controller模块存在弊端:

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

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

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

在前面,已经说明了为什么要引入Struts框架,其实就是为了提高开发效率…

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


Struts2开发步骤

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

引入jar文件

完整的struts中的jar包有80多个,我们日常开发是不需要那么多个的。一般我们导入的jar包有8个:

640?wx_fmt=png
这里写图片描述

配置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>
   <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";    }}
   @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>
       <!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()中的语句被执行了…

640?wx_fmt=png
这里写图片描述

Struts2执行流程

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

服务器启动

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

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

640?wx_fmt=gif
这里写图片描述

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

我们找到它的源码:

640?wx_fmt=png
这里写图片描述

我们发现了一大堆的Bean,interceptor,result-type,interceptor-stack…下边我来讲解一下它们是干嘛用的…

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


拦截器和过滤器

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

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

过滤器拦截web的所有资源,是Servlet的概念…


小总结

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

注意:此时的拦截器是还没有被调用的


访问阶段

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

值得注意的是:每访问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 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文件进行描述

640?wx_fmt=png
这里写图片描述

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

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

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值