javaWeb-编写迷你Structs2框架并使用
2017-10-11 13:23
344 查看
miniMVC流程和项目结构:
5.2:在core.web.config中创建ResultConfig对象,封装result节点的属性信息:
5.3:在ActionConfig类中添加成员变量:
并提供getter和setter方法,用于封装action节点中result节点属性信息。
5.4:在过滤器中,解析actions.xml时,在每个action节点迭代时,迭代得出result属性:
5.5:在doFilter中,执行完函数后,得到函数返回值(result的名称),由请求得到action的名称,得到对应ActionConfig对象,由函数返回值得到ActionConfig对象中对应的ResultConfig对象,然后根据请求类型和资源路径跳转到相应界面:
7.2:在web.xml中配置ActionFilter前端控制器:
7.3:书写自己的Action函数,如Product:
7.4:在resources源文件夹中新建actions.xml文件,并配置:
7.5:然后在webapp中随便写个html页面,如abc.html
7.6:访问格式:http://localhost:8080/miniMVC/Product;
1:创建oa.web.action包,并在其中编写两个对象的action,如:EmployeeAction和DepartmentAction:
package com._520it.oa.web.action; public class EmployeeAction { public void excute(){ System.out.println("员工的列表"); } } package com._520it.oa.web.action; public class DepartmentAction { public void excute(){ System.out.println("部门列表"); } }
2.1:在源文件夹resources中编写actions.xml文件,为action节点配置name,class,method属性,代表每次请求时需要执行的对象方法:
<!-- actions.xml --> <?xml version="1.0" encoding="UTF-8"?> <actions> <action name="Employee" class="com._520it.oa.web.action.EmployeeAction" method="excute" /> <action name="Department" class="com._520it.oa.web.action.DepartmentAction" method="excute" /> </actions>
2.2:在包web.core.config中编写ActionConfig类,用来封装每一个actions.xml中action节点的信息(以后只需在actions.xml中添加action节点即可):
package com._520it.core.web.config; //使用lombok完成get/set/toString @Data public class ActionConfig { private String name; private String className; private String method; public ActionConfig(String name, String className, String method) { this.name = name; this.className = className; this.method = method; } }
2.3:在包filter中编写处理请求的过滤器:
//1.解析actions.xml文件,将actions.xml中的action节点封装成对象,在过滤器中的init中封装成ActionConfigMap //2.在doFilter中根据请求中的信息,取出ActionConfigMap中的ActionConfig对象,利用反射创建对象并执行函数 package com._520it.core.web.filter; import java.io.IOException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import com._520it.core.web.config.ActionConfig; /** * @author lq * */ @SuppressWarnings("all") public class ActionFilter implements Filter { //将action对象的配置信息封装成对象,并装在Map中,获取时方便用请求名索引 private Map<String, Object> actionConfigMap = new HashMap<>(); public void init(FilterConfig filterConfig) throws ServletException { //1.获取文档对象 Document doc = getDocument(); //2.获取文档中所有action节点的节点集合 NodeList nodeList = doc.getElementsByTagName("action"); for (int i = 0; i < nodeList.getLength(); i++) { //3.获取每个节点中的属性信息,并封装成配置对象 Element actionEl = (Element) nodeList.item(i); String actionName = actionEl.getAttribute("name"); String actionClassName = actionEl.getAttribute("class"); String actionMethod = actionEl.getAttribute("method"); //4.创建配置文件对象,并放入配置文件对象映射中 ActionConfig actionConfig = new ActionConfig(actionName, actionClassName, actionMethod); actionConfigMap.put(actionName, actionConfig); } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { //1.在过滤器中对请求和相应对象强强转成Http类型,方便处理Http请求相关操作 HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; //2.得到请求中的最后一个/请求的名称 String requestUri = req.getRequestURI(); String actionName = requestUri.substring(requestUri .lastIndexOf("/") + 1); //3.判断配置对象映射中是否含有当前请求的信息 if (!actionConfigMap.containsKey(actionName)) { chain.doFilter(req, resp); } //4.获取当前请求操作的配置对象 ActionConfig actionConfig = (ActionConfig) actionConfigMap.get(actionName); //5.通过反射执行请求对象中的函数 Class clz = Class.forName(actionConfig.getClassName()); Object actionObj = clz.newInstance(); Method method = clz.getMethod(actionConfig.getMethod()); method.invoke(actionObj); } catch (Exception e) { e.printStackTrace(); } } public void destroy() { } //返回文档对象 public Document getDocument() { DocumentBuilderFactory db = DocumentBuilderFactory.newInstance(); try { fec9 DocumentBuilder builder = db.newDocumentBuilder(); return builder.parse(Thread.currentThread().getContextClassLoader() .getResourceAsStream("actions.xml")); } catch (Exception e) { e.printStackTrace(); } throw new RuntimeException("解析action.xml文件失败!"); } }
3.1:如何在对象Action中得到请求中的参数信息,写一个函数ActionContext,用来封装HttpServletRequest和HttpServletResponse:
//1.含HttpServletRequest和HttpServletResponse参数的构造器,方便构造函数。 //2.既然有了这个构造器,已上两个参数就不需要setter方法了。 //3.设置一个静态私有的ActionContext对象: 静态目的就是方便该类的静态方法getContext()能调用它, 私有目的:其他类不能直接调用该变量 package com._520it.core.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ActionContext { private HttpServletRequest req; private HttpServletResponse resp; //虽然此变量是静态的,但是是私有的,和getContext的static不重复 private static ActionContext mContext; public ActionContext(HttpServletRequest req, HttpServletResponse resp) { this.req = req; this.resp = resp; } public static void setContext(ActionContext context){ mContext = context; } public static ActionContext getContext(){ return mContext; } //因为构造器中已经有传req和resp得ActionContext对象,此处创建get即可 public HttpServletRequest getReq() { return req; } public HttpServletResponse getResp() { return resp; } }
3.2:在过滤器中,将当前的环境变量存储到ActionContext对象中,方便在其他对象中操作请求的信息:
ActionContext context = new ActionContext(req, resp); context.setContext(context);
3.3:在对象Action中调用ActionContext对象,以得到请求中的参数信息:
public class EmployeeAction { public void excute(){ System.out.println("员工的列表"); ActionContext context = ActionContext.getContext(); String username = context.getReq().getParameter("username"); System.out.println("username=" + username); } }
4.但此时在对象ActionContext中有线程不安全情况:
public class EmployeeAction { public void excute(){ System.out.println("员工的列表"); try { Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } ActionContext context = ActionContext.getContext(); String username = context.getReq().getParameter("username"); System.out.println("username=" + username); } }
4.1:问题:最后一次请求中的参数值会覆盖前面请求中的参数,主要原因是ActionContext中每次请求使用的是同一个该类中的ActionContext对象成员变量 4.2:解决: 为容易发生线程不安全的变量使用ThreadLocal,ThreadLocal又称为“线程局部变量”,它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突(好比每一个线程都使用的是一个新的变量),相应ActionContext的变化:
private static ThreadLocal<ActionContext> threadLocal = new ThreadLocal<>(); public static void setContext(ActionContext context){ threadLocal.set(context); } public static ActionContext getContext(){ return threadLocal.get(); }
5.在执行完action对象中的函数后跳转到一个页面中:
5.1:在actions.xml中的action节点展开并配置result节点,包含name,type,path,页面名字,请求类型,路径:<actions> <action name="Employee" class="com._520it.oa.web.action.EmployeeAction" method="excute" > <result name="list" type="dispatcher" path="/WEB-INF/views/employee/list.html" /> <result name="edit" type="redirect" path="/WEB-INF/views/employee/edit.html" /> </action> </actions>
5.2:在core.web.config中创建ResultConfig对象,封装result节点的属性信息:
package com._520it.core.web.config; @Data public class ResultConfig { private String name; private String type; private String path; public ResultConfig(String name, String type, String path) { this.name = name; this.type = type; this.path = path; } }
5.3:在ActionConfig类中添加成员变量:
private Map<String, ResultConfig> resultConfigMap = new HashMap<>();
并提供getter和setter方法,用于封装action节点中result节点属性信息。
5.4:在过滤器中,解析actions.xml时,在每个action节点迭代时,迭代得出result属性:
//将action对象的配置信息封装成对象,并装在Map中,获取时方便用请求名索引 private Map<String, ActionConfig> actionConfigMap = new HashMap<>(); private Map<String, ResultConfig> resultConfigMap = new HashMap<>(); public void init(FilterConfig filterConfig) throws ServletException { //1.获取文档对象 Document doc = getDocument(); //2.获取文档中所有action节点的节点集合 NodeList nodeList = doc.getElementsByTagName("action"); for (int i = 0; i < nodeList.getLength(); i++) { //3.获取每个节点中的属性信息,并封装成配置对象 Element actionEl = (Element) nodeList.item(i); String actionName = actionEl.getAttribute("name"); String actionClassName = actionEl.getAttribute("class"); String actionMethod = actionEl.getAttribute("method"); //4.创建配置文件对象,并放入配置文件对象映射中 ActionConfig actionConfig = new ActionConfig(actionName, actionClassName, actionMethod); actionConfigMap.put(actionName, actionConfig); //5.获取文档中所有result节点的节点集合 resultConfigMap = new HashMap<>(); NodeList resultNode = actionEl.getElementsByTagName("result"); for (int j = 0; j < resultNode.getLength(); j++) { Element resultEl = (Element) resultNode.item(j); String resultName = resultEl.getAttribute("name"); String resultType = resultEl.getAttribute("type"); String resultPath = resultEl.getAttribute("path"); ResultConfig resultConfig = new ResultConfig(resultName, resultType, resultPath); resultConfigMap.put(resultName, resultConfig); //6.将该action中所有result节点组成的map对象封装到actionConfig对象中 actionConfig.setResultConfigMap(resultConfigMap); } } }
5.5:在doFilter中,执行完函数后,得到函数返回值(result的名称),由请求得到action的名称,得到对应ActionConfig对象,由函数返回值得到ActionConfig对象中对应的ResultConfig对象,然后根据请求类型和资源路径跳转到相应界面:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
//1.在过滤器中对请求和相应对象强强转成Http类型,方便处理Http请求相关操作
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//2.将当前的环境变量存储到ActionContext对象中,方便在其他对象中操作请求的信息ActionContext context = new ActionContext(req, resp); context.setContext(context);
//3.得到请求中的最后一个/请求的名称
String requestUri = req.getRequestURI();
String actionName = requestUri.substring(requestUri
.lastIndexOf("/") + 1);
//4.判断配置对象映射中是否含有当前请求的信息
if (!actionConfigMap.containsKey(actionName)) {
chain.doFilter(req, resp);
}
//5.获取当前请求操作的配置对象
ActionConfig actionConfig = (ActionConfig) actionConfigMap.get(actionName);
//6.通过反射执行请求对象中的函数
Class clz = Class.forName(actionConfig.getClassName());
Object actionObj = clz.newInstance();
Method method = clz.getMethod(actionConfig.getMethod());
String action = (String) method.invoke(actionObj);
System.out.println("acton=" + action);
//7.通过执行函数返回的result的name,得到该action中确切的ResultConfig对象
ResultConfig resultConfig = actionConfigMap.get(actionName).getResultConfigMap().get(action);
String type = resultConfig.getType();
String path = resultConfig.getPath();
if("dispatcher".equals(type)){
req.getRequestDispatcher(path).forward(req, resp);
System.out.println(path);
}else if("redirect".equals(type)){
resp.sendRedirect(path);
System.out.println(path);
}
} catch (Exception e) {
e.printStackTrace();
}
}
6.导出miniMVC框架:
7.使用jar包:
7.1:导入jar包并buildpath.7.2:在web.xml中配置ActionFilter前端控制器:
<filter> <filter-name>ActionFilter</filter-name> <filter-class>com._520it.core.web.filter.ActionFilter</filter-class> </filter> <filter-mapping> <filter-name>ActionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
7.3:书写自己的Action函数,如Product:
package A.B.C; public class Product { public String execute(){ System.out.println("Product.execute()"); return "welcome"; } }
7.4:在resources源文件夹中新建actions.xml文件,并配置:
<?xml version="1.0" encoding="UTF-8"?> <actions> <action name="Product" class="A.B.C.Product" method="execute"> <result name="welcome" type="redirect" path="/abc.html" /> </action> </actions>
7.5:然后在webapp中随便写个html页面,如abc.html
7.6:访问格式:http://localhost:8080/miniMVC/Product;
miniMVC:tomcat根/config/server.xml中context元素属性path的值 Product:应该和action中的name向对应; Product中的execute返回值应与result元素中的name相对应
相关文章推荐
- Portal-Basic Java Web 应用开发框架:应用篇(二) —— Action 使用
- 面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序
- JAVA_WEB项目之三大框架中不使用HibernateTemplate而使用SessionFactory以及如何使用注解
- Java Web笔记 – Servlet中的Filter过滤器的介绍和使用 编写过滤器
- 搭建java web开发环境、使用eclipse编写第一个java web程序
- [转发]在 Java Web 项目中选择使用 Slf4J 通用日志框架
- 面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序
- 编写供有限状态机使用的Java框架
- 从零开始写javaweb框架笔记3-编写一个简单的web应用
- JAVA_WEB项目之使用Spring的xml配置方式在项目中管理Lucene检索框架
- 华为、阿里、京东使用的Java web框架是啥样的?
- JAVA_WEB项目之j使用query的验证框架的例子
- 使用开放源代码框架的 Java 应用程序的 Web 服务集成模式,第 1 部分: 实现调用模式
- 使用Python的Scrapy框架编写web爬虫的简单示例
- 客户端使用gsoap,访问基于jax-ws框架的java webservice
- 使用Java编写一个简单的Web的监控系统
- 面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序
- 2.1、Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职
- 《Java高手真经_应用框架卷_Java_Web核心框架》所用软件、使用版本、下载地址列表:
- 一个使用Java jdk8中Nashorn(Java javascript引擎)设计的Web开发框架