当前位置:文档之家› Struts2框架流程详细分析

Struts2框架流程详细分析

Struts2框架流程详细分析
Struts2框架流程详细分析

StrutsPrepareAndExecuteFilter实现了Filter接口init方法为初始化入口

StrutsPrepareAndExecuteFilter init方法

1.public void init(FilterConfig filterConfig) throws ServletException {

2.//初始化辅助类类似一个Delegate

3. InitOperations init = new InitOperations();

4.try {

5.// FilterHostConfig 封装了FilterConfig参数对象

6. FilterHostConfig config = new FilterHostConfig(filterConfig);

7.//LoggerFactory配置加载

8.//如果没有web.xml 没有配置“loggerFactory”参数尝试https://www.doczj.com/doc/de319284.html,mons.logging.LogFactory

9.//如果失败使用JdkLoggerFactory

10.//TODO SPI

11. init.initLogging(config);

12.//TODO 创建Dispatcher 注册加载器执行加载器创建容器解析xml

13. Dispatcher dispatcher = init.initDispatcher(config);

14. init.initStaticContentLoader(config, dispatcher);

15.//预处理类请求处理时才会真正用到

16.//1.主要负责在每次请求创建ActionContext 清除ActionContext

17.//2.当接收到一个请求时通过uri查找 ActionConfig 创建ActionMapping

18. prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);

//处理请求 Delegate

19. execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);

this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

20. //空实现留作扩展

21. postInit(dispatcher, filterConfig);

22. } finally {

23. init.cleanup();

24. }

25.}

InitOperations 类似与一个Delegate 主要负责实例化Dispatche 再把初始化操作转交给Dispatche init处理

1.public Dispatcher initDispatcher( HostConfig filterConfig ) {

2.//创建Dispatcher

3. Dispatcher dispatcher = createDispatcher(filterConfig);

4.//核心方法 Container容器的创建 xml解析在此方法发生

5. dispatcher.init();

6.return dispatcher;

7.}

8.

9.private Dispatcher createDispatcher( HostConfig filterConfig ) {

10. Map params = new HashMap();

11.for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {

12. String name = (String) e.next();

13. String value = filterConfig.getInitParameter(name);

14. params.put(name, value);

15. }

16.return new Dispatcher(filterConfig.getServletContext(), params);

17.}

Dispatcher init方法 1.针对配置文件注册不同的加载器保存到ConfigurationManager类中的一个变量中 2.创建容器解

析xml

1.public void init() {

2.//创建配置操作管理类 , 会保存元素加载器

3.if (configurationManager == null) {

4. configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAUL

T_BEAN_NAME);

5. }

6.try {

7./**初始化各种形式加载器,保存到ConfigurationManager#containerProviders Map集合中

8.没有真正执行加载解析逻辑*/

9.//org/apache/struts2/default.properties属性文件里面定义了一系列struts常量

10. init_DefaultProperties(); // [1]

11.//web.xml配置的 config参数 [配置多个用","分开]

12.//如果没有该参数默认为 struts-default.xml[框架级],struts-plugin.xml[框架级],struts.xml[系统级别]

13.//根据文件名称创建加载器加载xml主要有一下两个解析器

14.//XmlConfigurationProvider[xwork.xml],

15.//StrutsXmlConfigurationProvider[struts相关配置文件]配置元素加载器

16. init_TraditionalXmlConfigurations(); // [2]

17.//struts.locale 注册

18. init_LegacyStrutsProperties(); // [3]

19.//实例化我们自定义的加载器保存到containerProviders集合中

20.// web.xml configProviders参数多个用","分开

21.//配置器必须是ConfigurationProvider接口的实例

22.//TODO SPI

23. init_CustomConfigurationProviders(); // [5]

24.//web.xml配置的init-param参数加载器最终会保存到Container容器中

25. init_FilterInitParameters() ; // [6]

26.//TODO 根据我们在struts.xml定义的常量选择插件类

27.//比如集成spring 会用到org.apache.struts2.spring.StrutsSpringObjectFactory

28. init_AliasStandardObjects() ; // [7]

29./** 执行加载器 */

30.//TODO 创建容器解析xml 真正执行加载器方法

31. Container container = init_PreloadConfiguration();

32.//执行当前Dispatcher对象依赖关系注入

33. container.inject(this);

34.//额外动作

35. init_CheckConfigurationReloading(container);

36. init_CheckWebLogicWorkaround(container);

37. } catch (Exception ex) {

38.if (LOG.isErrorEnabled())

39. LOG.error("Dispatcher initialization failed", ex);

40.throw new StrutsException(ex);

41. }

42. }

ConfigurationManager 主要管理创建的各种加载器

1.public class ConfigurationManager {

2.protected static final Logger LOG = LoggerFactory.getLogger(ConfigurationManager.class);

3.//配置元素管理器

4.protected Configuration configuration;

5.protected Lock providerLock = new ReentrantLock();

6.//创建的xml加载器会保存到次集合中

7.private List containerProviders = new CopyOnWriteArrayList(); }

Dispatcher的createConfigurationManager方法

1.protected ConfigurationManager createConfigurationManager(String name) {

2.//name - > struts

3.return new ConfigurationManager(name);

4.}

1.default.properties 属性文件加载器

1.private void init_DefaultProperties() {

2.//保存到ConfigurationManager加载器集合中

3. configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());

4.}

2.创建struts相关文件加载器StrutsXmlConfigurationProvider

1.private void init_TraditionalXmlConfigurations() {

2.//web.xml 配置的config

3. String configPaths = initParams.get("config");

4.if (configPaths == null) {

5.//如果没有配置默认 struts-default.xml,struts-plugin.xml,struts.xml

6. configPaths = DEFAULT_CONFIGURATION_PATHS;

7. }

8. String[] files = configPaths.split("\\s*[,]\\s*");

9.for (String file : files) {

10.if (file.endsWith(".xml")) {

11.if ("xwork.xml".equals(file)) {

12. configurationManager.addConfigurationProvider(createXmlConfigurationProvider(file,false));

13. } else {

14.//struts xml加载器

15.//StrutsXmlConfigurationProvider

16. configurationManager.addConfigurationProvider(createStrutsXmlConfiguration

Provider(file, false, servletContext));

17. }

18. } else {

19.throw new IllegalArgumentException("Invalid configuration file name");

20. }

21. }

22.}

23.p rotected XmlConfigurationProvider createXmlConfigurationProvider(String filename, boolean

errorIfMissing) {

24.return new XmlConfigurationProvider(filename, errorIfMissing);

25.}

26.p rotected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, b

oolean errorIfMissing, ServletContext ctx) {

27.return new StrutsXmlConfigurationProvider(filename, errorIfMissing, ctx);

3.web.xml扩展的ContainerProviders加载器实例化

1.private void init_CustomConfigurationProviders() {

2.//web.xml 中configProviders 节点

3. String configProvs = initParams.get("configProviders");

4.if (configProvs != null) {

5. String[] classes = configProvs.split("\\s*[,]\\s*");

6.for (String cname : classes) {

7. Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());

8. ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();

9. configurationManager.addConfigurationProvider(prov);

10. }

11. }

12.}

init_PreloadConfiguration 方法主要完成创建容器, 解析xml动作

1.private Container init_PreloadConfiguration() {

2.//创建Container 解析xml

3. Configuration config = configurationManager.getConfiguration();

4. Container container = config.getContainer();

5.boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstan

ts.STRUTS_I18N_RELOAD));

6. LocalizedTextUtil.setReloadBundles(reloadi18n);

7.return container;

8.}

init_PreloadConfiguration 方法中调用了ConfigurationManager的getConfiguration 方法

1.public synchronized Configuration getConfiguration() {

2.//创建配置元素管理器

3.if (configuration == null) {

4.// defaultFrameworkBeanName - > struts

5. setConfiguration(createConfiguration(defaultFrameworkBeanName));

6.try {

7.// getContainerProviders 返回注册的各种加载器

8.// reloadContainer 创建Container 解析xml

9. configuration.reloadContainer(getContainerProviders());

10. } catch (ConfigurationException e) {

11. setConfiguration(null);

12.throw new ConfigurationException("Unable to load configuration.", e);

13. }

14. } else {

15. conditionalReload();

16. }

17.return configuration;

18.}

[java]view plainc opyprint?

1.protected Configuration createConfiguration(String beanName) {

DefaultConfiguration的reloadContainer方法会去执行已注册的各种加载器 ,和创建容器

1.public synchronized List reloadContainer(List providers) th

rows ConfigurationException {

2. packageContexts.clear();

3. loadedFileNames.clear();

4. List packageProviders = new ArrayList();

5.// 保存struts常量

6. ContainerProperties props = new ContainerProperties();

7.//容器构建器

8. ContainerBuilder builder = new ContainerBuilder();

9.for (final ContainerProvider containerProvider : providers) {

10./**

11. * 初始化Document 准备解析

12. * 具体在XmlConfigurationProvider实现类会处理include节点

13. * 处理完成之后Document会保存到XmlConfigurationProvider#documents list集合中

14. * include file路径会保存到XmlConfigurationProvider#loadedFileUrls set集合中

15. * 从代码中发现 include file属性中可以使用通配符 "*"

16. */

17./** StrutsXmlConfigurationProvider 是 XmlConfigurationProvider的子类 */

18./** StrutsXmlConfigurationProvider struts*.xml */

19. containerProvider.init(this);

20.//针对"bean","constant","unknown-handler-stack"节点不包括"package"节点解析xml

21.//每一个bean 对应一个LocatableFactory LocatableFactory保存了bean的定义

22.//bean定义保存到ContainerBuilder#factories map集合中

23.//配置文件中定义的常量保存到props中

24. containerProvider.register(builder, props);

25. }

26.//将常量保存到ContainerBuilder#factories map集合中

27.//每一个常量对应一个LocatableConstantFactory

28. props.setConstants(builder);

29. builder.factory(Configuration.class, new Factory() {

30.public Configuration create(Context context) throws Exception {

31.return DefaultConfiguration.this;

32. }

33. });

34. ActionContext oldContext = ActionContext.getContext();

35.try {

36.//创建辅助容器 ContainerImpl并且实例化 struts一些核心类

37. Container bootstrap = createBootstrapContainer();

38. setContext(bootstrap);

39.//主容器这是一个全局变量

40. container = builder.create(false);

41. setContext(container);

42. objectFactory = container.getInstance(ObjectFactory.class);

43.// Process the configuration providers first

44.for (final ContainerProvider containerProvider : providers) {

45.if (containerProvider instanceof PackageProvider) {

46.//com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#setObje

47. container.inject(containerProvider);

48.//解析 xml package节点

49.//保存packageContexts map集合中

50.//com.opensymphony.xwork2.config.providers.XmlConfigurationProvider line 481

((PackageProvider) containerProvider).loadPackages();

51. packageProviders.add((PackageProvider) containerProvider);

52. }

53. }

54.// Then process any package providers from the plugins

55. Set packageProviderNames = container.getInstanceNames(PackageProvider.class);

if (packageProviderNames != null) {

56.for (String name : packageProviderNames) {

57. PackageProvider provider = container.getInstance(PackageProvider.class, name);

58. provider.init(this);

59. provider.loadPackages();

60. packageProviders.add(provider);

61. }

62. }

63.//TODO

64. rebuildRuntimeConfiguration();

65. } finally {

66.if (oldContext == null) {

67. ActionContext.setContext(null);

68. }

69. }

70.return packageProviders;

71. }

StrutsXmlConfigurationProvider的init方法具体在父类XmlConfigurationProvider中实现

1.public void init(Configuration configuration) {

2.this.configuration = configuration;

3.this.includedFileNames = configuration.getLoadedFileNames();

4.// configFileName ->struts.xml

5.//1.递归处理include节点

6.//2.生成Document 集合

7. loadDocuments(configFileName);

8.}

loadDocuments方法中调用了loadConfigurationFiles方法返回一个Document集合

1.private void loadDocuments(String configFileName) {

2. loadedFileUrls.clear();

3.//List documents

4. documents = loadConfigurationFiles(configFileName, null);

5.}

loadConfigurationFiles方法递归处理include节点最终生成Document集合

1.private List loadConfigurationFiles(String fileName, Element includeElement) {

2. List docs = new ArrayList();

3. List finalDocs = new ArrayList();

4.//防止include重复引入

5.if (!includedFileNames.contains(fileName)) {

6.if (LOG.isDebugEnabled()) {

7. LOG.debug("Loading action configurations from: " + fileName);

9. includedFileNames.add(fileName);

10. Iterator urls = null;

11. InputStream is = null;

12. IOException ioException = null;

13.try {

14. urls = getConfigurationUrls(fileName);

15. } catch (IOException ex) {

16. ioException = ex;

17. }

18.if (urls == null || !urls.hasNext()) {

19.if (errorIfMissing) {

20.t hrow new ConfigurationException("Could not open files of the name " + fileName, ioException);

} else {

https://www.doczj.com/doc/de319284.html,("Unable to locate configuration files of the name " + fileName + ", skipping");

return docs;

22. }

23. }

24. URL url = null;

25.while (urls.hasNext()) {

26.try {

27. url = urls.next();

28. is = FileManager.loadFile(url);

29. InputSource in = new InputSource(is);

30. in.setSystemId(url.toString());

31.//生成Document对象

32. docs.add(DomHelper.parse(in, dtdMappings));

33. } catch (XWorkException e) {

34.if (includeElement != null) {

35.throw new ConfigurationException("Unable to load " + url, e, includeElement);

} else {

36.throw new ConfigurationException("Unable to load " + url, e);

37. }

38. } catch (Exception e) {

39.final String s = "Caught exception while loading file " + fileName;

40.throw new ConfigurationException(s, e, includeElement);

41. } finally {

42.if (is != null) {

43.try {

44. is.close();

45. } catch (IOException e) {

46. LOG.error("Unable to close input stream", e);

47. }

48. }

49. }

50. }

51.//sort the documents, according to the "order" attribute

52. Collections.sort(docs, new Comparator() {

53.public int compare(Document doc1, Document doc2) {

54.return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));

55. }

57.for (Document doc : docs) {

58. Element rootElement = doc.getDocumentElement();

59. NodeList children = rootElement.getChildNodes();

60.int childSize = children.getLength();

61.for (int i = 0; i < childSize; i++) {

62. Node childNode = children.item(i);

63.if (childNode instanceof Element) {

64. Element child = (Element) childNode;

65.final String nodeName = child.getNodeName();

66.if ("include".equals(nodeName)) {

67. String includeFileName = child.getAttribute("file");

68.//可以使用通配符匹配

69.if (includeFileName.indexOf('*') != -1) {

70. ClassPathFinder wildcardFinder = new ClassPathFinder();

71. wildcardFinder.setPattern(includeFileName);

72. Vector wildcardMatches = wildcardFinder.findMatches();

for (String match : wildcardMatches) {

73.//递归处理include节点

74. finalDocs.addAll(loadConfigurationFiles(match, child));

}

75. } else {

76.//递归处理include节点

77. finalDocs.addAll(loadConfigurationFiles(includeFileName, child));

78. }

79. }

80. }

81. }

82. finalDocs.add(doc);

83. loadedFileUrls.add(url.toString());

84. }

85. }

86.return finalDocs;

87. }

StrutsXmlConfigurationProvider的register方法主要在父类XmlConfigurationProvider中实现

1.遍历init方法中生成的Document 集合解析xml文件中定义的bean,constant常量节点不会处理package节点

2.解析bean节点的值包装成LocatableFactory对象注册到ContainerBuilder中factories map集合中

3.解析constant节点的值保存到ContainerProperties 对象中

XmlConfigurationProvider 的register 这里只解析bean , constant节点

1.public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws

ConfigurationException {

2. Map loadedBeans = new HashMap();

3.for (Document doc : documents) {

4. Element rootElement = doc.getDocumentElement();

5. NodeList children = rootElement.getChildNodes();

6.int childSize = children.getLength();

7.for (int i = 0; i < childSize; i++) {

8. Node childNode = children.item(i);

9.if (childNode instanceof Element) {

10. Element child = (Element) childNode;

12.//解析bean节点

13.if ("bean".equals(nodeName)) {

14. String type = child.getAttribute("type");

15. String name = child.getAttribute("name");

16. String impl = child.getAttribute("class");

17. String onlyStatic = child.getAttribute("static");

18. String scopeStr = child.getAttribute("scope");

19.boolean optional = "true".equals(child.getAttribute("optional"));

20. Scope scope = Scope.SINGLETON;

21.if ("default".equals(scopeStr)) {

22. scope = Scope.DEFAULT;

23. } else if ("request".equals(scopeStr)) {

24. scope = Scope.REQUEST;

25. } else if ("session".equals(scopeStr)) {

26. scope = Scope.SESSION;

27. } else if ("singleton".equals(scopeStr)) {

28. scope = Scope.SINGLETON;

29. } else if ("thread".equals(scopeStr)) {

30. scope = Scope.THREAD;

31. }

32.if (StringUtils.isEmpty(name)) {

33. name = Container.DEFAULT_NAME;

34. }

35.try {

36. Class cimpl = ClassLoaderUtil.loadClass(impl, getClass());

37. Class ctype = cimpl;

38.if (StringUtils.isNotEmpty(type)) {

39. ctype = ClassLoaderUtil.loadClass(type, getClass());

40. }

41.if ("true".equals(onlyStatic)) {

42.// Force loading of class to detect no class def found exceptions

43. cimpl.getDeclaredClasses();

44. containerBuilder.injectStatics(cimpl);

45. } else {

46.// beanName + class 构成唯一约束

47.if (containerBuilder.contains(ctype, name)) {

48.//用loadedBeans map集合检查是否有重复配置的bean

49. Location loc = LocationUtils.getLocation(loadedBeans.get(ctype.getName() + name));

50.if (throwExceptionOnDuplicateBeans) {

51.throw new ConfigurationException("Bean type " + ctype +

52." with the name " + name + " has already been loaded by " + loc, child);

53. }

54. }

55.// Force loading of class to detect no class def found exceptions

56. cimpl.getDeclaredConstructors();

57.if (LOG.isDebugEnabled()) {

58. LOG.debug("Loaded type:" + type + " name:" + name + " impl:" + impl);

59. }

60.//LocatableFactory 类似spring中 BeanDefinition

61.//bean定义保存到ContainerBuilder#factories map集合中

63. containerBuilder.factory(ctype, name, new LocatableFactory(name,

ctype, cimpl, scope, childNode), scope);

64. }

65.//loadedBeans 检查重复配置的bean

66. loadedBeans.put(ctype.getName() + name, child);

67. } catch (Throwable ex) {

68.if (!optional) {

69.throw new ConfigurationException("Unable to load bean: type:" +

70.t ype + " class:" + impl, ex, childNode);

71. } else {

72. LOG.debug("Unable to load optional class: " + ex);

73. }

74. }

75.//constant常量节点

76. } else if ("constant".equals(nodeName)) {

77. String name = child.getAttribute("name");

78. String value = child.getAttribute("value");

79.//ContainerProperties ->props

80. props.setProperty(name, value, childNode);

81. } else if (nodeName.equals("unknown-handler-stack")) {

82.L ist unknownHandlerStack = new ArrayList();

83. NodeList unknownHandlers = child.getElementsByTagName("unknown-handler-ref");

84.int unknownHandlersSize = unknownHandlers.getLength();

85.for (int k = 0; k < unknownHandlersSize; k++) {

86. Element unknownHandler = (Element) unknownHandlers.item(k);

87.unknownHandlerStack.add(new UnknownHandlerConfig(unknownHandler.getAttribute("name")));

88. }

89.if (!unknownHandlerStack.isEmpty())

90. configuration.setUnknownHandlerStack(unknownHandlerStack);

91. }

92. }

93. }

94. }

95.}

96.

XmlConfigurationProvider的loadPackages方法解析package节点下的所有子节点interceptor ,ResultType等等

保存到DefaultConfiguration packageContexts map集合中

1.public void loadPackages() throws ConfigurationException {

2. List reloads = new ArrayList();

3.for (Document doc : documents) {

4. Element rootElement = doc.getDocumentElement();

5. NodeList children = rootElement.getChildNodes();

6.int childSize = children.getLength();

7.for (int i = 0; i < childSize; i++) {

8. Node childNode = children.item(i);

9.if (childNode instanceof Element) {

10. Element child = (Element) childNode;

11.final String nodeName = child.getNodeName();

13.//解析package节点包装成PackageConfig对象

14. PackageConfig cfg = addPackage(child);

15.if (cfg.isNeedsRefresh()) {

16. reloads.add(child);

17. }

18. }

19. }

20. }

21.//空实现扩展时用

22. loadExtraConfiguration(doc);

23. }

24.if (reloads.size() > 0) {

25. reloadRequiredPackages(reloads);

26. }

27.for (Document doc : documents) {

28.//空实现扩展时用

29. loadExtraConfiguration(doc);

30. }

31. documents.clear();

32. configuration = null;

33. }

package节点下的所有子节点

1.protected PackageConfig addPackage(Element packageElement) throws ConfigurationException {

2.PackageConfig.Builder newPackage = buildPackageContext(packageElement);

3.if (newPackage.isNeedsRefresh()) {

4.return newPackage.build();

5. }

6.//处理所有的ResultType 包括自定义的 , strust-default.xml中定义的

7. addResultTypes(newPackage, packageElement);

8.//interceptor节点

9. loadInterceptors(newPackage, packageElement);

10.//default-interceptor-ref

11. loadDefaultInterceptorRef(newPackage, packageElement);

12.//default-class-ref节点

13. loadDefaultClassRef(newPackage, packageElement);

14.//全局result global-results节点

15. loadGlobalResults(newPackage, packageElement);

16.//global-exception-mappings节点异常处理

17. loadGobalExceptionMappings(newPackage, packageElement);

18. NodeList actionList = packageElement.getElementsByTagName("action");

19.for (int i = 0; i < actionList.getLength(); i++) {

20. Element actionElement = (Element) actionList.item(i);

21.// action节点 result节点处理

22. addAction(actionElement, newPackage);

23. }

24.//default-action-ref

25. loadDefaultActionRef(newPackage, packageElement);

26. PackageConfig cfg = newPackage.build();

27.//TODO 保存到Map packageContexts 集合中

29.return cfg;

30.}

最后整理解析的ActionConfig Map集合[DefaultConfiguration#packageContexts] 最终已

Map>形式存储

1.public void rebuildRuntimeConfiguration() {

2. runtimeConfiguration = buildRuntimeConfiguration();

3.}

[java]

1.protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws Configurati

onException {

2. Map> namespaceActionConfigs =

3.new LinkedHashMap>();

4. Map namespaceConfigs = new LinkedHashMap();

5.for (PackageConfig packageConfig : packageContexts.values()) {

6.if (!packageConfig.isAbstract()) {

7. String namespace = packageConfig.getNamespace();

8. Map configs = namespaceActionConfigs.get(namespace);

9.if (configs == null) {

10. configs = new LinkedHashMap();

11. }

12. Map actionConfigs = packageConfig.getAllActionConfigs(

); for (Object o : actionConfigs.keySet()) {

13. String actionName = (String) o;

14. ActionConfig baseConfig = actionConfigs.get(actionName);

15.//这里设置action的拦截器

16.//TODO buildFullActionConfig

17. configs.put(actionName, buildFullActionConfig(packageConfig, baseConfig));

18. }

19.//key -> nameSpace

20.//value - > ,ActionConfig包含了拦截器

21. namespaceActionConfigs.put(namespace, configs);

22.if (packageConfig.getFullDefaultActionRef() != null) {

23. namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef());

24. }

25. }

26. }

27.return new RuntimeConfigurationImpl(namespaceActionConfigs, namespaceConfigs);

28.}

解析完成后, 最终会保存到DefaultConfiguration runtimeConfiguration变量中

初始化顺序图:

Container容器接口定义

1.public interface Container extends Serializable {

2./**

3. * Default dependency name.

4. */

5. String DEFAULT_NAME = "default";

6./**

7. * 对当前对象执行依赖注入

8. * 引用了@Inject注解的方法字段构造器参数

9. * @param o

10. */

11.void inject(Object o);

13. * 创建实例然后再依赖注入

14. */

15. T inject(Class implementation);

16./**

17. * 返回容器中类型和名称匹配的bean

18. */

19. T getInstance(Class type, String name);

20./**

21. * 返回容器中类型匹配的bean 可能是多个

22. */

23. T getInstance(Class type);

24./**

25. * 返回容器中类型匹配的 bean名称可能是多个

26. */

27. Set getInstanceNames(Class type);

28./**

29. * Sets the scope strategy for the current thread.

30. */

31.void setScopeStrategy(Scope.Strategy scopeStrategy);

32./**

33. * Removes the scope strategy for the current thread.

34. */

35.void removeScopeStrategy();

36.}

容器的实现类

1.class ContainerImpl implements Container {

2.}

容器的创建是由ContainerBuilder create方法完成

1.public Container create(boolean loadSingletons) {

2. ensureNotCreated();

3. created = true;

4.//factories 保存了 bean的定义常量的定义

5.//ContainerImpl factories factoryNamesByType

6. final ContainerImpl container = new ContainerImpl(new HashMap, InternalFactory>(factories));

7.if (loadSingletons) {

8. container.callInContext(new ContainerImpl.ContextualCallable() {

9.public Void call(InternalContext context) {

10.for (InternalFactory factory : singletonFactories) {

11. factory.create(context);

12. }

13.return null;

14. }

15. });

16. }

17.// xml配置 bean节点属性static 为true 默认为false

18.//com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#register() line 210

19. container.injectStatics(staticInjections);

20.return container;

21.}

ConfigurationProvider接口主要完成struts配置文件加载注册过程

ConfigurationProvider接口定义

1.public interface ConfigurationProvider extends ContainerProvider, PackageProvider { }

ContainerProvider接口定义

1./**

2. * 容器加载注册器

3. */

4.public interface ContainerProvider {

5.

6.public void destroy();

7./**

8. * 初始化阶段调用

9. * XmlConfigurationProvider#init为具体实现主要加载xml 生成Document对象

10. */

11.public void init(Configuration configuration) throws ConfigurationException;

12./**

13. * 根据xml常量设置是否支持reload

14. */

15.public boolean needsReload();

16./**

17. * 解析注册bean,struts常量到容器ContainerBuilder

18. */

19.public void register(ContainerBuilder builder, LocatableProperties props) throws

20.ConfigurationException;

21.}

PackageProvider接口定义

1./**

2. * package节点加载解析器

3. * 加载解析xml文件配置的package节点

4. * @since 2.1

5. */

6.public interface PackageProvider {

7./**

8. * 初始化阶段调用

9. * XmlConfigurationProvider#init为具体实现主要加载xml 生成Document对象

10. */

11.public void init(Configuration configuration) throws ConfigurationException;

12./**

13. * 根据xml常量设置是否支持reload

14. */

15.public boolean needsReload();

16./**

17. * 加载解析 xml文件中定义的package节点创建PackageConfig对象

18. */

19.public void loadPackages() throws ConfigurationException;

20.

21.}

StrutsXmlConfigurationProvider:struts 相关xml 加载解析

BeanSelectionProvider:根据struts常量配置初始化与其他框架整合用到的类例如xml中配置struts.objectFactory 为spring 就需要StrutsSpringObjectFactory

LegacyPropertiesConfigurationProvider:strutus 相关的properties文件

DefaultPropertiesProvider:初始化org/apache/struts2/default.properties文件

StrutsPrepareAndExecuteFilter doFilter方法为请求的入口

doFilter方法主要做以下几件事

一:根据配置的常量设置当前request 字符编码response国际化Locale信息

二:创建ActionContext数据对象

三:请求处理

1.分析url 根据url 创建ActionMapping对象这些操作主要由ActionMapper接口实现类完成

2. 执行请求逻辑动作

①.根据请求映射对象ActionMapping 创建ActionProxy 主要由ActionProxyFactory接口完成

②.执行Action 逻辑(拦截器,Action对应方法)

四:清理ActionContext数据对象

流程分析

1.public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)

2. throws IOException, ServletException {

3. HttpServletRequest request = (HttpServletRequest) req;

4. HttpServletResponse response = (HttpServletResponse) res;

5.try {

6.//根据struts2常量配置设置当前request Encoding 即request.setCharacterEncoding(encoding)

7.//当前 response 设置国际化Locale信息即response.setLocale(locale);

8. prepare.setEncodingAndLocale(request, response);

9.//创建ActionContext数据对象包括ValueStack

10. prepare.createActionContext(request, response);

12. prepare.assignDispatcherToThread();

13.if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {

14. chain.doFilter(request, response);

15. } else {

16.//包装request 返回StrutsRequestWrapper

17.//StrutsRequestWrapper继承了HttpServletRequestWrapper

18. request = prepare.wrapRequest(request);

19.//创建ActionMapping

20. ActionMapping mapping = prepare.findActionMapping(request, response, true);

21.if (mapping == null) {

22.boolean handled = execute.executeStaticResourceRequest(request, response);

23.if (!handled) {

24. chain.doFilter(request, response);

25. }

26. } else {

27.//真正执行Action的地方

28. execute.executeAction(request, response, mapping);

29. }

30. }

31. } finally {

32.//清除ActionContext

33. prepare.cleanupRequest(request);

34. }

35. }

一:设置编码字符国际化Locale信息,PrepareOperations#setEncodingAndLocale方法调用了 Dispatcher#prepare方法真正做事的还是Dispatcher

PrepareOperations类的setEncodingAndLocale 方法

1.public void setEncodingAndLocale(HttpServletRequest request, HttpServletResponse response) {

2. dispatcher.prepare(request, response);

3.}

Dispatcher的prepare方法

1.public void prepare(HttpServletRequest request, HttpServletResponse response) {

2.//struts.i18n.encoding 常量

3. String encoding = null;

4.if (defaultEncoding != null) {

5. encoding = defaultEncoding;

6. }

7. Locale locale = null;

8.if (defaultLocale != null) {

9. locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());

10. }

11.if (encoding != null) {

12.try {

13. request.setCharacterEncoding(encoding);

14. } catch (Exception e) {

15. LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);

16. }

17. }

18.if (locale != null) {

20. }

21.}

二:创建ActionContext数据对象由PrepareOperations#createActionContext方法完成

1.public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {

2. ActionContext ctx;

3. Integer counter = 1;

4. Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);

5.if (oldCounter != null) {

6. counter = oldCounter + 1;

7. }

8.//ActionContext与 ValueStack 是主从关系

9.//ActionContext中持有ValueStack

10. ActionContext oldContext = ActionContext.getContext();

11.if (oldContext != null) {

12. ctx = new ActionContext(new HashMap(oldContext.getContextMap()));

13. } else {

14.//ValueStack是由ValueStackFactory 创建

15. ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();

16. stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));

17.//将创建的ValueStack 保存到ActionContext

18. ctx = new ActionContext(stack.getContext());

19. }

20. request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);

21.//将当前ActionContext 保存到ThreadLocal中

22. ActionContext.setContext(ctx);

23.return ctx;

24.}

三:请求处理

1.创建ActionMapping对象一个ActionMapping对象对应一次请求,

ActionMapping定义

1.public class ActionMapping {

2.private String name;

3.private String namespace;

4.private String method;

5.private String extension;

6.private Map params;

7.private Result result;

8.}

PrepareOperations findActionMapping方法创建ActionMaping对象的动作转交给ActionMapper接口的getMapping方法完成

1.public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response, boolean f

orceLookup) {

2. ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);

3.if (mapping == null || forceLookup) {

4.try {

5.//ActionMapper 默认实现DefaultActionMapper

6.//getMapping方法主要负责查找对应的ActionConfig对象根据ActionConfig对象创建 ActionMapping

7. mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatche

r.getConfigurationManager());

9. request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);

10. }

11. } catch (Exception ex) {

12.//错误信息

13.dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);

}

14. }

15.return mapping;

16.}

ActionMapper 的实现类DefaultActionMapper , getMapping方法分析url ,根据url查找到的ActionConfig对象创建

ActionMapping

1.public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {

2.//实例化ActionMapping

3. ActionMapping mapping = new ActionMapping();

4. String uri = getUri(request);

5.int indexOfSemicolon = uri.indexOf(";");

6. uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;

7. uri = dropExtension(uri, mapping);

8.if (uri == null) {

9.return null;

10. }

11.// name, namspace处理

12. parseNameAndNamespace(uri, mapping, configManager);

13. handleSpecialParameters(request, mapping);

14.if (mapping.getName() == null) {

15.return null;

16. }

17.//处理action!menthod 形式

18. parseActionName(mapping);

19.return mapping;

20.}

[

1.protected void parseNameAndNamespace(String uri, ActionMapping mapping,

2. ConfigurationManager configManager) {

3. String namespace, name;

4.int lastSlash = https://www.doczj.com/doc/de319284.html,stIndexOf("/");

5.if (lastSlash == -1) {

6. namespace = "";

7. name = uri;

8. } else if (lastSlash == 0) {

9. namespace = "/";

10. name = uri.substring(lastSlash + 1);

11. } else if (alwaysSelectFullNamespace) {

12.// Simply select the namespace as everything before the last slash

13. namespace = uri.substring(0, lastSlash);

14. name = uri.substring(lastSlash + 1);

15. } else {

16.//配置元素管理器

17. Configuration config = configManager.getConfiguration();

20.boolean rootAvailable = false;

21.//config.getPackageConfigs()

22.for (Object cfg : config.getPackageConfigs().values()) {

23. String ns = ((PackageConfig) cfg).getNamespace();

24.//匹配nameSpace

25.if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() ||

26. prefix.charAt(ns.length()) == '/')) {

27.if (ns.length() > namespace.length()) {

28. namespace = ns;

29. }

30. }

31.if ("/".equals(ns)) {

32. rootAvailable = true;

33. }

34. }

35. name = uri.substring(namespace.length() + 1);

36.if (rootAvailable && "".equals(namespace)) {

37. namespace = "/";

38. }

39. }

40.if (!allowSlashesInActionNames && name != null) {

41.int pos = https://www.doczj.com/doc/de319284.html,stIndexOf('/');

5.if (pos > -1 && pos < name.length() - 1) {

6. name = name.substring(pos + 1);

7. }

8. }

9.//TODO

10. mapping.setNamespace(namespace);

11. mapping.setName(name);

12. }

处理action!menthod 形式

5.protected ActionMapping parseActionName(ActionMapping mapping) {

6.if (mapping.getName() == null) {

7.return mapping;

8. }

9.if (allowDynamicMethodCalls) {

10. String name = mapping.getName();

11.int exclamation = https://www.doczj.com/doc/de319284.html,stIndexOf("!");

12.if (exclamation != -1) {

13. mapping.setName(name.substring(0, exclamation));

14. mapping.setMethod(name.substring(exclamation + 1));

15. }

16. }

17.return mapping;

18. }

最新版本Struts2.3.12+Spring3.2.2+Hibernate4.2.0框架配置详细步骤

SSH框架搭建 Struts2.3.12+Spring3.2.2+Hibernate4.2.0 编号:SSH-S2-S3-H4 版本:V1.1 级别:公开 编写时间:2013-03-18

目录 1 导言 (1) 1.1 目的 (1) 1.2 范围 (1) 1.3 说明 (1) 2 搭建Struts2 (2) 2.1 搭建所需jar包 (2) 2.2 整合步骤 (2) 2.2.1 创建项目 (2) 2.2.2 导入jar包 (2) 2.2.3 配置web.xml (4) 2.2.4 创建web (4) 2.2.5 创建jsp页面 (5) 2.2.6 配置struts.xml (6) 2.2.7 配置Tomcat (6) 2.2.8 部署项目 (7) 2.3 测试 (8) 2.3.1 启动Tomcat (10) 2.3.2 测试Tomcat (10) 2.3.3 测试Struts (11) 3 整合Spring3 (12) 3.1 整合所需jar包 (12) 3.2 整合步骤 (12) 3.2.1 导入jar包 (12) 3.2.2 配置web.xml (12) 3.2.3 配置struts.xml (13) 3.2.4 配置spring.xml (13) 3.3 测试 (14)

3.3.1 启动Tomcat (14) 3.3.2 测试登录 (14) 4 整合Hibernate4 (15) 4.1 整合所需jar包 (15) 4.2 整合步骤 (15) 4.2.1 导入jar包 (15) 4.2.2 创建数据库ccc (15) 4.2.3 创建对象User (16) 4.2.4 生成映射文件User.hbm.xml (17) 4.2.5 创建dao (18) 4.2.6 创建service (19) 4.2.7 创建web (20) 4.2.8 配置jdbc.properties (21) 4.2.9 配置db.xml (22) 4.2.10 配置spring.xml (24) 4.2.11 配置struts.xml (24) 4.3 测试 (25) 4.3.1 启动Tomcat (25) 4.3.2 测试登录 (25)

Struts2框架工作原理及应用体会

2012年第11卷第6期 产业与科技论坛2012.(11).6 Industrial &Science Tribune Struts2框架工作原理及应用体会 □宋 君 张家爱 【摘要】通过针对特定用户的分析,搭建以Struts2为技术核心的旅行社管理系统。本文简单的介绍了MVC 、 Struts2的工作原理,同时总结了在项目制作过程中所得到的心得。 【关键词】 Struts2;MVC ;FilterDispatcher ;Action 【基金项目】本文为大学生科技创新院级基金项目(编号:2011070)成果 【作者单位】宋君,吉林农业科技学院信息工程学院;张家爱,吉林农业科技学院信息工程学院教师 本着锻炼自我与积极参与到实用性技术的目标,以发掘自身创新意识为前提。利用空闲时间,在老师的指导下,进行了一次大学生创新项目的实践性活动。本着实用原则,以某中小旅行社为客户(根据用户需求,匿名),以Struts2框架为基点,进行了一次旅行社管理系统的开发。在项目结束之余, 特将在项目过程中经历的种种认识进行了简单的总结,希望让阅读本文的朋友们,更多的参与到此类活动中。 一、基础思想— ——MVC 简述作为时下经典框架之一, MVC 具有其独特的价值。MVC 框架简单的说,就是将数据模型与用户视图进行分离。通过控制器进行协调处理的一种结构是框架。同时,也是本文中要讨论的Sturts2框架的基础思想。 M 是指模型层(Model ),V 是指用户视图(View ),C 则是指控制器 (Controller )。这种划分方式是以将模型层与视图层进行代码分离,从而降低两者之间的耦合性,使同一程序可以使用不同形式进行表现。不同层之间的修改不会或尽量少的印象到其他层功能的史前为前提。有效的提高的代码的维护性和设计难度。 图1 二、 Struts2工作原理(一)Struts2框架组成。Struts2框架由三个主要部分组成:核心控制器、业务控制器,以及由用户实现的业务逻辑组件。这里我们将侧重于核心控制器与业务控制器的理解与说明。 (二)核心控制器:FilterDispatcher 。FilterDispatcher 是Struts2框架的核心控制器,在此,我们可以将FilterDispatcher 看作一个类似于过滤网的过滤器。当用户发出请求,并到达Web 硬哟那种时,该过滤器会过滤用户请求。如果用户请求的结尾为action ,则将该请求转入Struts2框架进行处理。当Struts2框架获得了*.actio 请求后,会根据请求前面“*”的那部分内容,决定调用哪个业务逻辑组件作为响应单位。这里需要说明的是Struts2用来处理用户请求的Action 实例并不是业务控制器,而是作为Action 的代理———正因为Struts2的一大特点,与Servlet API 的非耦合性,使得用户实现的业务控制器无法直接处理用户请求。有效的提高了后期调试维护的效率。而Struts2框架再次提供了了一系列的拦截器。这些拦截器负责将HttpServletRequest 请求的参数解析出来,传入Action 中,并毁掉Action 的Execute 方法来处理用户请求。用户实现的Action 类仅作为Struts2的Action 代理的代理目标。用户实现的业务控制器则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest 对象中,而用户的Action 类无需访问HttpServletRequest 对象。拦截器负责将HttpServletRequest 里的请求数据解析出来,并传给业务逻辑组件Action 实例。 (三)业务控制器。业务控制器就是前文提到的用来实现用户Action 的实力,这里的每个Action 类通常包含有一个execute 方法,当业务控制器处理完用户的请求后,该方法将会针对此次处理返回一个字符串— ——该字符串就是一个逻辑树图名。当程序开发人员开发出系统所需要的业务控制器后,还需要针对性的配置Struts2的Action ,即需要配置Ac- tion 的以下三个部分:(1)Action 所处理的URl 。(2)Action 组件所对应的实现类。(3)Action 里包含的逻辑试图和物理资源之间的对应关系。每个Action 都要处理一个用户请求,而用户请求则总是包含有指定的URL 。当核心控制器过滤用户请求,并调用后,根据请求的URL 和Action 处理URL 之间的对应关系来处理转发。 · 342·

软件项目主要阶段及各个阶段主要工作

软件项目主要阶段及各个阶段主要工作 Document number:WTWYT-WYWY-BTGTT-YTTYU-2018GT

软件项目主要分为哪些阶段各个阶段主要做哪些工作 本人在两个中小型软件开发企业工作过几年,也做过几年的项目管理工作。走过一些弯路也得出一些项目管理方面的体会,在此进行总结,希望能够与其他一些项目管理人员或对项目管理有兴趣的同事共同探讨一些中小型项目管理的问题及方法。? 大部分中小型软件开发企业的软件项目经常遇到的一些问题可能包括:项目时间紧、项目组成员经常加班;项目需求变更频繁;项目进行过程中可能就有项目团队成员离职或调离到其他项目组;项目重复性建设问题严重,每个项目都需要从框架开始重新开发,难以重用已有项目的成果等等。我觉得通过较好的规划和管理能够在一定程度上提高项目的成功率或者说提高项目的质量,降低开发成本,缩短项目开发时间。? 我理解项目管理有两个大的划分方法一是通用的项目管理体系,也就是PMP 中所说的5个项目管理过程组9个知识领域44个项目管理过程;二是具体业务领域的按项目生命期划分的各阶段的管理。本文主要从项目生命期各阶段的管理方面进行总结。? 我个人分析一个软件项目生命期大体需要经过的流程(这只是我个人的一个划分,有可能不是很全面):可行性分析、需求、设计、开发、测试、实施、维护、总结。? 下面我针对每个阶段谈一下自己的体会。? 一、可行性分析? 一般的项目都是通过外部招标的形式得到的。对于有些公司在应标的时候对项目就要有个取舍。如果在特殊时期为了生存可能只要不是太赔的项目都会尽量承接。? 但是一般项目在承接前最好在经济、技术等方面进行可行性分析,而且这种可行性分析最好是管理者、市场、技术等人员都参与,因为市场人员一般不懂(或不通)技术,技术不懂(或不通)市场,因此只有大家在一起共同分析讨论才能够得出比较可行的结果。可行性分析的结果一方面可以作为是否承接项目的依据,另一方面也可以作为承接项目方式或与客户谈判的依据。比如经分析项目工作量很大,如果按标书金额开发有可能会赔,那么可以与用户探讨是否将来能有个二期的项目;另外如果用户要求的时间比较紧,可是经分析很难按标书时间完成,那么也可以和用户同共探讨是否可以在正式签定合同时延长系统交付时间等。当然这些与用户的探讨工作一般是需要公司高层领导出面协调的,有时单独靠项目组是没有能力达成理想的结果的。? 另外在此阶段最好对项目的成本和需要的资源进行一下估算。? 二、需求? 需求实际要细分为需求调研、需求分析、需求确认、需求管理等。? 因为对于需求要想说清楚可能需要较长的篇幅,所以在此不进行展开。? 在此只是先强调一下需要相当重要,如果早期需求做的不够仔细会给项目的后期工作带来很多的隐患。?

struts2验证框架

Struts2Validator Struts2验证框架 Updated Jun 18, 2010 by cm2...@https://www.doczj.com/doc/de319284.html, Action配置中一定要设置input返回页面 添加验证只要创建验证的xml文件 1.创建xml文件名 验证Action中全部方法 在Action同包下,创建:Action类名-validation.xml 如:ValidateAction创建ValidateAction-validation.xml 验证Action中单个方法 注意事项 注意: 1.要验证的方法不能叫input. 2.这样配置在form表单中要在中action写好名称, 不能写action="validate_",然后 这样会找不到对应的配置文件,跳过验证. 3.如果验证出错,返回input页面时,那些存在ValueStack中的值会丢失,可以将Action实现Preparable接口, 然后prepare()方法里初始化添加页面需要的值. 4.如果使用Preparable接口,必须在action配置中添加

java-struts2复习题

Struts2复习题 1.以下属于struts2的控制器组件是: A.Action B.ActionForm C.ActionServlet D.dispatchAction 2.以下属于struts2的体系结构的是:(多选) A.struts2控制器组件 B.struts2配置文件 C.FilterDispathcer D.Action 3.以下属于struts2配置文件中的配置元素是:(多选) A. B. C. D. 4.关于struts1和struts2对比的说法正确的是: A.struts1要求Action类继承struts1框架中的Action父类,struts2中则不一定需要继承,可以是POJO类 B.struts1中的Action不是线程安全的,而struts2中的Action是线程安全的 C.struts1和struts2中都使用ActionForm对象封装用户的请求数据 D.struts1使用OGNL表达式语言来支持页面效果,struts2通过ValueStack技术使标签库访问值 5.以下关于ValueStack说法正确的是:(多选) A.每个Action对象实例拥有一个ValueStack对象 B.每个Action对象实例拥有多个ValueStack对象 C.Action中封装了需要传入下一个页面的值,这些值封装在ValueStack对象中 D.ValueStack会在请求开始时被创建,请求结束时消亡 6.关于struts2配置文件说法正确的是: A.必须在WEB-INF/classes目录下 B.名字必须为struts.xml C.配置Action时,必须配置包信息 D.使用元素配置转发 7.在struts2配置中用()元素来配置常量: A. B. C. D. 8.关于struts2包的说法正确的是: A.struts2框架使用包来管理常量 B.struts2框架定义包时必须指定name属性 C.struts2框架中配置包时,必须继承自struts-default包,否则会报错 D.struts2框架中使用包来管理Action 9.struts2中获取Servlet API的方法正确的是:(多选) A.使用ActionContext对象以解耦合的方法访问Servlet API B.使用ServletActionContext对象以解耦合的方式访问Servlet API C.使用ActionContext对象以耦合的方式访问Servlet API D.使用ServletActionContext对象以耦合的方式访问Servlet API 10.struts2动态调用的格式为: A.ActionName?methodName.action B.ActionName! methodName.action C.ActionName*methodName.action D.ActionName@mathodName.action 11.如果要实现struts2的数据校验功能 A.普通Action类可以实现

struts2 实验报告

1.系统分析与设计 1.1 系统功能描述 本系统是个非常简单的注册、登录系统。本系统的实现是基于Struts2、Spring、Hibernate 三个框架,系统功能单一,业务逻辑简单。 当用户注册信用户时,就是向系统中增加一个新用户,对应的数据库增加一条记录。 当用户输入注册信息时,系统提供了基本的输入验证判断用户输入是否合法,只有当用户输入满足基本输入要求时,才会被提交到实际的登录系统,进行实际的登录处理。 系统还使用了随机产生的图形验证码来防止刷新,防止用户通过单击浏览器的书安心按钮来重复注册多个用户。 系统还提供了一种Ajax方式来验证用户输入的注册名是否有效,系统要求所有的用户名不能重复。故当用户输完用户名后,系统立即在页面上方提示用户该用户名是否可用,如果系统中没有该用户名,则系统提示该用户名可用;否则提示用户该用户名重复,用户必须重新选择用户名注册。 当用户注册一个新用户名之后,就可以使用系统的登录功能来登录系统了,用户输入登录用的用户名、密码后,系统一样提供了基本的输入校验。 除此之外,系统还采用了随机产生图形验证码来防止恶意用户的暴力破解,系统随机生成一个图形验证码,而用户登录必须输入图形验证码中显示的字符串,只有用户输入的字符串和系统随机生成的验证码字符相同时,系统才允许用户登录。 1.2 系统功能流程

1.3 数据库设计 相关的映射文件: 一旦提供了上面的映射文件,Hibernate 就可以理解User 和user_table 之间的对应关系。 2.系统实现与测试 2.1 系统采用的关键技术 MVC 框架采用了Struts2框架,Struts2框架的易用性,极好的简化了系统的MVC 层的实现;本系统使用了Struts2的JSON 插件来完成Ajax 功能,除此之外本系统为了避免进行底层的Ajax 交互,还是用了一个简单Prototype.js 函数库,用以简化Ajax 编程。Struts2框架的稳定性,为系统的稳定运行提供了保证。

BBS论坛系统 UML建模

软件建模与UML 实训报告 实训项目:________________________ 小组名称:________________________ 小组成员:________________________ 联系方式:________________________

目录 一、摘要 (1) 二、BBS论坛系统的可行性分析 (2) 三、BBS论坛系统的需求分析 (3) 四、系统的UML建模设计 (6) 五、BBS系统的数据库建模 (14) 六、心得 (19)

一、摘要 随着Internet技术的快速发展,人与人之间交流方式逐渐增多。网络视频、网络聊天、博客已成为人们彼此沟通、交流信息的主要方式。此外,为了方便人们在某一专业领域探讨问题和发表意见,Internet上还出现了在线论坛。在论坛上,人们可以对某一领域提出自己遇到的问题,即发表某一主题,随后,论坛上的其他人会根据自己的学识、经验发表意见或提出问题的方法。 开发BBS论坛系统的目的是提供一个供用户交流的平台,为广大用户提供交流经验、探讨问题的网上社区。因此,BBS论坛系统最基本的功能首先是发表主题,其次是其他人员根据主题发表自己的看法。此外,为了记录主题的发表者和主题的回复者信息,系统还需要提供用户注册和登录的功能。只有注册的用户登录后才能够发表和回复主题,浏览者(游客)只能浏览主题信息。 本论坛系统是基于是Struts1.2+SQL Server 2000实现的,它具有使用方便、操作灵活、运行稳定、安全可靠等特点。 关键词在线论坛,BBS,网上社区

二、BBS论坛系统的可行性分析 可行性分析是在系统调查的基础上,针对新系统的开发是否具备必要性和可能性,对新系统的开发从技术、经济、社会的方面进行分析和研究,以避免投资失误,保证新系统的开发成功。可行性研究的目的就是用最小的代价在尽可能短的时间内确定问题是否能够解决。 2.1、技术可行性 技术上的可行性分析主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。该BBS论坛管理系统采用了流行的JSP语言和当前新兴的Browser/Server (浏览器/服务器)模式进行开发。三层的B/S体系结构具有许多传统Client/Server(客户机/服务器)体系结构不具备的优点,而且又紧密的结合了Internet/Intranet(国际互联网/企业内部互联网)技术,是技术发展的大势所趋,它把应用系统带入了一个崭新的发展时代。数据库服务器选用SQL Server 2000数据库,它能够处理大量数据,同时保持数据的完整性并提供许多高级管理功能。它的灵活性、安全性和易用性为数据库编程提供了良好的条件。因此,系统的软件开发平台已成熟可行。硬件方面,科技飞速发展的今天,硬件更新的速度越来越快,容量越来越大,可靠性越来越高,价格越来越低,其硬件平台能满足此系统的需要。 2.2、经济可行性 主要是对项目的经济效益进行评估,本系统模拟的是提供一个供用户交流的平台,为广大用户提供交流经验、探讨问题的社区。但实际只是用于个人的毕业设计,只是模拟,也不存在资金的流动,故在经济上是可行的。 2.3、社会可行性 随着Internet技术的快速发展,BBS论坛已成为人们彼此沟通、交流信息的主要方式。在论坛上,人们可以对某一领域提出自己遇到的问题,随后,论坛上的其他人会根据自己的学识、经验发表意见或提出问题的方法。BBS论坛接近了人们之间的距离,它早已成为人们网上生活的必备工具。所以说BBS论坛对当今社会是相当重要的。

structs2知识点

Struts2原理 上图来源于Struts2官方站点,是Struts 2 的整体结构。 Struts2框架由3个部分组成:核心控制器FilterDispatcher、业务控制器和用户实现的业务逻辑组件。在这3个部分里,Struts 2框架提供了核心控制器FilterDispatcher,而用户需要实现业务控制器和业务逻辑组件。 (1)核心控制器:FilterDispatcher

FilterDispatcher是Struts2框架的核心控制器,该控制器作为一个Filter运行在Web应用中,它负责拦截所有的用户请求,当用户请求到达时,该Filter 会过滤用户请求。如果用户请求以action结尾,该请求将被转入Struts2框架处理。 Struts2框架获得了*.action请求后,将根据*.action请求的前面部分决定调用哪个业务逻辑组件,例如,对于login.action请求,Struts2调用名为login的Action来处理该请求。 Struts2应用中的Action都被定义在struts.xml文件中,在该文件中定义Action 时,定义了该Action的name属性和class属性,其中name属性决定了该Action 处理哪个用户请求,而class属性决定了该Action的实现类。 Struts2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理——因为用户实现的业务控制器并没有与Servlet API耦合,显然无法处理用户请求。而Struts2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的请求参数解析出来,传入到Action中,并回调Action 的execute方法来处理用户请求。 (2)一个请求在Struts2框架中的处理大概分为以下几个步骤 1 .客户端初始化一个指向Servlet容器(例如Tomcat)的请求,即HttpServletRequest请求。 2 .这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3. 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action 4 .如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 5 .ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类 6 .ActionProxy创建一个ActionInvocation的实例。 7 .ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 8 .一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

如何看懂源代码--(分析源代码方法)

如何看懂源代码--(分析源代码方法) 4 推 荐 由于今日计划着要看Struts 开源框架的源代码 昨天看了一个小时稍微有点头绪,可是这个速度本人表示非常不满意,先去找了下资 料, 觉得不错... 摘自(繁体中文 Traditional Chinese):http://203.208.39.132/translate_c?hl=zh-CN&sl=en&tl=zh-CN&u=http://ww https://www.doczj.com/doc/de319284.html,/itadm/article.php%3Fc%3D47717&prev=hp&rurl=https://www.doczj.com/doc/de319284.html,&usg=AL kJrhh4NPO-l6S3OZZlc5hOcEQGQ0nwKA 下文为经过Google翻译过的简体中文版: 我们在写程式时,有不少时间都是在看别人的代码。 例如看小组的代码,看小组整合的守则,若一开始没规划怎么看,就会“噜看噜苦(台语)”不管是参考也好,从开源抓下来研究也好,为了了解箇中含意,在有限的时间下,不免会对庞大的源代码解读感到压力。网路上有一篇关于分析看代码的方法,做为程式设计师的您,不妨参考看看,换个角度来分析。也能更有效率的解读你想要的程式码片段。 六个章节: ( 1 )读懂程式码,使心法皆为我所用。( 2 )摸清架构,便可轻松掌握全貌。( 3 )优质工具在手,读懂程式非难事。( 4 )望文生义,进而推敲组件的作用。( 5 )找到程式入口,再由上而下抽丝剥茧。( 6 )阅读的乐趣,透过程式码认识作者。 程式码是别人写的,只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程式码。但是,与其抗拒接收别人的程式码,不如彻底了解相关的语言和惯例,当成是培养自我实力的基石。 对大多数的程式人来说,撰写程式码或许是令人开心的一件事情,但我相信,有更多人视阅读他人所写成的程式码为畏途。许多人宁可自己重新写过一遍程式码,也不愿意接收别人的程式码,进而修正错误,维护它们,甚至加强功能。 这其中的关键究竟在何处呢?若是一语道破,其实也很简单,程式码是别人写的,只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感,深怕被迫去碰触其他人所写的程式码。这是来自于人类内心深处对于陌生事物的原始恐惧。 读懂别人写的程式码,让你收获满满 不过,基于许多现实的原因,程式人时常受迫要去接收别人的程式码。例如,同事离职了,必须接手他遗留下来的工作,也有可能你是刚进部门的菜鸟,而同事经验值够了,升级了,风水轮流转,一代菜鸟换菜鸟。甚至,你的公司所承接的专案,必须接手或是整合客户前一个厂商所遗留下来的系统,你们手上只有那套系统的原始码(运气好时,还有数量不等的文件)。 诸如此类的故事,其实时常在程式人身边或身上持续上演着。许多程式人都将接手他人的程式码,当做一件悲惨的事情。每个人都不想接手别人所撰写的程式码,因为不想花时间去探索,宁可将生产力花在产生新的程式码,而不是耗费在了解这些程式码上。

02-Struts2的工作流程及配置文件

Struts2的工作流程及配置文件--- https://www.doczj.com/doc/de319284.html, --- Struts2.0的流程图

从图中看到Struts2的工作流程如下: 1.服务器接收到的请求首先经过一组过滤器链(实际中的其他过滤器可能还包括诸如Spring 的字符过滤器CharactorEncodingFilter、V elocity的过滤器等,一般FilterDispatcher位于过滤器的最后一个执行),过滤器链按照你在web.xml中的配置顺序在接收客户请求时顺序执行,在向客户发送响应时反序执行,Struts2的核心FilterDispatcher在web.xml中的配置如下: setCharactor org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 struts2 org.apache.struts2.dispatcher.FilterDispatcher setCharactor /* struts2 /* 注意:如果你使用的是W ebLogic6.1作为应用服务器,需要使用FilterDispatcherCompatW eblogic61替代FilterDispatcher。 2.请求被送到FilterDispatcher之后,FilterDispatcher会通过其私有静态的属性ActionMapper 询问这个请求是否需要调用Action处理,如果需要调用Action,FilterDispatcher会把请求委托给ActionProxy,ActionProxy调用ActionInvocation查找配置文件中该Action的所有信息,并以这个Action为目标创建代理对象(因为Struts2中的Action由于XWork的设计理念,并没有与Servlet的API被调用,所以如果直接调用Action的实例,那么显然基于HTTP 的请求都将无法传入Action。Struts2通过创建Action的代理对象,并使用拦截器将HTTP 的请求信息传入代理对象,这是典型的AOP处理方式,这也实现了控制器与Servlet的API 的分离,这是Struts1.x所欠缺的优秀的设计方式),然后执行该Action之前的所配置的所有拦截器,与过滤器相同,在接受请求时,会顺序执行你在配置文件中为该Action配置的拦截器顺序; 3.在穿越拦截器之后,就会执行Action,当Action执行完毕,ActionInvocation就要使用result

Struts2的工作机制原理分析及实例

Struts2的工作机制分析及实例 一、概述 本章讲述Struts2的工作原理。 读者如果曾经学习过Struts1.x或者有过Struts1.x的开发经验,那么千万不要想当然地以为这一章可以跳过。实际上Struts1.x 与Struts2并无我们想象的血缘关系。虽然Struts2的开发小组极力保留Struts1.x的习惯,但因为Struts2的核心设计完全改变,从思想到设计到工作流程,都有了很大的不同。 Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork 的核心,所以,Struts2并不是一个不成熟的产品,相反,构建在WebWork基础之上的Struts2是一个运行稳定、性能优异、设计成熟的WEB框架。 本章主要对Struts的源代码进行分析,因为Struts2与WebWork的关系如此密不可分,因此,读者需要下载xwork的源代码,访问https://www.doczj.com/doc/de319284.html,/xwork/download.action即可自行下载。 下载的Struts2源代码文件是一个名叫struts-2.1.0-src.zip的压缩包,里面的目录和文件非常多,读者可以定位到 struts-2.1.0-src\struts-2.0.10\src\core\src\main\java目录下查看Struts2的源文件,如图14所示。 (图14) 二、主要的包和类 Struts2框架的正常运行,除了占核心地位的xwork的支持以外,Struts2本身也提供了许多类,这些类被分门别类组织到不同的包中。从源代码中发现,基本上每一个Struts2类都访问了WebWork提供的功能,从而也可以看出Struts2与WebWork千丝万缕的联系。但无论如何,Struts2的核心功能比如将请求委托给哪个Action处理都是由xwork完成的,Struts2只是在WebWork 的基础上做了适当的简化、加强和封装,并少量保留Struts1.x中的习惯。

j2ee框架Struts2HibernateSpring考试复习题库

1.Eclipse是IMB公司向开放源代码社区捐献的Java程序开发平台,是一个成熟的、可扩展的体系结构。 2.Eclipse主要包含3个子项目:平台子项目,Java开发工具子项目,插件开发环境子项目。 3.MVC是Model(模型)业务逻辑层,View(试图)表述层,Controller(控制)控制层。 4.Struts是Apache Jakarta项目于2001年推出的一个开元的Java Web框架,通过一个配置文件,把各个层面的应用组件联系起来,使组件在程序层面上联系较少,耦合度较低,提高了应用程序的可维护性和扩展性。 5. Struts框架有两种发行包:源代码(source)和二进制(binary)。 6. Struts框架大约由300个Java类组成,可分为8个核心包:config,action,actions,tiles,upload,taglib,util,validator。 7. Struts的核心API包括ActionServlet,ActionForm,Action,ActionMapping及ActionForward,它们构成了Struts框架中的控制器组件,视图组件,模型组件 8.Hibernate是对象/关系映射(ORM)的解决方案,就是将Java对象与对象关系映射成关系数据库中表格与表格之间的关系。 9. Cache就是缓存,它往往是提高系统性能的在最重要手段,对数据起到一个蓄水池和缓冲的作用。 10. Session实现了第一级Cache,它属于事务级数据缓冲,二级Cache是SessionFactory范围内的缓冲,所有的Session共享同一个二级Cache。 11.设置Hibernate的二级Cache需要分两部进行:首先确认使用什么数据并发策略,然后设置缓存过期时间和设置Cache提供器。 12.Spring是指一个用于构造Java应用程序的轻量级框架。13.IoC是一种将组件依赖关系的创建和管理置于程序外部的技术。 1.MVC设计模式的J SP Model1和JSPModel2的区别?答:对Model1而言,JSP页面会完成请求的所有处理事项,负责向客户显示输出,整个流程并没有Servlet的参与,客户请求直接送往JSP页面,JSP页调用JavaBean组件或其他业务组件处理请求,并把结果在另一个页面显示出来。对Model2而言,客户请求不是直接送给JSP页面,而是送给一个Servlet 进行前端处理。一旦请求处理完毕,Servlet会把请求重定向到适当的JSP页面。 2. Struts 的基本原理?答:首先从struts-config.xml文件中读取信息,根据这些信息,它的控制器ActionServlet知道把视图中的请求转发给哪个业务逻辑组件处理。视图组件、控制器与业务逻辑组件之间没有代码上的联系,它们之间的关系在struts-config.xml中声明,这样大大提高了Web应用程序的可移植性和可维护性。 3. S truts的核心组件?答:ActionServlet的类扩展了javax.servlet.http.HttpServlet类,其职责是把HTTP消息打包起来并路由传送到框架中合适的处理器。Struts框架中的org.apache.struts.action.Action类是控制器组件的一个扩展。struts-config.xml是整个Struts 应用程序的枢纽。ActionMapping,控制器要通过查看请求信息并使用一组动作映射对象来作出决定。ActionForward,在Action完成之后,控制器要转交控制权的地方。ActionForm 对象可用来在用户和业务层之间传输客户的输入数据。 4. Struts框架如何处理每个请求相应的ActionForm对象?答:①检查该项动作的相应映射,查看是否已经有某个ActionForm得到配置②如果对应这个动作配置了某个ActionForm,则使用action元素中的name属性来查找FormBean的配置信息③查看是否已经创建了ActionForm的一个实例④如果在适当的作用域内已经存在一个ActionForm实例,而且这个实例的类型正是这个新请求所需要的类型,则重用这个实例⑤否则,创建所需ActionForm 的一个新实例,并存储在适当的作用域。⑥调用ActionForm实例的reset()方法⑦反复处理请求参数,如果参数名在ActionForm实例中具有对应的设置方法,就为它填上请求参数的

Struts2知识点总结

Struts2基础知识 Struts2概述 1.Struts2框架应用javaee三层结构中的web层框架。 2.Struts2框架在struts1和webwork基础之上发展的全新框架。 3.Struts2所解决的问题: 在以往实现一个功能时,都需要写很多的servlet,从而造成后期维护上的不方便。 图解: 4.现在比较稳定的Struts2版本 struts-2.3.24-all.zip 5.web层常见框架 1.struts 2.springMVC Struts2框架入门 1.导入jar包 1.在lib里面有jar包,但不能全部导入,因为里面含有一些spring 包,是不能使用的,导入会导致程序不能运行。 2.到app目录里面复制案例的jar包是最好的方法。 2.创建action 3.配置action类的访问路径

1.创建struts2核心配置文件,该核心配置文件位置和名称是固定的, 位置必须在src下面,名称为struts.xml 。 2.引入dtd约束,可以在案例文件中找到,复制在struts.xml文件中即 可。 3.action的配置 *注意访问路径: http://域名/端口号/项目名/action名.action 注意:.action可以省略,但建议不要省略,为了兼容一些老版本的浏览器。 4.配置Struts2的过滤器,可以在案例中的web.xml文件中找到,复制粘贴 即可。 Struts2执行过程 图解:

Struts2配置

1.是一种常量标签 2.修改Struts2的默认常量值 1.常用方式 在struts.xml中进行配置。 2.其它两种方式 1.在src下面创建struts.properties文件并修改。 2.在web.xml文件中进行修改。 3.Struts2最常用的常量 struts.il8n.encoding=UTF-8,解决表单在通过post方式提交中文时,中文乱码的问题。

基于Struts2框架的信息发布系统的设计与初步实现

第一章Struts2的起源和发展 说到网络应用很难让人不联想到网络信息的浏览,自从Internet进入民用领域之后,上网成为了越来越多的人闲暇时光的消磨手法。于是网络系统的开发也变得越来越总要。 1.1 Web技术的发展 随着Internet技术的大面积应用和发展,传统的静态HTML页面由于缺乏足够的用户交互能力已经无法满足日益膨胀的网络需求。人们希望Web应用中能够包含更多的动态交互功能,于是为了应对拥有更广泛用户群的动态Web开发,软件开发商分别推出的ASP和JSP两款动态网站开发解决方案。但是当时的JSP 开发并没有很科学的层次设计,最初的JSP开发中逻辑代码和前端代码杂合在一起。虽然在最初开发时这样的做法使得开发非常的容易,然而随着Web系统的使用越来越广泛,应用规模的日益增长,如果继续使用传统的简单的JSP + Servlet 结构进行Web系统的开发,则会由于系统层次混乱而导致系统的开发难度和维护成本越来越大,最终使开发过程陷入困境。 1.2 MVC思想进入Web系统开发 面对开发过程中所出现的困难,开发者们试图寻找一种能够使得开发结构更加具有条理性的开发模式。根据以往面向对象系统设计的经验,开发者开始将MVC开发模式引入Web系统的开发。MVC模式将一个应用分为三个基本部分:Model(模型)、View(视图)、Controller(控制器)。在此模式中触发事件由控制器捕获,并根据事件的类型来改变模型和视图。这样既可将系统模型与视图分离,从而使各部分能够工作在最小的耦合状态下协同工作,从来提高系统的扩展性和可维护性。将其引入Web系统开发后,系统模式由传统的JSP完成用户请求和响应改变为由控制器捕获用户请求,JavaBean完成模型操作,而JSP专门负责响应用户需求。老一代的开发框架Struts1便是这时的产物。

Struts2考试题分析

题目1 以下不届丁 Struts2中result 的type 届性() ? A. action B. redirect 题目2 下歹0有关拦截器说法错误的是? 「A.struts 通过拦截器完成执行action 请求处理方法前一系歹U 操作。例如: 数据封装、文件上传、数据校验等 'B.在struts 中,直接访问jsp 页面,struts 将使用默认拦截器栈处理当前 请求。 厂C.在执行action 时,struts 将执行若干拦截器1、2、3,执行action 完成 后,将继续执行拦截器3、2、1 'D.默认情况,在一个action 没有配置拦截器的引用,说明当前action 将不 使用拦截器 题目3 以下哪些是Action 接口提供的返回值? W A A. success ,D B. none C. error 财 D.input 题目4 如果要实现struts2的数据检验功能 广A 普通的Action 类可以实现 C. redirectAction D. dispatcher

「B继承自Action接口的可以实现 面C继承自ActionSupport类可以实现 厂D继承自ActionValidate 类可以实现 题目5 struts2默认的处理结果类型是: ? A.dispatcher ' B.redirect 「C.chain D. forward 题目6 在值栈的上下文Context中,存在一些固定的key表示不同的对象,以下描述正确的是? A. request,表示request作用域的数据 'B.session,表示session 作用域的数据 阿 C.application ,表示application 作用域的数据 * D.parameters ,表示请求参数的所有数据 题目7 以下届丁struts2配置文件中的配置元素是:()多选) A. B. 厂 C. 厂 D.

相关主题
文本预览
相关文档 最新文档