Struts2框架教程笔记一

Struts2入门第一讲——Struts2框架的快速入门 Struts2框架的概述Struts2是一种基于MVC模式的轻量级Web框架,它自问世以来,就受到了广大Web开发者的关注,并广泛应用于各种企业系统的开发中。目前掌握Struts2框架几乎成为Web开发者的必备技能之一。接下来将针对Struts2的特点、安装以及执行流程等内容进行详细的讲解。什么是Struts2先讲Struts2框架之前,我们得知道JavaEE一共有三层架构,如下: 架构名称 阅读详情
原文地址为: Struts2框架教程笔记一

struts 2 是基于OpenSymphony的网络工程框架,所以struts的类基本都在OpenSymphony的子包下。 

在Struts 2 中的模型(model),视图(view)和控制器(controller)分别用动作(action),结果(result)和过滤调度器(FilterDispatcher)来实现的。

控制器(controller)的任务是将用户的请求映射到合适的动作(action)。在Struts 2中,和过滤调度器(FilterDispatcher)做控制器(controller)同样的工作。

模型(model)包含数据和业务逻辑。在Struts 2中模型(model)是由动作(action)组件来体现的。

视图(view)是MVC模式中的描述组件。在Struts 2中视图(view)是用JSP, Velocity模板, Freemaker或一些其他描述层的技术实现的。

  

 

控制器(controller)接收到用户的请求,决定调用哪个Struct 2的动作(action)。

框架(Framework)创建一个动作(action)的实例并将它和动作调用器(ActionInvocation)的一个实例进行关联。

在Struts2中, 调用的动作(action)可以通过在应用XML文件中定义的一系列拦截器(interceptor)。

框架(Framework)调用动作调用器(ActionInvocation)的invoke()方法启动动作(action)的执行。

invoke()方法每次被调用的时候,动作调用器(ActionInvocation)都会询问自身的状态并执行下一步的拦截器(interceptor)。

动作调用器(ActionInvocation)通过调用拦截器(interceptor)的interceptor()方法来掌握控制在栈中的拦截器(interceptor)。

拦截器(interceptor)的interceptor()方法依次调用动作调用器(ActionInvocation)的invoke()方法,直到所有的拦截器(interceptor)被调用。最后,动作(action)被调用并将相应的结果返回给用户。

拦截器(interceptor)可以在动作(action)执行之前或之后,或是前后同时被调用。不是必须每次都调用它们。

首先拦截器(interceptor)按照在栈中定义的顺序执行,然后动作(action)被调用并将结果整合,之后再倒序调用在将栈中的拦截器(interceptor)。

抽象类com.opensymphony.xwork2.interceptor.AbstractInterceptor 继承了接口类Interceptor,下面就以国际化拦截器部分代码为例子:

public class I18nInterceptor extends AbstractInterceptor {
    protected static final Logger LOG = LoggerFactory.getLogger(I18nInterceptor.class);

         @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("intercept '"
                    + invocation.getProxy().getNamespace() + "/"
                    + invocation.getProxy().getActionName() + "' { ");
        }
        //get requested locale
        Map<String, Object> params = invocation.getInvocationContext().getParameters();

        boolean storeInSession = true;
        Object requested_locale = findLocaleParameter(params, parameterName);
        if (requested_locale == null) {
            requested_locale = findLocaleParameter(params, requestOnlyParameterName);
            if (requested_locale != null) {
                storeInSession = false;
            }
        }

        //save it in session

        Map<String, Object> session = invocation.getInvocationContext().getSession();

     /*这里省略了保存session信息的代码,补充:invocation.getInvocationContext()返回一个ActionContext对象,ActionContext cd = invocation.getInvocationContext()*/
               saveLocale(invocation, locale);

        if (LOG.isDebugEnabled()) {
            LOG.debug("before Locale=" + invocation.getStack().findValue("locale"));
        }

             /*拦截器(interceptor)的interceptor()方法依次调用动作调用器(ActionInvocation)的invoke()方法,直到所有的拦截器(interceptor)被调用*/

        final String result = invocation.invoke();
        if (LOG.isDebugEnabled()) {
            LOG.debug("after Locale=" + invocation.getStack().findValue("locale"));
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("intercept } ");
        }

        return result;
    }

那么Interceptor何时调用呢?

框架(Framework)调用动作调用器(ActionInvocation)的invoke()方法启动动作(action)的执行。

invoke()方法每次被调用的时候,动作调用器(ActionInvocation)都会询问自身的状态并执行下一步的拦截器(interceptor)。

参考com.opensymphony.xwork2.DefaultActionInvocation

public class DefaultActionInvocation implements ActionInvocation {

/*其他方法略掉*/

 public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);

            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }

            if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {

                                  /*invoke()方法每次被调用的时候,动作调用器(ActionInvocation)都会询问自身的状态并执行下一步的拦截器(interceptor)*/
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);

                                 }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }

               /*首先拦截器(interceptor)按照在栈中定义的顺序执行,然后动作(action)被调用并将结果整合,之后再倒序调用在将栈中的拦截器(interceptor)*/

            // this is needed because the result will be executed, then control will return to the Interceptor, which will
            // return above and flow through again
            if (!executed) {
                if (preResultListeners != null) {
                    for (Object preResultListener : preResultListeners) {
                        PreResultListener listener = (PreResultListener) preResultListener;

                        String _profileKey = "preResultListener: ";
                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, resultCode);
                        }
                        finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                // now execute the result, if we're supposed to
                if (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed = true;
            }

            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
    }

总结:通过上面的介绍,不难发现Interceptor的本质就是一个Action,它要达到的目的就是为了提高Action代码的复用性(比如国际化或者类型转换拦截器),降低Action的耦合性,但是Intercepetor又是一中特殊的Action,它在执行指定Action之前或者之后完成可复用的模块化业务逻辑,可以把通用的逻辑进行封装(比如国际化或者类型转换拦)。
 
下面提供DefaultActionInvocation的完整源代码struts2.3.1.2

/*
 * Copyright 2002-2006,2009 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.opensymphony.xwork2;

import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.profiling.UtilTimerStack;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * The Default ActionInvocation implementation
 *
 * @author Rainer Hermanns
 * @author tmjee
 * @version $Date: 2011-06-09 00:40:33 +0200 (Thu, 09 Jun 2011) $ $Id: DefaultActionInvocation.java 1133590 2011-06-08 22:40:33Z jafl $
 * @see com.opensymphony.xwork2.DefaultActionProxy
 */
public class DefaultActionInvocation implements ActionInvocation {

    private static final long serialVersionUID = -585293628862447329L;

    //static {
    //    if (ObjectFactory.getContinuationPackage() != null) {
    //        continuationHandler = new ContinuationHandler();
    //    }
    //}
    private static final Logger LOG = LoggerFactory.getLogger(DefaultActionInvocation.class);

    private static final Class[] EMPTY_CLASS_ARRAY   = new Class[0];
    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

    protected Object action;
    protected ActionProxy proxy;
    protected List<PreResultListener> preResultListeners;
    protected Map<String, Object> extraContext;
    protected ActionContext invocationContext;
    protected Iterator<InterceptorMapping> interceptors;
    protected ValueStack stack;
    protected Result result;
    protected Result explicitResult;
    protected String resultCode;
    protected boolean executed = false;
    protected boolean pushAction = true;
    protected ObjectFactory objectFactory;
    protected ActionEventListener actionEventListener;
    protected ValueStackFactory valueStackFactory;
    protected Container container;
    private Configuration configuration;
    protected UnknownHandlerManager unknownHandlerManager;

    public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
        DefaultActionInvocation.this.extraContext = extraContext;
        DefaultActionInvocation.this.pushAction = pushAction;
    }

    @Inject
    public void setUnknownHandlerManager(UnknownHandlerManager unknownHandlerManager) {
        this.unknownHandlerManager = unknownHandlerManager;
    }

    @Inject
    public void setValueStackFactory(ValueStackFactory fac) {
        this.valueStackFactory = fac;
    }

    @Inject
    public void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }

    @Inject
    public void setObjectFactory(ObjectFactory fac) {
        this.objectFactory = fac;
    }

    @Inject
    public void setContainer(Container cont) {
        this.container = cont;
    }

    @Inject(required=false)
    public void setActionEventListener(ActionEventListener listener) {
        this.actionEventListener = listener;
    }

    public Object getAction() {
        return action;
    }

    public boolean isExecuted() {
        return executed;
    }

    public ActionContext getInvocationContext() {
        return invocationContext;
    }

    public ActionProxy getProxy() {
        return proxy;
    }

    /**
     * If the DefaultActionInvocation has been executed before and the Result is an instance of ActionChainResult, this method
     * will walk down the chain of ActionChainResults until it finds a non-chain result, which will be returned. If the
     * DefaultActionInvocation's result has not been executed before, the Result instance will be created and populated with
     * the result params.
     *
     * @return a Result instance
     * @throws Exception
     */
    public Result getResult() throws Exception {
        Result returnResult = result;

        // If we've chained to other Actions, we need to find the last result
        while (returnResult instanceof ActionChainResult) {
            ActionProxy aProxy = ((ActionChainResult) returnResult).getProxy();

            if (aProxy != null) {
                Result proxyResult = aProxy.getInvocation().getResult();

                if ((proxyResult != null) && (aProxy.getExecuteResult())) {
                    returnResult = proxyResult;
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        return returnResult;
    }

    public String getResultCode() {
        return resultCode;
    }

    public void setResultCode(String resultCode) {
        if (isExecuted())
            throw new IllegalStateException("Result has already been executed.");

        this.resultCode = resultCode;
    }


    public ValueStack getStack() {
        return stack;
    }

    /**
     * Register a com.opensymphony.xwork2.interceptor.PreResultListener to be notified after the Action is executed and before the
     * Result is executed. The ActionInvocation implementation must guarantee that listeners will be called in the order
     * in which they are registered. Listener registration and execution does not need to be thread-safe.
     *
     * @param listener
     */
    public void addPreResultListener(PreResultListener listener) {
        if (preResultListeners == null) {
            preResultListeners = new ArrayList<PreResultListener>(1);
        }

        preResultListeners.add(listener);
    }

    public Result createResult() throws Exception {

        if (explicitResult != null) {
            Result ret = explicitResult;
            explicitResult = null;

            return ret;
        }
        ActionConfig config = proxy.getConfig();
        Map<String, ResultConfig> results = config.getResults();

        ResultConfig resultConfig = null;

        try {
            resultConfig = results.get(resultCode);
        } catch (NullPointerException e) {
            // swallow
        }
       
        if (resultConfig == null) {
            // If no result is found for the given resultCode, try to get a wildcard '*' match.
            resultConfig = results.get("*");
        }

        if (resultConfig != null) {
            try {
                return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
            } catch (Exception e) {
                LOG.error("There was an exception while instantiating the result of type " + resultConfig.getClassName(), e);
                throw new XWorkException(e, resultConfig);
            }
        } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) {
            return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode);
        }
        return null;
    }

    /**
     * @throws ConfigurationException If no result can be found with the returned code
     */
    public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);

            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }

            if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }

            // this is needed because the result will be executed, then control will return to the Interceptor, which will
            // return above and flow through again
            if (!executed) {
                if (preResultListeners != null) {
                    for (Object preResultListener : preResultListeners) {
                        PreResultListener listener = (PreResultListener) preResultListener;

                        String _profileKey = "preResultListener: ";
                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, resultCode);
                        }
                        finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                // now execute the result, if we're supposed to
                if (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed = true;
            }

            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
    }

    public String invokeActionOnly() throws Exception {
        return invokeAction(getAction(), proxy.getConfig());
    }

    protected void createAction(Map<String, Object> contextMap) {
        // load action
        String timerKey = "actionCreate: " + proxy.getActionName();
        try {
            UtilTimerStack.push(timerKey);
            action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
        } catch (InstantiationException e) {
            throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig());
        } catch (IllegalAccessException e) {
            throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig());
        } catch (Exception e) {
            String gripe = "";

            if (proxy == null) {
                gripe = "Whoa!  No ActionProxy instance found in current ActionInvocation.  This is bad ... very bad";
            } else if (proxy.getConfig() == null) {
                gripe = "Sheesh.  Where'd that ActionProxy get to?  I can't find it in the current ActionInvocation!?";
            } else if (proxy.getConfig().getClassName() == null) {
                gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
            } else {
                gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ",  defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
            }

            gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]");
            throw new XWorkException(gripe, e, proxy.getConfig());
        } finally {
            UtilTimerStack.pop(timerKey);
        }

        if (actionEventListener != null) {
            action = actionEventListener.prepare(action, stack);
        }
    }

    protected Map<String, Object> createContextMap() {
        Map<String, Object> contextMap;

        if ((extraContext != null) && (extraContext.containsKey(ActionContext.VALUE_STACK))) {
            // In case the ValueStack was passed in
            stack = (ValueStack) extraContext.get(ActionContext.VALUE_STACK);

            if (stack == null) {
                throw new IllegalStateException("There was a null Stack set into the extra params.");
            }

            contextMap = stack.getContext();
        } else {
            // create the value stack
            // this also adds the ValueStack to its context
            stack = valueStackFactory.createValueStack();

            // create the action context
            contextMap = stack.getContext();
        }

        // put extraContext in
        if (extraContext != null) {
            contextMap.putAll(extraContext);
        }

        //put this DefaultActionInvocation into the context map
        contextMap.put(ActionContext.ACTION_INVOCATION, this);
        contextMap.put(ActionContext.CONTAINER, container);

        return contextMap;
    }

    /**
     * Uses getResult to get the final Result and executes it
     *
     * @throws ConfigurationException If not result can be found with the returned code
     */
    private void executeResult() throws Exception {
        result = createResult();

        String timerKey = "executeResult: " + getResultCode();
        try {
            UtilTimerStack.push(timerKey);
            if (result != null) {
                result.execute(this);
            } else if (resultCode != null && !Action.NONE.equals(resultCode)) {
                throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
                        + " and result " + getResultCode(), proxy.getConfig());
            } else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation());
                }
            }
        } finally {
            UtilTimerStack.pop(timerKey);
        }
    }

    public void init(ActionProxy proxy) {
        this.proxy = proxy;
        Map<String, Object> contextMap = createContextMap();

        // Setting this so that other classes, like object factories, can use the ActionProxy and other
        // contextual information to operate
        ActionContext actionContext = ActionContext.getContext();

        if (actionContext != null) {
            actionContext.setActionInvocation(this);
        }

        createAction(contextMap);

        if (pushAction) {
            stack.push(action);
            contextMap.put("action", action);
        }

        invocationContext = new ActionContext(contextMap);
        invocationContext.setName(proxy.getActionName());

        // get a new List so we don't get problems with the iterator if someone changes the list
        List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
        interceptors = interceptorList.iterator();
    }

    protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
        String methodName = proxy.getMethod();

        if (LOG.isDebugEnabled()) {
            LOG.debug("Executing action method = " + actionConfig.getMethodName());
        }

        String timerKey = "invokeAction: " + proxy.getActionName();
        try {
            UtilTimerStack.push(timerKey);

            boolean methodCalled = false;
            Object methodResult = null;
            Method method = null;
            try {
                method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
            } catch (NoSuchMethodException e) {
                // hmm -- OK, try doXxx instead
                try {
                    String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
                    method = getAction().getClass().getMethod(altMethodName, EMPTY_CLASS_ARRAY);
                } catch (NoSuchMethodException e1) {
                    // well, give the unknown handler a shot
                    if (unknownHandlerManager.hasUnknownHandlers()) {
                        try {
                            methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName);
                            methodCalled = true;
                        } catch (NoSuchMethodException e2) {
                            // throw the original one
                            throw e;
                        }
                    } else {
                        throw e;
                    }
                }
            }

            if (!methodCalled) {
                methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY);
            }

            return saveResult(actionConfig, methodResult);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "");
        } catch (InvocationTargetException e) {
            // We try to return the source exception.
            Throwable t = e.getTargetException();

            if (actionEventListener != null) {
                String result = actionEventListener.handleException(t, getStack());
                if (result != null) {
                    return result;
                }
            }
            if (t instanceof Exception) {
                throw (Exception) t;
            } else {
                throw e;
            }
        } finally {
            UtilTimerStack.pop(timerKey);
        }
    }

    /**
     * Save the result to be used later.
     * @param actionConfig
     * @param methodResult the result of the action.
     * @return the result code to process.
     */
    protected String saveResult(ActionConfig actionConfig, Object methodResult) {
        if (methodResult instanceof Result) {
            this.explicitResult = (Result) methodResult;

            // Wire the result automatically
            container.inject(explicitResult);
            return null;
        } else {
            return (String) methodResult;
        }
    }

}

 

转载请注明本文地址: Struts2框架教程笔记一
使用IDEA学习Struts2框架 (一)Struts2入门-HelloWorld应用 作为一个刚学习完JavaWeb必要储备知识的人,早已经急不可耐地想要学习运用MVC设计模式的Web框架了。目前Java的三大框架仍然是ssh(Struts、Spring、Hibernate),而struts2对于struts1的一些缺点进行了改进,那么本着了解MVC设计模式和基础web框架学习的目的,开始学习struts2。开发工具IDEA(没有用过Eclipse,但是已经习惯了IDEA,就不改了... 阅读详情

相关推荐

Struts2.0框架完全教程

本文还有配套的精品资源,点击获取 简介:本教程旨在深入介绍Struts2.0,一款基于MVC设计模式的Java Web框架,由Apache软件基金会维护。本课程将讲解Struts2.0的核心概念、关键特性、配置文件以及安全注意事项,帮助开发者掌握Struts2.0框架的使用,并通过实践项目加深理解。教程内容覆盖Action类、结果类型、拦截器、OGNL表达式、插件与扩展、框...

weixin_29097457的博客 1216

创建了action,什么时候将action放入了valuestack的根栈中

首先我们知道在一次请求中DefaultActionInvocation的invoke方法中会不停的执行拦截器,当拦截器链执行完毕后,会执行到action,然后返回,最后又会回头执行拦截器,然后请求完毕。先来分析invoke的部分代码。 public String invoke() throws Exception { String profileKey = "invoke: ";

renzhengxiao的博客 341

深入理解Struts2框架笔记

本文还有配套的精品资源,点击获取 简介:Struts2是一个开源的JavaEE Web应用程序框架,基于MVC设计模式。本笔记深入讲解了Struts2的核心概念,包括Action类的工作原理、struts.xml配置文件的使用、结果类型和OGNL表达式语言的应用、表单提交的自动数据校验、以及与Spring框架的集成。此外,还讨论了Tiles模板技术和Struts2工具组件的...

weixin_34413326的博客 1198

Struts json格式返回

16:57:17,751 ERROR com.opensymphony.xwork2.DefaultActionInvocation:198 - There was an exception while instantiating the result of type org.apache.struts2.json.JSONResult org.springframework.beans.fac

u014764449的专栏 521

深入Struts2框架学习笔记与实战指导

Struts2作为一款流行于Java社区的MVC框架,因其易于掌握和灵活的配置,成为了许多Web应用的首选。本章将介绍Struts2的起源、架构以及它如何在Web开发中实现MVC模式。Struts2框架的发展历程是一个由多个技术融合的过程,它的前身是Jakarta Struts,经历了Struts 1到Struts 2的转变。Struts 2由WebWork项目演变而来,其最初的设计目标是简化Web应用的开发。随着各种插件和功能的集成,Struts2逐渐演化为一个成熟且功能全面的MVC框架。

weixin_32661831的博客 949

o型圈沟槽设计_O型密封圈——详细选型过程及步骤

一、密封圈常用材料二、密封圈常用密封形式密封圈分为活塞密封,活塞杆密封,端面密封,旋转密封。三、O型密封圈的选型规则O型密封圈的尺寸图径向安装O型圈选型(静态和动态运动)活塞杆密封选择适当规格的O形圈时,应该保证其外径(d1+2*d2)至少等于或者大于沟槽外径d6;当选择的O形圈直径d1大于250 mm时, O形圈外径将不能超过沟槽外径的3%;当选择的O形圈直径d1小于250mm时, O形圈外径将...

weixin_39856630的博客 2万+

忘记李刚,一步一步跟我学Struts2 —— 拦截器详解

[b][color=blue]专栏地址:[/color][url]http://www.iteye.com/wiki/struts2/1397-deep-into-struts2-interceptors[/url][/b] 在之前的文章中,我们已经涉及到了拦截器(Interceptor)的概念。 [quote="downpour"]拦截器是AOP中的概念,它本身是一段代码,可以通过定...

luzhou33的专栏 335

STM32F429移植LVGL9.3.0:从源码配置到双缓冲优化实战

本文详细介绍了如何在STM32F429平台上移植LVGL 9.3.0图形库,涵盖从源码准备、工程配置、显示驱动适配到双缓冲优化等关键步骤。重点解析了利用STM32F429的硬件特性实现高效内存管理和流畅显示性能的实战技巧,为嵌入式GUI开发提供完整解决方案。

q6r7s8t9的博客 1137

Struts2框架简单入门

Struts2入门

qq_42640067的博客 7744

​​EMC设计实战:BCI(大电流注入)硬件设计规范

LIN接口:集成TVS管(如PESD5V0S1BL)与共模电感,耐压等级≥20V(8kV HBM)。输入滤波:10μF电解电容(100kHz截止)+ 0.1μF陶瓷电容(10MHz截止)。​:全频段(1MHz-400MHz)注入200mA电流,LIN通信误码率<0.01%。对敏感电路(如传感器)采用隔离电源(如ADuM5000),隔离电压≥3kVrms。​:连续波(CW)与调幅波(AM,调制深度80%)组合,覆盖全频段干扰场景。​:选择低频段(1-100MHz)感量≥100μH的绕线电感,抑制共模电流。

m0_50833886的博客 1938

QGC二次开发实战指南(一):从零构建自定义地面站界面

本文详细介绍了QGC二次开发实战指南,从零开始构建自定义地面站界面。通过QT和QML技术结合MAVLINK协议,开发者可以打造适合特定业务场景的无人机监控系统,提升操作效率与用户体验。文章包含环境搭建、界面设计、数据绑定等完整开发流程,是QGC二次开发的实用教程。

weixin_28693683的博客 496

Struts学习笔记(一)

一、框架概述       1、框架的意义与作用:                             所谓框架,就是把一些繁琐的重复性代码封装起来,使程序员在编码中把更多的经历放到业务需求的分析和理解上面。                      特点:封装了很多细节,程序员在使用的时候会非常简单。       2、三大框架:                            ...

种媳妇儿的博客 1万+

论文阅读4——一种宽频带圆极化微带天线的设计

论文阅读——一种宽频带圆极化微带天线的设计(现在才觉得开始弄懂了一点,懂了一点之后又更糊涂了……)

weixin_64612422的博客 2317

Struts2框架学习笔记一:Struts2框架搭建、配置详解

文章目录Struts2框架学习笔记一:Struts2框架搭建、配置详解Struts2框架搭建Struts2拦截器的重要性struts2常量配置struts2动态调用struts2的默认值配置Action类的操作 Struts2框架学习笔记一:Struts2框架搭建、配置详解 Struts2框架搭建 创建一个Dynamic web project项目 在lib文件下导入相应的包,解压Struts压...

公子&小白的博客 1151

13、使用 Mathematica 撰写文本

本文详细介绍了如何使用 Mathematica 进行文本撰写与处理。内容涵盖文本输入、格式设置、结构化排版、超链接插入、翻译与拼写检查工具的使用,以及将笔记本导出为多种格式(如 PDF、HTML、LATEX 和 RTF)的方法。通过实例演示了创建专业文档的完整流程,包括样式设置、公式推导、标题编号、页眉页脚配置等操作。适合希望利用 Mathematica 编写学术论文、技术报告或教学资料的用户参考。

sony5的博客 208

226届数字IC秋招笔试面试全攻略

本文系统介绍了数字IC设计岗位面试的核心技巧,聚焦三大关键环节:自我介绍、项目介绍和技术问题回答。在自我介绍部分,强调1-2分钟结构化表达,突出与岗位匹配的技能和量化成果;项目介绍环节提出"背景-职责-技术-难点-成果"五步框架,建议结合架构图和性能数据展示技术深度;技术问题回答策略包括理解问题、结构化思考、举例说明和诚实应对未知。文章还提供了项目包装方法,指导如何通过量化数据、架构创新展示和技术难点解决方案来突出项目亮点,并附有简历项目描述示例和技术问题回答模板,帮助面试者全方位展示专

2301_79143213的博客 1062

【Struts2】一_idea快速搭建struts2框架

SSH是的一个集成框架,是16年之前较为流行的一种Web应用程序开源框架。区别于 Secure Shell。集成SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理struts和hibernate。1、导入核心jar包。

m0_70083523的博客 3334

SolidWorks软件二次开发:使用C#进行SolidWorks二次开发

SolidWorks 提供的 API(应用程序编程接口)允许开发者使用多种编程语言(如 C#、VB.NET 等)来控制和扩展 SolidWorks 的功能。API 架构基于 COM(组件对象模型),这意味着开发者可以通过引用 SolidWorks 的类型库来访问其对象模型。SolidWorks 的对象模型包括了从文档、零件、装配体到特征、草图等所有 SolidWorks 中可操作的对象。

kkchenjj的博客 3218

Struts2框架进阶(一)

Struts2框架入门之后,我们就要踏上Struts2框架漫漫的进阶之路了。我们以Struts2框架入门中的案例开始吧!Struts2框架中Action名称的搜索顺序假设某用户的请求路径的URL是http://localhost:8080/Struts2/path1/path2/path3/test.action,那么Struts2框架是怎么搜索到相应的Action来处理用户的请求呢?答案为: 首先

李阿昀的博客 3241

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

struts2框架学习

STRUTS2笔记实现原理struts2项目搭建功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 实现原理 先放一张很俗的框架图: 是不是看着很复杂?其实简单的讲这个古老的框架将我们平时使用的springMVC中的controll

qq_39794423的博客 5757

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

常用框架学习(一)——Struts2

1.1  Struts2概述1.1.1  什么是Struts2Struts2是由Apache社区的Struts1和Opensysmphony的Webwork整合而来,Struts负责对http请求的处理,Webwork负责业务逻辑处理。1.1.2 运行环境搭建1.导入13个jar包(在Struts2自带的demo中可以找到最少所需包)2.需要在web.xml文件中配置StrutsPrepareAn...

不忘初心的博客 3万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Struts2 框架简介

概述 Struts2 是基于MVC设计模式的web应用程序框架,最初是以WebWork框架和Struts框架为基础,通过提供增强和改进的Struts框架,进而实现简化web技术人员开发工作的目标。 模型(Model)-视图(View)-控制器(Controller),通常简称MVC,是一种开发web应用程序的软件设计模式。该软件设计模式由以下三部分组成:   模型——属于软件设计模式的底层基...

jcs1992的博客 2565

Struts 框架

遗留系统维护:Struts 1 仍广泛存在于政府、金融等传统 JavaEE 项目。现代替代方案:Spring MVC 更轻量,注解驱动更灵活;但Struts 2 的拦截器设计和OGNL 表达式仍值得借鉴。架构启示MVC 分层、配置中心化()、拦截器机制均为后续框架(如 Spring)提供了重要范本。作为架构师,建议在新项目中选用,但对 Struts 的理解有助于快速重构遗留系统,并深入理解 MVC 框架的演进逻辑。

chenglin016的博客 817

Struts2框架使用详解一

struts2框架使用详解一一、Struts2框架介绍1.1 struts2是什么?1.2 struts2框架的优势二、struts2框架的搭建2.1 struts2框架需要的架包2.2 书写Action类2.3 创建struts2框架配置文件2.4 配置struts2框架核心过滤器2.5 struts2框架使用测试三、struts2访问流程以及架构3.1 struts2访问流程3.1struts...

tianzhen620的博客 663
上一篇: jquery 中 change input 事件失效
下一篇: StringBuilder与StringBuffer的区别(转)
dearbaba_8520
博客等级 码龄9年 406粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值