- 浏览: 276782 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
u014704612:
你好,请问这个实现由需要什么条件吗,我复制进去达不到全屏的效果 ...
JavaScript控制页面全屏,并且禁止使用ALT+TAB键切换 -
shengtu:
能不能兼容其它浏览器呢?
JavaScript控制页面全屏,并且禁止使用ALT+TAB键切换 -
leongfeng:
xd_fjx 写道如果使用那个HibernateCallbac ...
Spring中使用HibernateCallback -
soft5200:
jQuery.getJSON('http://localhos ...
使用JQuery结合HIghcharts实现从后台获取JSON实时刷新图表 -
monica617:
讲的还可以字体和格式再设置为易读模式就更好了
Struts1.3.x中ActionServlet源码分析之执行
执行流程:
1、ActionServlet处理.do的请求 不管是get还是post方式都将转到
protected void process(HttpServletRequest request, HttpServletResponse response) 方法。
2、根据请求对象和servletContext对象选择请求所隶属的模块
ModuleUtils.getInstance().selectModule(request, getServletContext());
3、加载模块配置对象 ModuleConfig config = getModuleConfig(request);
4、加载请求处理对象
RequestProcessor processor = getProcessorForModule(config);
if (processor == null) {
processor = getRequestProcessor(config);
}
5、调用请求对象(processor)对象的
public void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
方法处理请求。
6、对mutipart请求(上传)进行特殊包装 request = processMultipart(request);
1、首先判断是否为post方式,如果不是post方式,则肯定不是上传请求,则直接返回request对象
if (!"POST".equalsIgnoreCase(request.getMethod())) {
return (request);
}
2、获取request对象的ContentType,如果ContentType为multipart/form-datade 话则 new 一个 MultipartRequestWrapper 对象返回。否则直接返回request。
String contentType = request.getContentType();
if ((contentType != null)
&& contentType.startsWith("multipart/form-data")) {
return (new MultipartRequestWrapper(request));
} else {
return (request);
}
1、MultipartRequestWrapper继承于HttpServletRequestWrapper。下面是包装代码
public MultipartRequestWrapper(HttpServletRequest request) {
super(request);
this.parameters = new HashMap();
}
7、处理请求路径
String path = processPath(request, response); 返回的是访问的action的名字
8、如果返回值是空, 则方法直接return,结束。
if (path == null) {
return;
}
9、把请求的方式(post/get)和action名字记入日志
if (log.isDebugEnabled()) {
log.debug("Processing a '" + request.getMethod() + "' for path '"
+ path + "'");
}
10、为当前的用户请求选择对应的local(区域和语言),这是根据浏览器的设置的。涉及到国际化问题。
// Select a Locale for the current user if requested
processLocale(request, response);
11、为response对象设置ContentType和no-cache的header信息。
// Set the content type and no-caching headers if requested
processContent(request, response);
processNoCache(request, response);
12、留了一个可以预处理请求的扩展接口。
// General purpose preprocessing hook
if (!processPreprocess(request, response)) {
return;
} 这里processPreprocess方法只有一句话:return(true);其实是为了可以扩展,如果要对请求预处理,可以继承这个类,然后重写这个
protected boolean processPreprocess(HttpServletRequest request,HttpServletResponse response) {
return (true);
}
方法。
13、处理以前缓存的信息
this.processCachedMessages(request, response);
其实就是清空session里如果存在的struts定义的提示信息和错误信息。
14、根据request,response,和path(action的名字)返回actionMapping对象。
// Identify the mapping for this request
ActionMapping mapping = processMapping(request, response, path);
if (mapping == null) {
return;
}
1、首先去配置文件里找相应的配置信息
// Is there a mapping for this path?
ActionMapping mapping = (ActionMapping) moduleConfig.findActionConfig(path);
2、如果有配置则把它放入request,并返回他。
// If a mapping is found, put it in the request and return it
if (mapping != null) {
request.setAttribute(Globals.MAPPING_KEY, mapping);
return (mapping);
}
3、找到“未知的映射路径(如果有的话)”。同样找到了就放到request里并返回他。
// Locate the mapping for unknown paths (if any)
ActionConfig[] configs = moduleConfig.findActionConfigs();
for (int i = 0; i < configs.length; i++) {
if (configs[i].getUnknown()) {
mapping = (ActionMapping) configs[i];
request.setAttribute(Globals.MAPPING_KEY, mapping);
return (mapping);
}
}
4、如果还是没有找到mapping信息则发送错误消息,并返回null
// No mapping can be found to process this request
String msg = getInternal().getMessage("processInvalid");
log.error(msg + " " + path);
response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
return null;
15、检查执行这个action所要的所有角色(是否有权访问)
// Check for any role required to perform this action
if (!processRoles(request, response, mapping)) {
return;
}
1、从actionMapping(mapping)对想里取得角色名称的数组。
// Is this action protected by role requirements?
String[] roles = mapping.getRoleNames();
2、如果mapping里没有角色信息(没有配置),就不做处理,直接返回true
if ((roles == null) || (roles.length < 1)) {
return (true);
}
3、依次取出配置了的角色 ,如果用户在角色中 (配置了的所有角色中的任意一个) ,则把用户名和角色名记 录到log里。并返回true。
// Check the current user against the list of required roles
for (int i = 0; i < roles.length; i++) {
if (request.isUserInRole(roles[i])) {
if (log.isDebugEnabled()) {
log.debug(" User '" + request.getRemoteUser()
+ "' has role '" + roles[i] + "', granting access");
}
return (true);
}
}
4、如果仍没找到用户所对应的角色,则说明这个用户是非法访问的。则把这个用户名记录到log里,发送错误信息,并返回false。
// The current user is not authorized for this action
if (log.isDebugEnabled()) {
log.debug(" User '" + request.getRemoteUser()
+ "' does not have any required role, denying access");
}
response.sendError(HttpServletResponse.SC_FORBIDDEN,
getInternal().getMessage("notAuthorized", mapping.getPath()));
return (false);
16、处理与这个请求有关的所有actionForm。(调用processActionForm()方法返回ActionForm对象)
// Process any ActionForm bean related to this request
ActionForm form = processActionForm(request, response, mapping);
1、如果有需要就新建一个ActionForm来供使用。
// Create (if necessary) a form bean to use
ActionForm instance = RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);
1、查看mapping里是否配置name属性或attribute属性来指定ActionForm,如果都没有则返回null
// Is there a form bean associated with this mapping?
String attribute = mapping.getAttribute();
if (attribute == null) {
return (null);
}
2、通过name属性拿到ActionForm的配置信息
// Look up the form bean configuration information to use
String name = mapping.getName();
FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
3、如果没有与name属性相对应的<form-bean>配置,则在log里记录:没有配置与name对应的formBean,并返回null;
if (config == null) {
log.warn("No FormBeanConfig found under '" + name + "'");
return (null);
}
4、根据拿到的<form-bean>配置,在相应的范围里(request,session)找ActionForm的实例
ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());
5、如果找到,并被判定为可用,则返回找到的实例。
// Can we recycle the existing form bean instance (if there is one)?
if ((instance != null) && config.canReuse(instance)) {
return (instance);
}
6、如果没找到,(前面已经确定配置了formBean)。则新建一个ActionForm对象出来并返回他。
return createActionForm(config, servlet);
1、首先判断传入的config,如果config为null,则直接返回null
if (config == null) {
return (null);
}
2、创建并返回一个新的ActionForm对象。这里调用了config对象的createActionForm方法。该方法里肯定用到了反射机制。另外把创建的ActionForm或动态ActionForm的信息存到log里。同样,如果过程中出错,错误信息业将被保存到日志里。
ActionForm instance = null;
// Create and return a new form bean instance
try {
instance = config.createActionForm(servlet);
if (log.isDebugEnabled()) {
log.debug(" Creating new "
+ (config.getDynamic() ? "DynaActionForm" : "ActionForm")
+ " instance of type '" + config.getType() + "'");
log.trace(" --> " + instance);
}
} catch (Throwable t) {
log.error(servlet.getInternal().getMessage("formBean",
config.getType()), t);
}
return (instance);
17、为ActionForm填充数据。
processPopulate(request, response, form, mapping);
1、首先判断form是否为null,如果是则直接return。
if (form == null) {
return;
}
2、往log里写入一句话提示从这里开始填充formBean
if (log.isDebugEnabled()) {
log.debug(" Populating bean properties from this request");
}
3、设置Servlet。
form.setServlet(this.servlet);
(不知道具体作用)
4、执行reset方法重置表单。默认reset方法不做任何事情。这个方法是为了方便扩展。可以继承ActionForm类重写reset方法,这个方法可以用来做设置一些默认值等工作。
form.reset(mapping, request);
5、如果是上传表单,则获取上传类。(不甚了解)
if (mapping.getMultipartClass() != null) {
request.setAttribute(Globals.MULTIPART_KEY,
mapping.getMultipartClass());
}
6、填充form
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(), request);
1、建立一个HashMap 用于存放属性
// Build a list of relevant request parameters from this request
HashMap properties = new HashMap();
2、建立一个Enumeration用于存放参数名
// Iterator of parameter names
Enumeration names = null;
3、建立一个Map来存放multipart参数
// Map for multipart parameters
Map multipartParameters = null;
4、获取请求的ContentType和Method。并设置multipart表示为false。
String contentType = request.getContentType();
String method = request.getMethod();
boolean isMultipart = false;
5、如果是multipart表单则做上传处理(不甚了解)
if (bean instanceof ActionForm) {
((ActionForm) bean).setMultipartRequestHandler(null);
}
MultipartRequestHandler multipartHandler = null;
if ((contentType != null)
&& (contentType.startsWith("multipart/form-data"))
&& (method.equalsIgnoreCase("POST"))) {
// Get the ActionServletWrapper from the form bean
ActionServletWrapper servlet;
if (bean instanceof ActionForm) {
servlet = ((ActionForm) bean).getServletWrapper();
} else {
throw new ServletException("bean that's supposed to be "
+ "populated from a multipart request is not of type "
+ "\"org.apache.struts.action.ActionForm\", but type "
+ "\"" + bean.getClass().getName() + "\"");
}
// Obtain a MultipartRequestHandler
multipartHandler = getMultipartHandler(request);
if (multipartHandler != null) {
isMultipart = true;
// Set servlet and mapping info
servlet.setServletFor(multipartHandler);
multipartHandler.setMapping((ActionMapping) request
.getAttribute(Globals.MAPPING_KEY));
// Initialize multipart request class handler
multipartHandler.handleRequest(request);
//stop here if the maximum length has been exceeded
Boolean maxLengthExceeded =
(Boolean) request.getAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);
if ((maxLengthExceeded != null)
&& (maxLengthExceeded.booleanValue())) {
((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
return;
}
//retrieve form values and put into properties
multipartParameters =
getAllParametersForMultipartRequest(request,
multipartHandler);
names = Collections.enumeration(multipartParameters.keySet());
}
}
6、如果不是上传,则把参数名存到names枚举里面。
if (!isMultipart) {
names = request.getParameterNames();
}
7、遍历这个枚举
while (names.hasMoreElements())
1、把名字拿出来存到name和stripped变量里
String name = (String) names.nextElement();
String stripped = name;
2、去掉name的前缀和后缀(如果有的话(配置文件里可以配置))
if (prefix != null) {
if (!stripped.startsWith(prefix)) {
continue;
}
stripped = stripped.substring(prefix.length());
}
if (suffix != null) {
if (!stripped.endsWith(suffix)) {
continue;
}
stripped =
stripped.substring(0, stripped.length() - suffix.length());
}
3、获取参数值,分上传和非上传两种方式
Object parameterValue = null;
if (isMultipart) {
parameterValue = multipartParameters.get(name);
parameterValue = rationalizeMultipleFileProperty(bean, name, parameterValue);
} else {
parameterValue = request.getParameterValues(name);
}
4、如果参数名去掉了前后缀后不是一org.Apache.struts开头则把参数存到定义好的HashMap里
// Populate parameters, except "standard" struts attributes
// such as 'org.apache.struts.action.CANCEL'
if (!(stripped.startsWith("org.apache.struts."))) {
properties.put(stripped, parameterValue);
}
8、调用BeanUtils的方法把formBean的属性填充进去(异常处理那块不是很明白)
// Set the corresponding properties of our bean
try {
BeanUtils.populate(bean, properties);
} catch (Exception e) {
throw new ServletException("BeanUtils.populate", e);
} finally {
if (multipartHandler != null) {
// Set the multipart request handler for our ActionForm.
// If the bean isn't an ActionForm, an exception would have been
// thrown earlier, so it's safe to assume that our bean is
// in fact an ActionForm.
((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
}
}
7、加入合适的话就把退出属性设置到request里;(还是不了解)
// Set the cancellation request attribute if appropriate
if ((request.getParameter(Globals.CANCEL_PROPERTY) != null)
|| (request.getParameter(Globals.CANCEL_PROPERTY_X) != null)) {
request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
}
18、验证表单输入的合法性。如果有不合法的则return。(一般不用struts的表单级验证)
// Validate any fields of the ActionForm bean, if applicable
try {
if (!processValidate(request, response, form, mapping)) {
return;
}
} catch (InvalidCancelException e) {
ActionForward forward = processException(request, response, e, form, mapping);
processForwardConfig(request, response, forward);
return;
} catch (IOException e) {
throw e;
} catch (ServletException e) {
throw e;
}
19、处理mapping指定的forward 和 include
// Process a forward or include specified by this mapping
if (!processForward(request, response, mapping)) {
return;
}
if (!processInclude(request, response, mapping)) {
return;
}
20、创建或者获取一个Action的实例来处理请求。
// Create or acquire the Action instance to process this request
Action action = processActionCreate(request, response, mapping);
1、从mapping里取出配置的Action类名
// Acquire the Action instance we will be using (if there is one)
String className = mapping.getType();
2、把查找Action实例的动作记入到日志里
if (log.isDebugEnabled()) {
log.debug(" Looking for Action instance for class " + className);
}
3、在拿到Action实例之前先线程同步synchronized (actions) ,保证只有一个Action实例
4、从map里取出Action返回,(如果有的话),并把结果写入日志
nstance = (Action) actions.get(className);
if (instance != null) {
if (log.isTraceEnabled()) {
log.trace(" Returning existing Action instance");
}
return (instance);
}
5、如果上面的操作没进行,那说明要新建一个Action实例,把新建实例的动作记录到日志里
if (log.isTraceEnabled()) {
log.trace(" Creating new Action instance");
}
6、创建出Action实例,吧实例放到map里并返回实例
try {
instance = (Action) RequestUtils.applicationInstance(className);
// Maybe we should propagate this exception
// instead of returning null.
} catch (Exception e) {
log.error(getInternal().getMessage("actionCreate",
mapping.getPath()), e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
getInternal().getMessage("actionCreate", mapping.getPath()));
return (null);
}
actions.put(className, instance);
if (instance.getServlet() == null) {
instance.setServlet(this.servlet);
}
}
return (instance);
21、再次判断Action是否创建成功,如果没有则方法直接return
if (action == null) {
return;
}
22、执行Action的excute方法,获得ActionForward
// Call the Action instance itself
ActionForward forward = processActionPerform(request, response, action, form, mapping);
其中processActionPerform方法调用了action的excute方法:
protected ActionForward processActionPerform(HttpServletRequest request,
HttpServletResponse response, Action action, ActionForm form,
ActionMapping mapping)
throws IOException, ServletException {
try {
return (action.execute(mapping, form, request, response));
} catch (Exception e) {
return (processException(request, response, e, form, mapping));
}
}
这里也做了一个处理,如果要在执行excute方法之前做一些操作,就可以覆盖processActionPerform方法。
23、更具Actionforward进行转发
// Process the returned ActionForward instance
processForwardConfig(request, response, forward);
1、如果ActionForward为空,则方法直接返回
if (forward == null) {
return;
}
2、把接下来处理forward的操作记录到日志里
if (log.isDebugEnabled()) {
log.debug("processForwardConfig(" + forward + ")");
}
3、从mapping里获取forward对应的url,默认用forward的方式转发,如果配了redirect,则用redirect重定向
String forwardPath = forward.getPath();
String uri;
// If the forward can be unaliased into an action, then use the path of the action
String actionIdPath = RequestUtils.actionIdURL(forward, request, servlet);
if (actionIdPath != null) {
forwardPath = actionIdPath;
ForwardConfig actionIdForward = new ForwardConfig(forward);
actionIdForward.setPath(actionIdPath);
forward = actionIdForward;
}
// paths not starting with / should be passed through without any
// processing (ie. they're absolute)
if (forwardPath.startsWith("/")) {
// get module relative uri
uri = RequestUtils.forwardURL(request, forward, null);
} else {
uri = forwardPath;
}
if (forward.getRedirect()) {
// only prepend context path for relative uri
if (uri.startsWith("/")) {
uri = request.getContextPath() + uri;
}
response.sendRedirect(response.encodeRedirectURL(uri));
} else {
doForward(uri, request, response);
}
相关推荐
源码分析是理解其工作原理、学习框架设计思想以及进行二次开发的重要途径。 首先,让我们来探讨一下Struts 1.3的核心概念: 1. **ActionServlet**:这是Struts框架的入口点,它是一个实现了Servlet接口的类,负责...
深入研究Struts1.3的源码,可以让你了解其内部的工作流程,如请求的处理流程、Action的执行过程、异常处理、国际化实现等。此外,通过查看源码,还可以学习到如何利用Struts的API进行扩展和定制,如创建自定义标签、...
Struts1.3源代码的分析可以帮助我们深入理解其内部工作机制,这对于开发者来说具有重要的学习价值。 在Struts1.3版本中,主要包含以下几个核心组件: 1. **ActionServlet**:这是Struts的核心控制器,负责处理HTTP...
- 根据`struts-config.xml`中的配置,ActionServlet确定对应的ActionForm和Action。 - ActionForm对请求参数进行校验,然后Action执行业务逻辑,可能修改ActionForm的属性。 - Action根据业务逻辑的结果,返回一...
这里的"struts-1.3.9 源码"指的是Struts 1.x系列的第9次次要版本的源代码。Struts 1.3.9是在2008年发布的,它提供了许多增强和修复了之前版本中的问题,以提高框架的稳定性和安全性。 首先,我们来看看`LICENSE.txt...
在这个版本中,Controller 部分由 Struts ActionServlet 执行,Model 由 ActionForm 实现,View 可以是 JSP 或其他视图技术。 2. **配置文件**:`struts-config.xml` 是 Struts 的核心配置文件,用于定义动作映射、...
通过分析`CompressionFilter`和`beerV2_strutsV1.3`的源码,读者不仅可以了解到Servlet过滤器和Struts框架的工作原理,还可以学习到如何在实际项目中实现这些功能,提升自己的Java Web开发技能。同时,这也有助于...
11.2.1 ActionServlet(分发器) 11.2.2 Action(控制器) 11.2.3 Action Mapping(映射) 11.2.4 ActionForm(表单控制器) 11.2.5 ActionErrors(错误处理) 11.2.6 DispatchAction(多动作控制器) 11.3 利用...
11.2.1 ActionServlet(分发器) 11.2.2 Action(控制器) 11.2.3 Action Mapping(映射) 11.2.4 ActionForm(表单控制器) 11.2.5 ActionErrors(错误处理) 11.2.6 DispatchAction(多动作控制器) 11.3 利用...
11.2.1 ActionServlet(分发器) 11.2.2 Action(控制器) 11.2.3 Action Mapping(映射) 11.2.4 ActionForm(表单控制器) 11.2.5 ActionErrors(错误处理) 11.2.6 DispatchAction(多动作控制器) 11.3 利用...
作者处处从实战出发,在丰富的示例中直观地探讨了许多实用的技术,如数据类型转换、文件上传和下载、提高Struts 2应用的安全性、调试与性能分析、FreeMarker、Velocity、Ajax,等等。跟随作者一道深入Struts 2,聆听...
在JSP早期,开发者常面临控制器杂乱无章的问题,Struts通过引入ActionServlet解决了这一问题,将业务逻辑与视图分离,使程序结构更加清晰。 2.2 Struts的优缺点 2.2.1 Struts的优点 - 结构清晰:采用MVC模式,便于...
11.2.1 ActionServlet(分发器) 11.2.2 Action(控制器) 11.2.3 Action Mapping(映射) 11.2.4 ActionForm(表单控制器) 11.2.5 ActionErrors(错误处理) 11.2.6 DispatchAction(多动作控制器) 11.3 利用...
主要包括Java Web开发环境、JSP语法、JSP内置对象、Java Bean技术、Servlet技术、EL与JSTL标签库、数据库应用开发、初识Struts2基础、揭密Struts2高级技术、Hib锄劬e技术入门、Hibernate高级应用、Spring核心之IoC、...
详细阐述各功能模块的实现细节,包括SQL查询语句、JavaBean的编写、Action类的设计等。 第四章 系统测试与优化 4.1 单元测试 对系统各模块进行单元测试,确保功能的正确性。 4.2 集成测试 进行整体的系统测试,...