java中struts 框架的完成。本站提示廣大學習愛好者:(java中struts 框架的完成)文章只能為提供參考,不一定能成為您想要的結果。以下是java中struts 框架的完成正文
該文章重要簡略粗魯的完成了struts的要求轉發功效。 其他的功效後續會漸漸補上。
比來在進修javassist的內容,看到一篇文章 年夜家一路寫mvc 重要簡略的描寫了mvc的任務流程,同時完成了簡略的struts2功效。
這裡模仿的寫了個簡略的struts2框架,同時加上了本身的一些懂得。
該文章重要簡略粗魯的完成了struts的要求轉發功效。 其他的功效後續會漸漸補上。
起首,在struts2框架中,要求的完成、跳轉重要是經由過程在struts.xml停止相干設置裝備擺設。 一個<action>標簽表現一個要求的界說,action中包括了①要求的稱號“name”;②要求對應的完成類“class” ;③同時還可經由過程“method”屬性自界說履行的辦法,若沒設置裝備擺設默許履行execute0辦法。<result》標簽界說了①成果的類型“name”,包含'SUCCESS'、'NONE'、'LOGIN'、'INPUT'、'ERROR';②要求的類型“type”,包含'dispatcher(默許)'、'chain'、'redirect'、'redirectAction'、'stream';③成果的跳轉。 在設置裝備擺設完struts.xml後,界面中的表單便可以經由過程action屬性與action界說的name屬性值相婚配找到對應的action標簽,從而找到對應的class和履行的辦法。再依據履行辦法前往的string字符串同result標簽中的name相婚配,依據界說的type類型,停止下一步要求操作。
好了,在懂得了struts2是怎樣將界面要求同法式功效相銜接後,我們經由過程本身的代碼來完成這部門的功效。
那末,我們該若何下手了?
我們將須要完成的功效簡略的分為兩部門 ①action部門 ②result部門
action部門
①我們須要依據界面的要求找到對應的類和履行的辦法
result部門
①我們須要依據辦法履行的邏輯前往'SUCCESS'、'NONE'、'LOGIN'、'INPUT'、'ERROR'這類型的字符串
②須要對分歧的前往類型,指定分歧的下一步要求地址
③須要界說要求的類型,包含'dispatcher(默許)'、'chain'、'redirect'、'redirectAction'、'stream'
在本文章中,result的前往類型只完成了'SUCCESS'、'LOGIN'兩種,而且暫不斟酌要求類型,完成的是默許的dispatcher要求轉發類型。完美的功效前期會再彌補。
那末,上面我們來經由過程代碼看怎樣完成如上功效。
起首界說了ActionAnnotation和ResultAnnotation 兩個自界說注解來要求須要對應的辦法和辦法前往的字符串對應的跳轉要求
/**
* action注解:ActionName相當於web.xml設置裝備擺設中的url-pattern
* @author linling
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ActionAnnotation
{
String ActionName() default "";
ResultAnnotation[] results() default {};
}
/**
* 前往注解對象:name相當於struts設置裝備擺設中的result的name,包含'SUCCESS'、'NONE'、'ERROR'、'INPUT'、'LOGIN';value相當於struts設置裝備擺設中對應前往跳轉內容
* @author linling
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResultAnnotation
{
ResultType name() default ResultType.SUCCESS;
String value() default "index.jsp";
}
然後我們界說一個ActionContext類,來保留一個要求所須要的內容
/**
* 完成模仿struts依據設置裝備擺設文件跳轉至action履行響應辦法中須要的內容
* @author linling
*
*/
public class ActionContext
{
/**
* 相當於web.xml中url-pattern,獨一的
*/
private String Url;
/**
* ActionAnnotation注解對應辦法,也就是action中要履行的辦法
*/
private String method;
/**
* ActionAnnotation中的Result,對應action辦法前往的類型。例如:key:'SUCCESS';value:'index.jsp'
*/
private Map<ResultType, String> results;
/**
* action的類
*/
private Class<?> classType;
/**
* action的對象
*/
private Object action;
/**
* 辦法參數類型
*/
private Class<?>[] paramsType;
/**
* 辦法參數的稱號,留意這裡辦法稱號須要和下面paramType參數逐個對應
* 可以懂得為是struts中action中的屬性
*/
private String[] actionParamsName;
/**
* 本次要求的HttpServletRequest
*/
private HttpServletRequest request;
/**
* 本次要求的HttpServletResponse
*/
private HttpServletResponse response;
analysePackage是在組裝ActionContext須要的辦法
/**
* 遍歷scan_package包下的class文件,將應用了ActionAnnotation注解的辦法停止解析,組裝成ActionContext對象 並放入urlMap中
* @param real_path
* @param scan_package
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws NotFoundException
*/
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<ResultType, String> map = new HashMap<ResultType, String>();
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要求中的要求內容取得要求參數數組,該參數數組為挪用辦法體的參數內容
/**
* 依據 參數類型parasType 和 參數名actinParamsName 來解析要求request 構建參數object[]
* @param request
* @param paramsType
* @param actionParamsName
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SecurityException
*/
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<String, String[]> map = request.getParameterMap();
for(Iterator<String> 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要求
<servlet>
<servlet-name>StrutsInitServlet</servlet-name>
<servlet-class>com.bayern.struts.one.servlet.StrutsInitServlet</servlet-class>
<init-param>
<param-name>scan_package</param-name>
<param-value>com.bayern.struts.one</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>com.bayern.struts.one.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
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<ResultType,String> 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框架的要求轉發的功效。功效寫得很粗拙,許多情形都還未斟酌出去,願望年夜家多多指導~
以上所述就是本文的全體內容了,願望年夜家可以或許愛好。