标签:j2ee
struts的基于配置的action跳转方式使用起来特别方便,对此我也模仿struts的action,实现一个自己定义的通过配置文件配置action进行简单的操作:
首先,可以知道sturts是通过过滤器来拦截浏览器发送的请求,再在过滤器里进行操作,实现这个流程。
那么,我们也定义一个filter在我们的程序中:
public class StrutsFilter implements Filter{ public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException { { } }
同样,对所有请求进行拦截,在web.xml中进行配置:
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>com.yc.frame.filter.StrutsFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>当然,struts中最重要的就是struts.xml的这个配置文件,在这里分析配置文件可以知道,struts必然是先解析出xml,然后将解析的xml以一个数据结构储存,利用反射找到相应的Action子类,再用反射激活里面的配置的方法或者默认的execute方法,既然逻辑出来了,那么要如何设置数据结构对xml解析出来的文件进行存储呢?
struts.xml如下:
<?xml version="1.0" encoding="UTF-8" ?> <struts> <!-- 自定义的Struts --> <package name="default" namespace="/" > <action name="user.action" class="com.yc.frame.actions.UserAction" method="add"> <result name="success" type="direct">a.jsp</result> <result name="fail" type="direct">a.jsp</result> </action> <!--多个action--> </package> </struts>
在这里,每个节点对应一个类, 由于xml中有对应的层级关系,所以在设计这些类时,也要将这些类的层级关系体现出来,才能准确的对数据进行处理和操作:
//package节点对应的节点类,它应该有一个actioin节点类的集合<pre name="code" class="java">自然要提供getset方法(get,set省略)
<pre name="code" class="java">(get,set省略)
最核心的环节就是将数据读取出来后取出action的实体类,利用反射找到对应的方法,执行action的方法得到返回值,最后判断result的type,执行跳转页面,是不是清晰了一点?
//1.解析请求 HttpServletRequest request=(HttpServletRequest)arg0; HttpServletResponse response=(HttpServletResponse)arg1; String servletPath=request.getServletPath();//这个是请求的资源路径名 //判断请求的路径名是否action if(servletPath.lastIndexOf(".action")==-1){ arg2.doFilter(request, response); }else{ try { //地址格式为:cccc/user.action /user.action int lastSlashIndex = servletPath.lastIndexOf("/"); String requestActionName = servletPath .substring(lastSlashIndex + 1); String nameSpaceName = servletPath.substring(0, lastSlashIndex);//这个是总项目后面那个文件夹地址 //2.到map中找到这个action PackageWrapper packageWrapper = null; //TODO: //这里为什么要用这个entry? for (Map.Entry<String, PackageWrapper> entry : packagesMap .entrySet()) { PackageWrapper pw = entry.getValue(); pw.getNamespace().equals(nameSpaceName); packageWrapper = pw; break; } //3.反射生成action的对象 //4.激活这个action的execute方法 //5.得到这个execute返回的String ActionWrapper actionWrapper = packageWrapper.getActionMap() .get(requestActionName); String actionClassName = actionWrapper.getClassName(); Class c = Class.forName(actionClassName); Object obj1=c.newInstance(); //TODO: //这里通过packageWrapper获得拦截器的集合 List<Interceptor> interceptors=new ArrayList<Interceptor>(); List<InterceptorWrapper> iw=packageWrapper.getInterceptorList(); if(iw.size()>0){ for(int i=0;i<iw.size();i++){ InterceptorWrapper interceptorWrapper=iw.get(i); String inname=interceptorWrapper.getName(); String inclassName=interceptorWrapper.getClassName(); if(inclassName.toLowerCase().endsWith(inname.toLowerCase()+"interceptor")){ Class interceptor = Class.forName(inclassName); Object obj=interceptor.newInstance(); interceptors.add(((Interceptor)obj)); } } actionInvokation=new ActionInvokation(interceptors,((Action)obj1)); } String result = invokeActionMethod(request,c, requestActionName, actionWrapper); //6.到map中找到这个String对应的result; ResultWrapper resultWrapper=actionWrapper.getResultMap().get(result); //7.转发到这个result上 String dispatcherType=resultWrapper.getType(); String page=resultWrapper.getValue(); if(dispatcherType!=null&&!"".equals(dispatcherType)){ if("direct".equals(dispatcherType)){ String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; response.sendRedirect(basePath+page); } }else{ request.getRequestDispatcher(page).forward(request, response); } } catch (Exception e) { e.printStackTrace(); request.getSession().setAttribute("ycexeption", e.getMessage()); } } } /** * 这个方法是对result中的方法进行激活,通过传过来的反射实例和action的名字以及拿到的method名字 * @param c * @param requestActionName * @param actionWrapper * @return * @throws SecurityException * @throws NoSuchMethodException */ private String invokeActionMethod(HttpServletRequest request,Class c,String requestActionName,ActionWrapper actionWrapper) throws Exception{ String requestResult=""; Object obj=c.newInstance(); //这里完成注入参数的工作 injectParameterToAction(request, obj, c); //如果methodname为空,则执行action中的execute方法 if(actionWrapper.getMethodName()==null||"".equals(actionWrapper.getMethodName())){ requestResult=((Action)obj).execute(); }else{ //否则执行action中的配置的方法 String methodName=actionWrapper.getMethodName(); Method m=c.getMethod(methodName, null); requestResult=(String) m.invoke(obj, null); } return requestResult; } //注入参数 private void injectParameterToAction(HttpServletRequest request,Object obj,Class c) throws Exception, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ //基本类型的注入 //1.从request中取出所有的健值对,转成Map setName Map<String,String[]> map=parseRequest(request); //2.从c中找出各个要注入的方法 getMthod方法名 Method [] ms=c.getMethods(); //3.反向激活方法,注入参数 for(Method m:ms){ String methodName=m.getName(); if(map.containsKey(methodName)){ String[] values=map.get(methodName); if(values.length==1){ String s=values[0]; String type=m.getParameterTypes()[0].getName(); if (m.getParameterTypes()[0].getName().equals( "java.lang.Integer") || m.getParameterTypes()[0].getName().equals( "int")) { // 激活方法,传进去值 m.invoke(obj, Integer.parseInt(s)); continue; } else if (m.getParameterTypes()[0].getName().equals( "java.lang.Double") || m.getParameterTypes()[0].getName().equals( "double")) { m.invoke(obj, Double.parseDouble(s)); continue; } else if (m.getParameterTypes()[0].getName().equals( "java.lang.Float") || m.getParameterTypes()[0].getName().equals( "float")) { m.invoke(obj, Float.parseFloat(s)); continue; } else if (m.getParameterTypes()[0].getName().equals( "java.lang.String") || m.getParameterTypes()[0].getName().equals( "String")) { m.invoke(obj, s); continue; } } } } } private Map<String, String[]> parseRequest(HttpServletRequest request) { Map<String,String[]> map=new HashMap<String,String[]>(); Enumeration<String> enu=request.getParameterNames(); while(enu.hasMoreElements()){ String name=enu.nextElement(); String methodName="set"+name.substring(0,1).toUpperCase()+name.substring(1); map.put(methodName, request.getParameterValues(name)); } return map; } public void init(FilterConfig config) throws ServletException { //读取配置文件 Struts.xml =》Map realpath=config.getServletContext().getRealPath("/"); packagesMap=parseStrutsXml(); }解析xml文件省略了,这是我自己实现的一个最简单的struts,当然强大的struts我只是模仿了皮毛中的皮毛,欢迎来讨论和相互学习。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:j2ee
原文地址:http://blog.csdn.net/u010214269/article/details/47137787