栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java中struts 框架的实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java中struts 框架的实现

该文章主要简单粗暴的实现了struts的请求转发功能。 其他的功能后续会慢慢补上。

最近在学习javassist的内容,看到一篇文章  大家一起写mvc  主要简单的描述了mvc的工作流程,同时实现了简单的struts2功能。

这里仿照的写了个简单的struts2框架,同时加上了自己的一些理解。

该文章主要简单粗暴的实现了struts的请求转发功能。 其他的功能后续会慢慢补上。

首先,在struts2框架中,请求的实现、跳转主要是通过在struts.xml进行相关配置。 一个标签表示一个请求的定义,action中包含了①请求的名称“name”;②请求对应的实现类“class” ;③同时还可通过“method”属性自定义执行的方法,若没配置默认执行execute0方法。

好了,在了解了struts2是怎么将界面请求同程序功能相连接后,我们通过自己的代码来实现这部分的功能。

那么,我们该如何下手了?

我们将需要实现的功能简单的分为两部分 ①action部分 ②result部分

   action部分

       ①我们需要根据界面的请求找到对应的类以及执行的方法

    result部分

        ①我们需要根据方法执行的逻辑返回'SUCCESS'、'NONE'、'LOGIN'、'INPUT'、'ERROR'这类型的字符串
 
        ②需要对不同的返回类型,指定不同的下一步请求地址
 
        ③需要定义请求的类型,包括'dispatcher(默认)'、'chain'、'redirect'、'redirectAction'、'stream'

在本文章中,result的返回类型只实现了'SUCCESS'、'LOGIN'两种,并且暂不考虑请求类型,实现的是默认的dispatcher请求转发类型。完善的功能后期会再补充。

那么,下面我们来通过代码看怎么实现如上功能。 

首先定义了ActionAnnotation和ResultAnnotation 两个自定义注解来请求需要对应的方法以及方法返回的字符串对应的跳转请求

 
 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface ActionAnnotation 
{ 
  String ActionName() default ""; 
  ResultAnnotation[] results() default {}; 
}
 
   
  @Retention(RetentionPolicy.RUNTIME) 
  @Target(ElementType.METHOD) 
  public @interface ResultAnnotation 
  { 
    ResultType name() default ResultType.SUCCESS; 
    String value() default "index.jsp"; 
  } 
 

然后我们定义一个ActionContext类,来保存一个请求所需要的内容

 
 
public class ActionContext 
{ 
   
  private String Url; 
    
   
  private String method; 
    
   
  private Map results; 
    
   
  private Class classType; 
    
   
  private Object action; 
    
   
  private Class[] paramsType; 
    
   
  private String[] actionParamsName; 
    
   
  private HttpServletRequest request; 
    
   
  private HttpServletResponse response; 
 
 

analysePackage是在组装ActionContext需要的方法

   
    public static void analysePackage(String real_path, String scan_package) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NotFoundException 
    { 
      File file = new File(real_path); 
      if(file.isDirectory()) 
      { 
 File[] files = file.listFiles(); 
 for(File f : files) 
 { 
   analysePackage(f.getAbsolutePath(),scan_package); 
 } 
      } 
      else 
      { 
 String str = real_path.replaceAll("/", "."); 
 if (str.indexOf("classes." + scan_package) <= 0 || !str.endsWith(".class")) 
 { 
   return; 
 } 
 String fileName = str.substring(str.indexOf(scan_package),str.lastIndexOf(".class")); 
 Class classType = Class.forName(fileName); 
 Method[] methods = classType.getMethods(); 
 for(Method method : methods) 
 { 
   if(method.isAnnotationPresent(ActionAnnotation.class)) 
   { 
     ActionContext actionContext = new ActionContext(); 
     ActionAnnotation actionAnnotation = (ActionAnnotation)method.getAnnotation(ActionAnnotation.class); 
     String url = actionAnnotation.ActionName(); 
     ResultAnnotation[] results = actionAnnotation.results(); 
     if(url.isEmpty() || results.length < 1) 
     { 
throw new RuntimeException("method annotation error! method:" + method + " , ActionName:" + url + " , result.length:" + results.length); 
     } 
     actionContext.setUrl(url); 
     actionContext.setMethod(method.getName()); 
     Map map = new HashMap(); 
     for(ResultAnnotation result : results) 
     { 
String value = result.value(); 
if(value.isEmpty()) 
{ 
  throw new RuntimeException("Result name() is null"); 
} 
map.put(result.name(), value); 
     } 
     actionContext.setResults(map); 
     actionContext.setClassType(classType); 
     actionContext.setAction(classType.newInstance()); 
     actionContext.setParamsType(method.getParameterTypes()); 
     actionContext.setActionParamsName(getActionParamsName(classType, method.getName())); 
     urlMap.put(url, actionContext); 
   } 
 } 
      } 
    } 
 
 

getParams是根据httpServletRequest请求中的请求内容获得请求参数数组,该参数数组为调用方法体的参数内容

   
    public static Object[] getParams(HttpServletRequest request, Class[] paramsType, String[] actionParamsName) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException 
    { 
      Object[] objects = new Object[paramsType.length]; 
      for(int i = 0; i < paramsType.length; i++) 
      { 
 Object object = null; 
 if(ParamsUtils.isBasicType(paramsType[i])) 
 { 
   objects[i] = ParamsUtils.getParam(request, paramsType[i], actionParamsName[i]); 
 } 
 else 
 { 
   Class classType = paramsType[i]; 
   object = classType.newInstance(); 
   Field[] fields = classType.getDeclaredFields(); 
   for(Field field : fields) 
   { 
     Map map = request.getParameterMap(); 
     for(Iterator iterator = map.keySet().iterator(); iterator.hasNext();) 
     { 
String key = iterator.next(); 
if(key.indexOf(".") <= 0) 
{ 
  continue; 
} 
String[] strs = key.split("\."); 
if(strs.length != 2) 
{ 
  continue; 
} 
if(!actionParamsName[i].equals(strs[0])) 
{ 
  continue; 
} 
if(!field.getName().equals(strs[1])) 
{ 
  continue; 
} 
String value = map.get(key)[0]; 
classType.getMethod(convertoFieldToSetMethod(field.getName()), field.getType()).invoke(object, value); 
break; 
     } 
   } 
   objects[i] = object; 
 } 
      } 
      return objects; 
    } 
 
 

好了,接下来。我们可以来实现action方法了

  public class LoginAction 
  { 
    @ActionAnnotation(ActionName="login.action",results={@ResultAnnotation(name=ResultType.SUCCESS,value="index.jsp"),@ResultAnnotation(name=ResultType.LOGIN,value="login.jsp")}) 
    public ResultType login(String name, String password) 
    { 
      if("hello".equals(name) && "world".equals(password)) 
      { 
 return ResultType.SUCCESS; 
      } 
      return ResultType.LOGIN; 
    } 
      
    @ActionAnnotation(ActionName="loginForUser.action",results={@ResultAnnotation(name=ResultType.SUCCESS,value="index.jsp"),@ResultAnnotation(name=ResultType.LOGIN,value="login.jsp")}) 
    public ResultType loginForUser(int number, LoginPojo loginPojo) 
    { 
      if("hello".equals(loginPojo.getUsername()) && "world".equals(loginPojo.getPassword())) 
      { 
 return ResultType.SUCCESS; 
      } 
      return ResultType.LOGIN; 
    } 
  } 
 
 

接下来,我们需要做的是让程序在启动的时候去遍历工作目录下所有类的方法,将使用了ActionAnnotation的方法找出来组装成ActionContext,这就是我们请求需要执行的方法。这样在请求到了的时候我们就可以根据请求的地址找到对应的ActionContext,并通过反射的机制进行方法的调用。
 
我们定了两个Servlet。一个用于执行初始化程序。一个用来过滤所有的action请求

   
    StrutsInitServlet 
    com.bayern.struts.one.servlet.StrutsInitServlet 
     
      scan_package 
      com.bayern.struts.one 
     
    10 
    
     
    
    DispatcherServlet 
    com.bayern.struts.one.servlet.DispatcherServlet 
    
    
    DispatcherServlet 
    *.action 
    

DispatcherServlet实现了对所用action请求的过滤,并使之执行对应的action方法,以及进行下一步的跳转

ublic void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException 
  { 
  
    request.setCharacterEncoding("utf-8"); 
    String url = request.getServletPath().substring(1); 
    ActionContext actionContext = DispatcherServletUtil.urlMap.get(url); 
    if(actionContext != null) 
    { 
      actionContext.setRequest(request); 
      actionContext.setResponse(response); 
      try 
      { 
 Object[] params = DispatcherServletUtil.getParams(request, actionContext.getParamsType(), actionContext.getActionParamsName()); 
 Class classType = actionContext.getClassType(); 
 Method method = classType.getMethod(actionContext.getMethod(), actionContext.getParamsType()); 
 ResultType result = (ResultType)method.invoke(actionContext.getAction(), params); 
 Map results = actionContext.getResults(); 
 if(results.containsKey(result)) 
 { 
   String toUrl = results.get(result); 
   request.getRequestDispatcher(toUrl).forward(request, response); 
 } 
 else 
 { 
   throw new RuntimeException("result is error! result:" + result); 
 } 
   
      } 
 

好了,现在我们已经实现了最简单的strut2框架的请求转发的功能。功能写得很粗糙,很多情况都还未考虑进来,希望大家多多指点~

以上所述就是本文的全部内容了,希望大家能够喜欢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/151553.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号