哈哈,一颗好奇心、一颗永不满足的心让我终于解决了这个问题。
解决问题来源:官方的教程(英文的,虽然英语不咋地,还是硬着头皮给看完了。(*^__^*) 嘻嘻……),获取办法google搜索struts2然后找到带有apache的网址,也就是在www.apache.org中的一个分支了。
下面就说一下里面的具体问题吧:
当我们需要用到注解的时候,需要引入一个jar包,名字为:struts2-convention-plugin-2.3.1.2.jar,先提示一下,千万别小看这个包哦,这个包可是很“智能”的,如果你很想自己手工完成某些操作,而你引入了这个包,它很可能破坏你的打算哦。下面就看一下这个包的作用了:
默认情况下Convention plugin监听包名含有:stru、struts2、action或者actions这些包中的action类,也就是说如果你建立的包名最后包含上述这几个类型,那么action就会自动的将它作为你的action处理类所在的包。
那么我们自己编写的action呢就应该实现action接口或者以action结尾,那么Convention plugin就会自动识别这些类。
并且啊,这个Convention plugin还会用类的名字去匹配URL,也就是说:如果你发出的一个请求是请求hello.action,如果你有一个类名为HelloAction(可以不实现Action接口)或者类名为Hello(实现Action接口),那么你就可以不进行任何的配置(指的是struts.xml中配置action和URL的映射,并且也没有采用注解方式配置)就可以形成一个Action和URL的映射。神奇吧,这个就是Convention plugin的智能,别急,不要急着去实践,下面还有呢。。。
此刻Convention plugin已经知道了如何的将请求和Action对应起来,那么它是否可以智能的将结果和结果页面对应呢。当你看到这个问题的时候估计和我的想法一样:这怎么可能呢,返回的结果有那么多的情况:input、error、success等等,它怎么可以自动的寻找映射呢。(*^__^*) 嘻嘻……那你也太小看Convention plugin这个包了,它的确可以形成映射,但是前提就是你的结果页面必须的符合一定的命名规则,并且存储的路径也不能随便存储哦。它的具体规则为:1、通常情况下Convention
plugin包会默认为处理的结果页面位于WEB-INF/content这个路径下(此路径可以在struts.properties中进行修改,要修改的属性为:上struts.convention.result.path
);2、结果的命名也就是在你请求的页面后面加上结果信息了,例如:刚刚请求的是Hello,那么你可以在前面要求的路径下建立一个hello.jsp(返回success时会执行)、hello-success.jsp(返回success时会执行)、hello-input.jsp(返回input的时候会执行),剩下的就依葫芦画瓢了,也就是”你的请求”+”-”+”结果类型”.jsp,当然还可以有其它的类型,例如:freeMaker等。
看到这儿,基本上那个问题都已经解决了。
那么下面,我们就看一下官方提供的一个示例源代码了:
在看源代码前,先看一下整体的命名规则及其所需要引入的库:
先看一下Web.xml中的配置吧
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Struts2Example1</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
再看一下Index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
<s:form action="welcome-user" >
<s:textfield name="userName" label="User Name" />
<s:submit />
</s:form>
</body>
</html>
下面的是URL对应的action:
package com.vaannila.action;
import com.opensymphony.xwork2.ActionSupport;
public class WelcomeUser extends ActionSupport{
private String userName;
private String message;
public String execute() {
message = "Welcome " + userName;
return SUCCESS;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setMessage(String message) {
this.message = message;
}
public String getUserName() {
return userName;
}
public String getMessage() {
return message;
}
}
<!--[endif]-->下面的是用来显示结果的页面:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome User</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
至此已经完成了。。。。
还有一个顺便提醒一下:不知大家有没有留意什么时候保存.java文件的时候服务器会自动重启。。。我的观察结果:如果你的类不是重要的类(处理用户请求的类为重要类)或者文件不是重要的配置文件,那么服务器就不会重启,因为此刻牵扯到如果你的action放在一个包名不为convention
plugin所自动化解析的包中的时候,并且你采用的是注解方式配置(因为我只做了这个测试,所以此处只说这种情况,其它的大家可以自己测试),那么你修改了action类,服务器不会重启。
觉得还是分析一下源代码比较好。。。。要不然总感觉到有些玄乎。。。
此刻我没有采用单步调试,只是简单的看了一下convention plug-in包中的部分代码,如果谁进行单步调试并分析了结果还希望可以分享一下哦。。。
下面总结一下看的结果:
org.apache.struts2.convention.
DefaultResultMapBuilder这个类中有一个函数就实现了结果页面的自动映射,其实看这个类的名字也很容易发现的:默认生成结果映射
/**
* Makes all the results for the given path.
*
* @param actionClass The action class the results are being built for.
* @param path The path to build the result for.
* @param resultPrefix The is the result prefix which is the result location plus the action name.
* This is used to determine if the path contains a result code or not.
* @param results The Map to place the result(s)
* @param packageConfig The package config the results belong to.
* @param resultsByExtension The map of extensions to result type configuration instances.
*/
protected void makeResults(Class<?> actionClass, String path, String resultPrefix,
Map<String, ResultConfig> results, PackageConfig packageConfig,
Map<String, ResultTypeConfig> resultsByExtension) {
if (path.startsWith(resultPrefix)) {
int indexOfDot = path.indexOf('.', resultPrefix.length());
// This case is when the path doesn't contain a result code
if (indexOfDot == resultPrefix.length() || !flatResultLayout) {
if (LOG.isTraceEnabled()) {
LOG.trace("The result file [#0] has no result code and therefore" +
" will be associated with success, input and error by default. This might" +
" be overridden by another result file or an annotation.", path);
}
//下面就是分析是否包含有返回结果类型的页面了
if (!results.containsKey(Action.SUCCESS)) {
ResultConfig success = createResultConfig(actionClass,
new ResultInfo(Action.SUCCESS, path, packageConfig, resultsByExtension),
packageConfig, null);
results.put(Action.SUCCESS, success);
}
if (!results.containsKey(Action.INPUT)) {
ResultConfig input = createResultConfig(actionClass,
new ResultInfo(Action.INPUT, path, packageConfig, resultsByExtension),
packageConfig, null);
results.put(Action.INPUT, input);
}
if (!results.containsKey(Action.ERROR)) {
ResultConfig error = createResultConfig(actionClass,
new ResultInfo(Action.ERROR, path, packageConfig, resultsByExtension),
packageConfig, null);
results.put(Action.ERROR, error);
}
// This case is when the path contains a result code
} else if (indexOfDot > resultPrefix.length()) {
if (LOG.isTraceEnabled()) {
LOG.trace("The result file [#0] has a result code and therefore" +
" will be associated with only that result code.", path);
}
String resultCode = path.substring(resultPrefix.length() + 1, indexOfDot);
ResultConfig result = createResultConfig(actionClass,
new ResultInfo(resultCode, path, packageConfig, resultsByExtension),
packageConfig, null);
results.put(resultCode, result);
}
}
}
..................................
分享到:
相关推荐
struts2-convention-plugin-2.3.24.1
struts2-convention-plugin-2.3.15.1.jar
struts2-convention-plugin-2.1.6.jar
struts2-convention-plugin-2.3.1.jar,使用注解的方式代替xml配置action,必须要引用这个包。
struts2-convention-plugin-2.1.8.jar
struts2-convention-plugin-2.3.32
struts2-convention-plugin-2.3.1.2.jar
struts2-convention-plugin-2.3.24.jar
不论高低版本,要使用struts2-core这个jar包,当又需struts2-convention-plugin.jar时勿必要使两者版本一致哦,否则会有DefError、Unable to read class诸等错误
struts2-convention-plugin-2.3.15.3.jar struts2配置Action注解要用到的包,真正实现零配置
struts2-convention-plugin-2.3.4.1.jar
Struts开始使用convention-plugin代替codebehind-plugin来实现struts的零配置,使用Convention插件,你需要此JAR文件
struts2-convention-plugin-2.1.8.1.jar
在给定的文件"struts2-convention-plugin-2.3.32.jar"中,我们关注的是Struts2的Convention插件,版本号为2.3.32。这个插件是Struts2框架的一个重要组成部分,旨在提供更加灵活和自动化的配置方式。 Convention...
从struts2.1开始,struts2不再推荐使用Codebehind作为零配置插件,而是改为使用Convention插件来支持零配置,和Codebehind相比,Convention插件更彻底,该插件完全抛弃配置信息,不仅不需要是使用struts.xml文件进行...
在传统的Struts2配置中,开发者需要为每个Action编写XML配置文件,以指定Action类、结果页面和其他相关设置。然而,随着版本的更新,Struts2引入了一个名为Convention Plugin的新特性,旨在简化配置过程,实现所谓的...
一:升级高版本的struts2.5.22 无法访问Action解决办法 1.最主要原始struts版本与freemarker-2.3.22版本不一致...2.具体原因就研究struts2-core-2.3.32.jar 与 freemarker-2.3.22.jar 关系依赖 更新如下8个jar即可。