随着struts2的不断升级,Struts开始使用convention-plugin代替codebehind-plugin来实现struts的零配置。所谓的零配置并不是任何配置都不需要,而是采用约定大于配置的方式。
在web开发过程中,根据convention-plugin的默认约定,我们不再需要在Struts.xml中配置任何信息。
首先,让我们先来看一下基于convention-plugin实现的Struts"零配置"登录。
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- <package name="default" namespace="/" extends="struts-default" />
- </struts>
package com.redhamr.web.member.actions;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionContext;
import com.redhamr.comp.member.MemberHandler;
import com.redhamr.persistent.model.Member;
import com.redhamr.web.member.GlobalConstant;
/**
* 商户信息管理
*
* @author zonto
*/
@Scope("prototype")
@Controller("loginact")
@ParentPackage("index")
public class LoginAct extends BasePageAct{
private static final long serialVersionUID = 1L;
@Autowired MemberHandler memberhandler;
private Member member;
private String msg;
private String gopath=SUCCESS;
private String referrer;//推荐人
/**
* 会员登录
* @return
*/
@Action(value = "memberlogin",results = {
@Result(name = "success",type="chain",location="memlist"),
@Result(name = "input",location="/login.jsp")})
public String merchOperLogin(){
if(member==null){
this.setMsg("请输入您的帐号和登陆密码!");
return INPUT;
}
try {
member=memberhandler.memLogin(member.getUsername(),member.getPassword());
if(member==null){
this.setMsg("帐号和登陆密码错误!");
return INPUT;
}
} catch (Exception e) {
this.setMsg("帐号和登陆密码错误!");
return INPUT;
}
ActionContext.getContext().getSession().put(GlobalConstant.SESSION_MEMBER,member);
this.setMsg("登陆成功!");
return this.getGopath();
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<s:property value="msg" escape="false"/>
<s:form action="memberlogin">
用户名:<s:textfield name="member.username"/>
密 码:<s:password name="member.password"/>
<s:submit/>
</s:form>
之所以在login中不需要任何配置,是因为struts2-convention-plugin进行了以下一系列的约定。
-
Action location by package naming conventionscom.example. action.Main Actioncom.example. actions.products.Display (implements com.opensymphony.xwork2.Action)com.example. struts.company.details.ShowCompanyDetailsActioncom.example. struts2.company.details.ShowCompanyDetailsAction
- <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
Convention plugin在上述的包及其子包中查找后缀为Action、或者实现了com.opensymphony.xwork2.Action的类。你可以通过设置
struts.convention.action.suffix属性来修改这个配置。Convention plugin默认的配置如下:
- <constant name="struts.convention.action.suffix" value="Action"/>
- Result (JSP, FreeMarker, etc) location by naming conventions
当在浏览器中输入http://localhost:8080/redhamr_web_member/login.jsp访问时,页面会跳转到WEB-INF/content/login.jsp。
默认情况下, Convention plugin假设所有的results存放在WEB-INF/content/下。可以通过设置struts.convention.result.path进行修改。Convention plugin默认的配置如下:
- <constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
Convention plugin即使在找不到对应的action的情况下,也可以通过Action的URL(这里是/hello-world)找到对应的结果(/hello-world.jsp)。
- Class name to URL naming convention
com.example.actions.products.Display -> /products/display
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details/show-company-details
以com.example.struts.company.details.ShowCompanyDetailsAction对应的Action URL为例,Convention plugin会将com.example.struts.company.details.ShowCompanyDetailsAction 的struts后的子包转换成命名空间“/company/details/”,然后ShowCompanyDetailsAction中的“Action”后缀去掉,并将驼峰式的命名大写变小写,并在之间加上“-”(当然“-”也是Convention plugin默认的)最终形成/company/details/show-company-details。这就是类名和Action URL之间的“约定”。
- Package name to namespace convention
com.example.actions.products.Display -> /products
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details
Convention plugin默认将actions、action、struts、struts2作为root Package,那么com.example.actions.MainAction的命名空间即为“/”,而com.example.actions.products.Display的命名空间为“/products”。
正是有了这些“约定”才使得我们的LOGIN能够实现零配置。
实际的开发过程中如果只这些约定,也许不能完全满足实际项目的需要。幸运的是Convention Plugin的配置是相当灵活的。