📄 actioncontroller.java
字号:
package jodd.servlet;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jodd.util.ReflectUtil;
import jodd.util.StringUtil;
/**
* Represents a controller part of mvc2 framework.
* <p>
*
* During initialization, configuration xml file is read and all data are
* loaded by controller. When request is received, controller will lookup for
* the adequate <code>ActionServlet.doAction()</code> or defined mapped
* method to invoke. Depending of the resulting string and the configuration,
* controller will perform forwarding or redirection to the destination view.
* <p>
*
* Controller allows intercepting of all invoked actions, by using the ActionFilter.
*
* @see ActionServlet
* @see ActionFilter
*/
public class ActionController extends ActionServlet {
/**
* Holds all actions defined in xml configuration files.
*/
private HashMap actionsMap = new HashMap();
/**
* Holds all global data.
*/
private ActionData global_forwards = new ActionData();
/**
* Global controller ActionFilter.
*/
private ActionFilter actionFilter = null;
// ---------------------------------------------------------------- init
private String configPath;
private String configFile;
private String configFilter;
/**
* Initialization of the controler. Reads all actions xml configuration
* files and populates actionsMap; and initialize ActionFilter if defined.
*
* @param config actionsMap
*
* @exception ServletException
* @see #reload
*/
public void init(javax.servlet.ServletConfig config) throws ServletException {
super.init(config);
// build path for the main config file
configPath = config.getServletContext().getRealPath("");
configFile = config.getInitParameter("config");
configFilter = config.getInitParameter("filter");
reload();
}
/**
* Reloads configuration XML files. This method should be used in
* developement, since it is not synchronized with the main dispatcher. It
* re-reads configuration files and resets all ActionServlet settings, while
* server and controller are active. This makes posible to change
* configuration without restarting server.
*/
public void reload() throws ServletException {
actionsMap = new HashMap();
global_forwards = new ActionData();
ActionControllerUtil.parseFile(actionsMap, global_forwards, configPath, configFile);
if (configFilter != null) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = ActionController.class.getClassLoader();
}
try {
Class c = classLoader.loadClass(configFilter);
actionFilter = (ActionFilter) c.newInstance();
} catch (Exception ex) {
actionFilter = null;
}
} else {
actionFilter = null;
}
}
// ---------------------------------------------------------------- doRequest
/**
* Unique request parameter name that holds ActionData for the current
* invoked action, as defined in the configuration xml file. It is used
* internally.
*
* @see jodd.servlet.ActionData
*/
public static String ACTION_DATA = "jodd.servlet.ActionController.actionData";
/**
* Unique request parameter name that holds action path of the the current
* invoked action, as defined in the configuration xml file. It is used
* internally.
*/
public static String ACTION_PATH = "jodd.servlet.ActionController.actionPath";
/**
* Unique <b>global</b> forward name that will be used in case when action is
* not mapped to a request.
*/
public static String ACTION_NOT_FOUND = "jodd.servlet.ActionController.actionNotFound";
/**
* Request dispatcher - the controller.<p>
*
* The request uri will be processed first. Controller will try to find
* specific Action type (defined in actions xml configuration file). Very
* first time when action is required its class (child of ActionServlet) will
* be loaded and instanced. Next time, actions instance will be found in the
* buffer, so actions will be instanced just once (when accessed first time).
* <p>
*
* If Action can not be found, controller will forward to ACTION_NOT_FOUND
* global forward mapping.
* <p>
*
* Method doAction() will be invoked on founded action. This method returns a
* string that represents a forward name (defined in actions xml
* configuration file). Alternatively, if defined so, mapped method will be
* invoked.
* <p>
*
* On the end, controller will perform forward or redirection to path defined
* with returned forward name string (that doAction() returns), as defined in
* configuration file. If forward name can not be found, then global forwards
* will be examined. If global forward can not be found, that it is assumed
* that no forwards are used, and that returned string represents a page.
*
* @param request
* @param response
*
* @exception IOException
* @exception ServletException
*/
public void doRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String uri = request.getRequestURI();
String ctxPath = request.getContextPath();
int i = uri.indexOf(ctxPath);
String actionPath = uri.substring(i + ctxPath.length());
ActionData actionData = (ActionData) actionsMap.get(actionPath);
if (actionData == null) {
String actionNotFoundPath = global_forwards.getForwardPath(ACTION_NOT_FOUND);
if (actionNotFoundPath == null) {
actionNotFoundPath = ACTION_NOT_FOUND;
}
forward(request, response, actionNotFoundPath);
return;
}
// invoke action and get results
String actionResult = invokeAction(request, response, actionData, actionPath);
// forward/redirect:
// split returned forward to uri and parameters.
// first examine local forwards and then global forwards.
// if none found, assume it is a normal page.
if (actionResult != null) {
String actionResultUri = actionResult;
String actionResultParams = "";
i = actionResult.indexOf('?');
if (i != -1) {
actionResultUri = actionResult.substring(0, i);
actionResultParams = actionResult.substring(i + 1);
}
String fwdPath = actionData.getForwardPath(actionResultUri);
if (fwdPath == null) {
fwdPath = global_forwards.getForwardPath(actionResultUri);
}
if (fwdPath == null) {
fwdPath = actionResultUri;
}
// add params to fwdPath
if (actionResultParams.length() > 0) {
i = fwdPath.indexOf('?');
if (i != -1) {
fwdPath += "&" + actionResultParams;
} else {
fwdPath += "?" + actionResultParams;
}
}
if (actionData.isForwardRedirect(actionResultUri)) {
redirect(request, response, fwdPath);
} else {
forward(request, response, fwdPath);
}
}
}
// ---------------------------------------------------------------- invoke action
/**
* Unique <b>global</b> forward name that will be used in case when action is
* not mapped to a request.
*/
public static String INVOKE_ACTION_PARAMS = "jodd.servlet.ActionController.invokeActionParams";
/**
* Invoke specified action as it would be invoked by ActionController.
*
* <p>
* NOTE: request parameters are passed from the current request!!!
* Instead, they are passed as a HashMap in request attribute under the key:
* INVOKE_ACTION_PARAMS.
*
* @param request http request
* @param response http response
* @param actionPath action path, as defined in configuration xml file
*
* @return resulting forward String, or ACTION_NOT_FOUND if not founded
* @exception IOException
* @exception ServletException
* @see #doRequest
*/
public String invokeAction(HttpServletRequest request, HttpServletResponse response, String actionPath) throws IOException, ServletException {
String actionPathUri = actionPath;
int i = actionPath.indexOf('?');
if (i != -1) {
actionPathUri = actionPath.substring(0, i);
HashMap map = ServletUtil.getUrlParams(actionPath);
request.setAttribute(INVOKE_ACTION_PARAMS, map);
}
ActionData actionData = (ActionData) actionsMap.get(actionPathUri);
if (actionData == null) {
return ACTION_NOT_FOUND;
}
return invokeAction(request, response, actionData, actionPathUri);
}
/**
* Invokes an request once ActionData has been found.
*
* @param request http request
* @param response http responce
* @param actionData valida action data
* @param actionPath valid action path
*
* @return action forward string
* @exception IOException
* @exception ServletException
*/
private String invokeAction(HttpServletRequest request, HttpServletResponse response, ActionData actionData, String actionPath) throws IOException, ServletException {
ActionServlet action = actionData.getAction();
// is action already loaded ?
if (action == null) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = ActionController.class.getClassLoader();
}
try {
Class c = classLoader.loadClass((String) actionData.getType());
action = (ActionServlet) c.newInstance();
} catch (Exception ex) {
action = null;
throw new ServletException("can't load ActionServlet " + (String)actionData.getType(), ex);
}
action.controller = this; // store controller reference in each action servlet
actionData.setAction(action);
actionsMap.put(actionPath, actionData);
}
// invoke founded action
String actionResult = null;
if (action != null) {
request.setAttribute(ACTION_DATA, actionData);
request.setAttribute(ACTION_PATH, actionPath);
String method = actionData.getMethod();
// invoke filter
String actionFilterResult = null;
if (actionFilter != null) {
actionFilterResult = actionFilter.onAction(request, response, action);
}
if (actionFilterResult == null) {
if (method == null) {
// invoke default method
actionResult = action.doAction(request, response);
} else {
// invoke mapped metod
try {
// faster:
actionResult = StringUtil.toString(ReflectUtil.invoke(action, method, new Object[] {request, response}, new Class[] {HttpServletRequest.class, HttpServletResponse.class}));
// slower:
//actionResult = StringUtil.toString(ReflectUtil.invoke(action, method, new Object[] {request, response}));
} catch (Exception ex) {
}
}
if (actionFilter != null) {
actionFilterResult = actionFilter.onAfterAction(request, response, action, actionResult);
if (actionFilterResult != null) {
actionResult = actionFilterResult;
}
}
} else {
actionResult = actionFilterResult;
}
}
return actionResult;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -