• 手动的写一个structs


    为了更好的学习框架的运行机制,这里开始学习框架之前,介绍一个简单的自定义的框架。

    需求:

      登录:id:aaa,pwd:888登录成功之后,跳转到,index.jsp页面并显示,欢迎你,aaa

      注册,页面,输入用户名密码,点击注册。注册成功之后,将会跳转到登录界面。

      重在了解前后的这个逻辑,所以把后天是写死的。

    entity层

      就一个User

    package cn.itcast.entity;
    
    public class User {
    
        private String name;
        private String pwd;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        
    }
    View Code

    接着是到层

      就一个UserDao,模拟了注册,登录,没有都是写死的

     1 package cn.itcast.dao;
     2 
     3 import cn.itcast.entity.User;
     4 
     5 
     6 public class UserDao {
     7 
     8     // 模拟登陆
     9     public User login(User user){
    10         if ("tom".equals(user.getName()) && "888".equals(user.getPwd()) ){
    11             // 登陆成功
    12             return user;
    13         }
    14         // 登陆失败
    15         return null;
    16     }
    17     
    18     // 模拟注册
    19     public void register(User user) {
    20         System.out.println("注册成功:用户," + user.getName());
    21     }
    22 }
    View Code

    service层还和以前一样,没有什么区别,直接使用就可以了这里也就一个UserService

     1 package cn.itcast.service;
     2 
     3 import cn.itcast.dao.UserDao;
     4 import cn.itcast.entity.User;
     5 
     6 
     7 public class UserService {
     8     
     9     private UserDao ud = new UserDao();
    10 
    11     // 模拟登陆
    12     public User login(User user){
    13         return ud.login(user);
    14     }
    15     
    16     // 模拟注册
    17     public void register(User user) {
    18         ud.register(user);
    19     }
    20 }
    View Code

    framewoek层,

      这是手动缩写的这个,mystructs的核心部分。

      以往在ervlet层中写servlet,反观一下,servlet层在mvc中负责control的角色:获取参数,调用service,跳转页面。无非就这三大块。

      不同的页面请求提交到不同的servt,但最终从宏观上来说无非是上面的三块内容。于是我们想做到的是,值写一个servlet这里我们命名为ActionServlet,这个类的功能,就是统筹全局请求的分配,针对比如像http:localhost:8080/mystucets/login.action的请求,ActionServlet解析出login,把这个请求,交给LoginAction类处理,类似于register.action的请求交给对应的RegisterAction处理。  

      要想完成这种准确无误的转发关系,或者说是一种映射。那么ActionServlet要一个根据,这个根据就是一个ActionSerlet可以查找的表。我们先来看一个,上面设想的架构的时序流

    1.就收请求,http:localhost:8080/mystucets/login.action,解析出login

    2。转发给LoginAction处理,LoginAction调用login()方法,这个方法执行完成之后返回一个returnFlag标志,loginSuccess表示登陆成功,loginFial表示登录失败,

    3.ActionServlet根据返回的returnFlag判断跳转的页面,当然要先查询配置(映射表)文件,获取对应的跳转page,以及跳转的方式(转发或者重定向)

    我们需要一个配置文件,这个配置文件是一个xml文件,这个文件我们根据,login或者register找到所对应的Action类,进一步找到跳转的可能,设计这个mystructs.xml的配置文件如下:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <mystruts>
     3     <package>
     4         <!-- 配置请求路径,与处理action类的关系 -->
     5         <!-- 
     6             1. 请求路径与处理Action的关系
     7                  /login = LoginAction                          login
     8                         success = /index.jsp                     登陆成功(重定向)
     9                         loginFaild  = /login.jsp                 登陆失败
    10             
    11          -->
    12         <action name="login" class="cn.itcast.framework.action.LoginAction" method="login">
    13             <result name="loginSuccess" type="redirect">/index.jsp</result>
    14             <result name="loginFaild">/login.jsp</result>
    15         </action>
    16         
    17         <action name="register" class="cn.itcast.framework.action.RegisterAction" method="register">
    18             <result name="registerSuccess">/login</result>
    19         </action>
    20         
    21     </package>
    22 
    23 </mystruts>

      对于一个项目而言,要处理的请求有很多,也就说有很多的XxxAction,这是需要我们,那么对应的mystructs.xml文件就会很大,我们不会每次都来查找解析这个xml文件,而且对于需要同时管理很多信息时,常见的做法是把这若干信息封装到一些bean中,讲分页的时候已经使用过这种策略了。每个<action>封装到对应的ActionMapping类中,每个<result>封装到Result类中,因为每个<action>中包含若干的<result>所以每个ActionMapping总包含若干的<Result>。ActionMapping和Result的设计如下:

    ActionMapping:

     1 package cn.itcast.framework.bean;
     2 
     3 import java.util.Map;
     4 
     5 /**
     6  * 封装action节点
     7  *      <action name="login" class="cn.itcast.framework.action.LoginAction" method="login">
     8             <result name="success" type="redirect">/index.jsp</result>
     9             <result name="loginFaild">/login.jsp</result>
    10         </action>
    11         
    12  * @author Jie.Yuan
    13  *
    14  */
    15 public class ActionMapping {
    16 
    17     // 请求路径名称
    18     private String name;
    19     // 处理aciton类的全名
    20     private String className;
    21     // 处理方法
    22     private String method;
    23     // 结果视图集合
    24     private Map<String,Result> results;
    25     
    26     public String getName() {
    27         return name;
    28     }
    29     public void setName(String name) {
    30         this.name = name;
    31     }
    32     public String getClassName() {
    33         return className;
    34     }
    35     public void setClassName(String className) {
    36         this.className = className;
    37     }
    38     public String getMethod() {
    39         return method;
    40     }
    41     public void setMethod(String method) {
    42         this.method = method;
    43     }
    44     public Map<String, Result> getResults() {
    45         return results;
    46     }
    47     public void setResults(Map<String, Result> results) {
    48         this.results = results;
    49     }
    50     
    51     
    52     
    53 }
    View Code

    Result:

     1 package cn.itcast.framework.bean;
     2 
     3 /**
     4  * 封装结果视图
     5  * <result name="success" type="redirect">/index.jsp</result>
     6  * @author Jie.Yuan
     7  *
     8  */
     9 public class Result {
    10 
    11     // 跳转的结果标记
    12     private String name;
    13     // 跳转类型,默认为转发; "redirect"为重定向
    14     private String type;
    15     // 跳转的页面
    16     private String page;
    17     public String getName() {
    18         return name;
    19     }
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23     public String getType() {
    24         return type;
    25     }
    26     public void setType(String type) {
    27         this.type = type;
    28     }
    29     public String getPage() {
    30         return page;
    31     }
    32     public void setPage(String page) {
    33         this.page = page;
    34     }
    35     
    36 }
    View Code

    为了避免每次查询mystructs.xml问价(这样使很消耗时间的),我们的做法是在首次访问ActionServlet的时候,也就是在ActionServlet的init()函数中把mystructs.xml中的内容全部读取出来(在后面的ActionServlet的代码可以看到),读取出来之后我们使用一个ActionMappingManager进行管理,下面是ActionMappingManager类:

      1 package cn.itcast.framework.bean;
      2 
      3 import java.io.InputStream;
      4 import java.util.HashMap;
      5 import java.util.Iterator;
      6 import java.util.List;
      7 import java.util.Map;
      8 
      9 import org.dom4j.Document;
     10 import org.dom4j.Element;
     11 import org.dom4j.io.SAXReader;
     12 
     13 /**
     14  * 加载配置文件, 封装所有的真个mystruts.xml
     15  * @author Jie.Yuan
     16  *
     17  */
     18 public class ActionMappingManager {
     19 
     20     // 保存action的集合
     21     private Map<String,ActionMapping> allActions ;
     22     
     23     public ActionMappingManager(){
     24         allActions = new HashMap<String,ActionMapping>();
     25         // 初始化
     26         this.init();
     27     }
     28     
     29     /**
     30      * 根据请求路径名称,返回Action的映射对象
     31      * @param actionName   当前请求路径
     32      * @return             返回配置文件中代表action节点的AcitonMapping对象
     33      */
     34     public ActionMapping getActionMapping(String actionName) {
     35         if (actionName == null) {
     36             throw new RuntimeException("传入参数有误,请查看struts.xml配置的路径。");
     37         }
     38         
     39         ActionMapping actionMapping = allActions.get(actionName);
     40         if (actionMapping == null) {
     41             throw new RuntimeException("路径在struts.xml中找不到,请检查");
     42         }
     43         return actionMapping;
     44     }
     45     
     46     // 初始化allActions集合
     47     private void init() {
     48         /********DOM4J读取配置文件***********/
     49         try {
     50             // 1. 得到解析器
     51             SAXReader reader = new SAXReader();
     52             // 得到src/mystruts.xml  文件流
     53             InputStream inStream = this.getClass().getResourceAsStream("/mystruts.xml");
     54             // 2. 加载文件
     55             Document doc = reader.read(inStream);
     56             
     57             // 3. 获取根
     58             Element root = doc.getRootElement();
     59             
     60             // 4. 得到package节点
     61             Element ele_package = root.element("package");
     62             
     63             // 5. 得到package节点下,  所有的action子节点
     64             List<Element> listAction = ele_package.elements("action");
     65             
     66             // 6.遍历 ,封装
     67             for (Element ele_action : listAction) {
     68                 // 6.1 封装一个ActionMapping对象
     69                 ActionMapping actionMapping = new ActionMapping();
     70                 actionMapping.setName(ele_action.attributeValue("name"));
     71                 actionMapping.setClassName(ele_action.attributeValue("class"));
     72                 actionMapping.setMethod(ele_action.attributeValue("method"));
     73                 
     74                 // 6.2 封装当前aciton节点下所有的结果视图
     75                 Map<String,Result> results = new HashMap<String, Result>();
     76                 
     77                 // 得到当前action节点下所有的result子节点
     78                  Iterator<Element> it = ele_action.elementIterator("result");
     79                  while (it.hasNext()) {
     80                      // 当前迭代的每一个元素都是 <result...>
     81                      Element ele_result = it.next();
     82                      
     83                      // 封装对象
     84                      Result res = new Result();
     85                      res.setName(ele_result.attributeValue("name"));
     86                      res.setType(ele_result.attributeValue("type"));
     87                      res.setPage(ele_result.getTextTrim());
     88                      
     89                      // 添加到集合
     90                      results.put(res.getName(), res);
     91                  }
     92                 
     93                 // 设置到actionMapping中
     94                 actionMapping.setResults(results);
     95                 
     96                 // 6.x actionMapping添加到map集合
     97                 allActions.put(actionMapping.getName(), actionMapping);
     98             }
     99             
    100             
    101         } catch (Exception e) {
    102             throw new RuntimeException("启动时候初始化错误",e);
    103         }
    104     }
    105 }
    View Code

      我们说了,ActionServlet位居中枢相当于行军主将,居中调遣需要冲锋陷阵的士卒(XxxAction),这里就是LoginAction和RegisterAction,下面是他们的定义:

      LoginAction:

     1 package cn.itcast.framework.action;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.ServletException;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 
     9 import cn.itcast.entity.User;
    10 import cn.itcast.service.UserService;
    11 
    12 /**
    13  * Action表示动作类 1. 一个servlet对应一个action 2. action中负责处理具体的请求
    14  * 
    15  * @author Jie.Yuan
    16  * 
    17  */
    18 public class LoginAction {
    19     
    20     public Object execute(HttpServletRequest request, HttpServletResponse response)
    21     throws ServletException, IOException {
    22         return null;
    23     }
    24 
    25     /**
    26      * 处理登陆请求
    27      */
    28     public Object login(HttpServletRequest request, HttpServletResponse response)
    29             throws ServletException, IOException {
    30         Object uri = null;
    31 
    32         // 1. 获取请求数据,封装
    33         String name = request.getParameter("name");
    34         String pwd = request.getParameter("pwd");
    35         User user = new User();
    36         user.setName(name);
    37         user.setPwd(pwd);
    38 
    39         // 2. 调用Service
    40         UserService userService = new UserService();
    41         User userInfo = userService.login(user);
    42         // 3. 跳转
    43         if (userInfo == null) {
    44             // 登陆失败
    45 //            request.getRequestDispatcher("/login.jsp").forward(request,
    46 //                    response);
    47 //            uri = request.getRequestDispatcher("/login.jsp");
    48             uri = "loginFaild";   // loginFaild  = /login.jsp
    49         } else {
    50             // 登陆成功
    51             request.getSession().setAttribute("userInfo", userInfo);
    52             // 首页
    53 //            response.sendRedirect(request.getContextPath() + "/index.jsp");
    54 //            uri = "/index.jsp";
    55             uri = "loginSuccess";  // loginSuccess = /index.jsp
    56         }
    57         return uri;
    58     }
    59 }
    View Code

      Register类:

    package cn.itcast.framework.action;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import cn.itcast.entity.User;
    import cn.itcast.service.UserService;
    
    public class RegisterAction {
    
        public Object register(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            Object uri;
    
            // 1. 获取请求数据,封装
            String name = request.getParameter("name");
            String pwd = request.getParameter("pwd");
            User user = new User();
            user.setName(name);
            user.setPwd(pwd);
    
            // 2. 调用Service
            UserService userService = new UserService();
            userService.register(user);
            // 3. 跳转
    //        request.getRequestDispatcher("/login.jsp").forward(request, response);
            //uri = request.getRequestDispatcher("/login.jsp");
            return "registerSuccess"; //返回注册的标记;   registerSuccess = /login.jsp
    
        }
    }
    View Code

      中军主帅ActionServlet类:

     1 package cn.itcast.framework;
     2 
     3 import java.io.IOException;
     4 import java.lang.reflect.Method;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 import cn.itcast.framework.bean.ActionMapping;
    12 import cn.itcast.framework.bean.ActionMappingManager;
    13 import cn.itcast.framework.bean.Result;
    14 
    15 /**
    16  * 核心控制器,此项目只有这一个servlet
    17  * 1. 拦截所有的*.action为后缀的请求
    18  * 2. 请求:http://localhost:8080/mystruts/login.action
    19  *           http://localhost:8080/mystruts/register.action
    20 
    21  * @author Jie.Yuan
    22  *
    23  */
    24 public class ActionServlet extends HttpServlet{
    25     
    26     private ActionMappingManager actionMappingManager;
    27     
    28     // 只执行一次  (希望启动时候执行)
    29     @Override
    30     public void init() throws ServletException {
    31         System.out.println("1111111111111111ActionServlet.init()");
    32         actionMappingManager = new ActionMappingManager();
    33     }
    34 
    35     // http://localhost:8080/mystruts/login.action
    36     @Override
    37     protected void doGet(HttpServletRequest request, HttpServletResponse response)
    38             throws ServletException, IOException {
    39         
    40         try {
    41             // 1. 获取请求uri, 得到请求路径名称   【login】
    42             String uri = request.getRequestURI();
    43             // 得到 login
    44             String actionName=uri.substring(uri.lastIndexOf("/")+1, uri.indexOf(".action"));
    45             
    46             // 2. 根据路径名称,读取配置文件,得到类的全名   【cn..action.LoginAction】
    47             ActionMapping actionMapping = actionMappingManager.getActionMapping(actionName);
    48             String className = actionMapping.getClassName();
    49             
    50             // 当前请求的处理方法   【method="login"】
    51             String method = actionMapping.getMethod();
    52             
    53             // 3. 反射: 创建对象,调用方法; 获取方法返回的标记
    54             Class<?> clazz = Class.forName(className);
    55             Object obj = clazz.newInstance();  //LoginAction loginAction = new LoginAction();
    56             Method m = clazz.getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class );
    57             // 调用方法返回的标记
    58             String returnFlag =  (String) m.invoke(obj, request, response);
    59             
    60             // 4. 拿到标记,读取配置文件得到标记对应的页面 、 跳转类型
    61             Result result = actionMapping.getResults().get(returnFlag);
    62             // 类型
    63             String type = result.getType();
    64             // 页面
    65             String page = result.getPage();
    66             
    67             // 跳转
    68             if ("redirect".equals(type)) {
    69                 response.sendRedirect(request.getContextPath() + page);
    70             } else {
    71                 request.getRequestDispatcher(page).forward(request, response);
    72             }
    73         } catch (Exception e) {
    74             e.printStackTrace();
    75         }
    76     }
    77     
    78     
    79     @Override
    80     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    81             throws ServletException, IOException {
    82         doGet(req, resp);
    83     }
    84 }
    View Code

    注意了,这里只有一个ActionServlet处理所有的页面请求,将处理所有的http:localhost:8080/mystructs/*.action请求,那么就要在web.xml中配置ActionServlet的<pattern-url>时使用模糊匹配具体如下:

     1 <!-- 核心控制器 -->
     2   <servlet>
     3     <servlet-name>ActionServlet</servlet-name>
     4     <servlet-class>cn.itcast.framework.ActionServlet</servlet-class>
     5     <!-- 启动时候执行servlet初始化方法 -->
     6     <load-on-startup>1</load-on-startup>
     7   </servlet>
     8   <servlet-mapping>
     9     <servlet-name>ActionServlet</servlet-name>
    10     <url-pattern>*.action</url-pattern>
    11   </servlet-mapping>

    为了保证启动时执行ActionServlet的init()方法,还用了一个参数<load-on-startup>1</load-on-startup>,使用这个参数,init函数将会在启动服务器之后调用,不然的第一次访问ActionServlet,ActionServlet创建对象时才会执行init函数。

    到这里,这个简单的模拟项目就结束了,就可以开始测试了。我们访问http://localhost:8080/mystructs/login.jsp,然后输入用户名aaa和密码888,点击登录于是请求login.action,然后跳转到index.jsp页面看到欢迎你,aaa

  • 相关阅读:
    JS BOM对象 History对象 Location对象
    JS 字符串对象 数组对象 函数对象 函数作用域
    JS 引入方式 基本数据类型 运算符 控制语句 循环 异常
    Pycharm Html CSS JS 快捷方式创建元素
    CSS 内外边距 float positio属性
    CSS 颜色 字体 背景 文本 边框 列表 display属性
    【Android】RxJava的使用(三)转换——map、flatMap
    【Android】RxJava的使用(二)Action
    【Android】RxJava的使用(一)基本用法
    【Android】Retrofit 2.0 的使用
  • 原文地址:https://www.cnblogs.com/OliverZhang/p/6010194.html
Copyright © 2020-2023  润新知