ActionForm中的setter方法
ActionServlet中的一个方法processActionForm,当我们在截取字符串,再根据字符串取得ActionMapping之后,我们就要用利用ActionMapping来创建ActionForm,并且把ActionForm放到request或session中管理。获得ActionForm之后,我们就要将ActionForm中的数据放到Mapping中,以便实例化Action。在Struts中有一个方法是专门把ActionForm的数据放到Mapping的,这个方法就是processPopulate。今天我们就来详细来看看这个方法。
首先这个方法主要的功能是将表单数据放到Map中,并且将Map的值根据ActionForm类型转换好后设置到ActionForm中。
这个方法具体的流程是首先执行ActionForm中的reset方法进行重置,然后得到表单中所有输入域的name名称,再调用request.getParameterValues(),根据name名称得到相应的值,最后将表单中的数据全部放到一个map中,map的key为表单输入域的名称,map的value为表单输入域的值(字符串数组),接下来调用一个第三方组件BeanUtils,将Map中的值,根据ActionForm中的类型先转换好,再调用ActionForm中的setter方法设置到ActionForm上。
下面咱们来跟随源代码来看看这个方法的实现过程.首先还是和以前博客一样设置断点,进入process方法,找到processPopulate方法:
进入这个方法,看到这个方法的实现源代码:
- protectedvoid processPopulate(HttpServletRequest request,
- HttpServletResponse response,
- ActionForm form,
- ActionMapping mapping)
- throws ServletException {
- if (form == null) {
- return;
- }
- // Populate the bean properties of this ActionForm instance
- if (log.isDebugEnabled()) {
- log.debug(" Populating bean properties from this request");
- }
- form.setServlet(this.servlet);
- form.reset(mapping, request);
- if (mapping.getMultipartClass() != null) {
- request.setAttribute(Globals.MULTIPART_KEY,
- mapping.getMultipartClass());
- }
- RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
- request);
- // Set the cancellation request attribute if appropriate
- if ((request.getParameter(Constants.CANCEL_PROPERTY) != null) ||
- (request.getParameter(Constants.CANCEL_PROPERTY_X) != null)) {
- request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
- }
- }
其中,form.reset(mapping, request);这个方法就是讲form重置,作用是使ActionForm中的值恢复初始状态。
下面RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix()这个方法就是要完成填充map和转换类型等操作的,具体实现:
- publicstaticvoid populate(
- Object bean,
- String prefix,
- String suffix,
- HttpServletRequest request)
- throws ServletException {
- // Build a list of relevant request parameters from this request
- HashMap properties = new HashMap();
- // Iterator of parameter names
- Enumeration names = null;
- // Map for multipart parameters
- Map multipartParameters = null;
- String contentType = request.getContentType();
- String method = request.getMethod();
- boolean isMultipart = false;
- 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 {
- thrownew 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());
- }
- }
- if (!isMultipart) {
- names = request.getParameterNames();
- }
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- String stripped = 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());
- }
- Object parameterValue = null;
- if (isMultipart) {
- parameterValue = multipartParameters.get(name);
- } else {
- parameterValue = request.getParameterValues(name);
- }
- // Populate parameters, except "standard" struts attributes
- // such as 'org.apache.struts.action.CANCEL'
- if (!(stripped.startsWith("org.apache.struts."))) {
- properties.put(stripped, parameterValue);
- }
- }
- // Set the corresponding properties of our bean
- try {
- BeanUtils.populate(bean, properties);
- } catch(Exception e) {
- thrownew 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);
- }
- }
- }
这段实现的前半部分是关于上传的代码,因为咱们这个实例不和上传有关,所以直接忽略,直接到
- if (!isMultipart) {
- names = request.getParameterNames();
- }
这段代码,这段代码主要是获得表单的所有名称,之后通过下面这段代码:
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- String stripped = 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());
- }
- Object parameterValue = null;
- if (isMultipart) {
- parameterValue = multipartParameters.get(name);
- } else {
- parameterValue = request.getParameterValues(name);
- }
- // Populate parameters, except "standard" struts attributes
- // such as 'org.apache.struts.action.CANCEL'
- if (!(stripped.startsWith("org.apache.struts."))) {
- properties.put(stripped, parameterValue);
- }
- }
遍历名称,并且通过parameterValue = request.getParameterValues(name);获得名称对应的value值,之后通过
- if (!(stripped.startsWith("org.apache.struts."))) {
- properties.put(stripped, parameterValue);
- }
将名称作为key值,讲名称的value值作为value值添加到map中,到此为止,我们就讲表单数据添加到了map中。
随后,调用第三方的组件来实现类型转换:
- try {
- BeanUtils.populate(bean, properties);
- } catch(Exception e) {
- thrownew 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);
- }
- }
这个方法会遍历ActionForm的值的类型,并且讲Map中的值的类型改为和ActionForm对应的类型。