⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 详细分析三.txt

📁 开源论坛实现
💻 TXT
📖 第 1 页 / 共 4 页
字号:
                  <param name="excludeParams">dojo\..*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>
而自定义拦截器是要求拦截器是无状态的原因是Struts 2不能保证为每一个请求或者action创建一个实例,所以如果拦截器带有状态,会引发并发问题。所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。除此之外,大家可能更喜欢继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor。需实现其public String intercept(ActionInvocation invocation) throws Exception .
而下面的remoteAddrInterceptor:
	<interceptor name="remoteAddrInterceptor"
			class="com.laoer.bbscs.web.interceptor.RemoteAddrInterceptor">
			</interceptor>
我们进入web.interceptor层:
	public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext ac = invocation.getInvocationContext();
		Object action = invocation.getAction();
		HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);//得到request请求
		String userRemoteAddr = request.getRemoteAddr();
		if (action instanceof RemoteAddrAware) {  //action是RomoteAddrAware实例?

			((RemoteAddrAware)action).setRemoteAddr(userRemoteAddr);
			//System.out.println(userRemoteAddr);
		}

		return invocation.invoke();
	}
}
我们可以看到RemoteAddrAware是如下这个接口,这是为了方便将远程地址放入action中:
public interface RemoteAddrAware {
	public void setRemoteAddr(String remoteAddr);
}

接下来是userCookieInterceptor:
<interceptor name="userCookieInterceptor"				
class="com.laoer.bbscs.web.interceptor.UserCookieInterceptor">
			</interceptor>
public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext ac = invocation.getInvocationContext();
		Object action = invocation.getAction();

		if (action instanceof UserCookieAware) {
			HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST); //用于UserCookie
			HttpServletResponse response = (HttpServletResponse) ac.get(ServletActionContext.HTTP_RESPONSE);//用于UserCookie

			ServletContext servletContext = (ServletContext) ac.get(ServletActionContext.SERVLET_CONTEXT);
			WebApplicationContext wc = WebApplicationContextUtils.getWebApplicationContext(servletContext);//得到业务层服务!
			if (wc == null) {
				logger.error("ApplicationContext could not be found.");
			} else {
				SysConfig sysConfig = (SysConfig) wc.getBean("sysConfig");
				UserCookie userCookie = new UserCookie(request, response, sysConfig);   //关键点!!!!
				//logger.debug("userCookie sid:" + userCookie.getSid());
				((UserCookieAware) action).setUserCookie(userCookie);
			}
		}
		return invocation.invoke();
	}
而UserCookieAware:
public interface UserCookieAware {
	public void setUserCookie(UserCookie userCookie);
}
看最后一个interceptor:requestBasePathInterceptor
public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext ac = invocation.getInvocationContext();
		Object action = invocation.getAction();

		if (action instanceof RequestBasePathAware) {
			HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
			StringBuffer sb = new StringBuffer();
			sb.append(BBSCSUtil.getWebRealPath(request));//得到域名
/**
public static String getWebRealPath(HttpServletRequest request) {
		StringBuffer sb = new StringBuffer();
		sb.append("http://");
		sb.append(request.getServerName());
		if (request.getServerPort() != 80) {
			sb.append(":");
			sb.append(request.getServerPort());
		}
		return sb.toString(); //返回域名啊!
	} 
*/
			sb.append(request.getContextPath());//request相对路径
			sb.append("/");
			((RequestBasePathAware) action).setBasePath(sb.toString());//设置BasePath
		}

		return invocation.invoke();
	}
其中,RequestBasePathAware:
public interface RequestBasePathAware {
	public void setBasePath(String basePath);
}

我们回到public class Login extends BaseAction implements RequestBasePathAware, RemoteAddrAware, UserCookieAware, SessionAware,可见这个Login实现了我们的这些Aware..并且它继承了BaseAction,而BaseAction继承了ActionSupport,它有几个通用的方法:getAction,setAction,getAjax,setAjax,及page.total(本来私有的)的getter/setter方法,另外还有以下方法:
protected String executeMethod(String method) throws Exception { //子类用!
		Class[] c = null;
		Method m = this.getClass().getMethod(method, c);
		Object[] o = null;
		String result = (String) m.invoke(this, o);
		return result;
	}

	public int boolean2int(boolean value) {
		if (value) {
			return 1;
		} else {
			return 0;
		}
	}

	public boolean int2boolean(int value) {
		if (value == 0) {
			return false;
		} else {
			return true;
		}
	}
有点类似C++了!true-->1  value!=0--->true
我们进入正题Login:
首先它需要一个静态的logger:private static final Log logger = LogFactory.getLog(Login.class);
还有private static final long serivalVeserionUID...
当然,它需要get/set一下上面的basePath,remoteAddr,userCookie.另外还有一个session
作为struts,它有与表单交互的字段:actionUrl,tourl,passwd,username,hiddenLogin,authCode,urlRewrite,useAuthCode,cookieTime=-1等及其getter/setter方法...注意:
public boolean isUseAuthCode() {
		return useAuthCode;
	}
另外,我们可以看到其构造方法中:
	public Login() {
		this.setRadioYesNoListValues();//隐身选择是或否
		this.setCookieTimeListValues();//Cookie时间选择一年/一月/一天/浏览器进程 
	}
	private void setRadioYesNoListValues() { //private的注意哦!!
		radioYesNoList.add(new RadioInt(0, this.getText("bbscs.no")));//注意getText从资源文件BaseAction中获得字符串值!
		radioYesNoList.add(new RadioInt(1, this.getText("bbscs.yes")));
	}
	private void setCookieTimeListValues() {
		cookieTimeList.add(new RadioInt(365 * 24 * 3600, this.getText("login.cookietime0")));//一年以365计算
		cookieTimeList.add(new RadioInt(30 * 24 * 3600, this.getText("login.cookietime1")));
		cookieTimeList.add(new RadioInt(24 * 3600, this.getText("login.cookietime2")));
		cookieTimeList.add(new RadioInt(-1, this.getText("login.cookietime3")));
	}
我们来看RadioInt(com.laoer.bbscs.web.ui):它是一个简单的bean,封装了两个属性int的key和String类型的value,而公开其getter/setter方法,和下面的构造方法:
public RadioInt(int key, String value) {
		this.key = key;
		this.value = value;
	}
当然,也有其List<RadioInt> radioYesNoList = new ArrayList<RadioInt>();

	public List<RadioInt> getRadioYesNoList() {
		return radioYesNoList;
	}
	public void setRadioYesNoList(List<RadioInt> radioYesNoList) {
		this.radioYesNoList = radioYesNoList;
	}
也于提供给界面用.而private只能用于类的构造之中.对于一个action,它将调用业务层来处理数据,完成逻辑操作!这里用到了sysConfig,userService,loginErrorService,userOnlineService,在这个action类中提供get/set,由spring的applicationContext.xml注入!我们先看
<bean id="sysConfig"
		class="com.laoer.bbscs.service.config.SysConfig">
		<constructor-arg>
			<ref bean="configService" />
		</constructor-arg>
		<property name="isLoad">
			<value>${bbscs.isloadconfig}</value> //bbscs.isloadconfig=false
		</property>
	</bean>
而我们看<bean id="configService" parent="txProxyTemplate"> //其它如userService都类似哦!!
		<property name="target">
			<ref bean="configTarget" />
		</property>
	</bean>
而txProxyTemplate是一个事务处理的TransactionProxyFactoryBean:
<bean id="txProxyTemplate" abstract="true"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager">
			<ref bean="myTransactionManager" />
		</property>
		<property name="transactionAttributes"> //对于如下的内容进行事务
			<props>
				<prop key="create*">
					PROPAGATION_REQUIRED,-com.laoer.bbscs.exception.BbscsException
				</prop>
				<prop key="save*">
					PROPAGATION_REQUIRED,-com.laoer.bbscs.exception.BbscsException
				</prop>
				<prop key="remove*">
					PROPAGATION_REQUIRED,-com.laoer.bbscs.exception.BbscsException
				</prop>
				<prop key="update*">
					PROPAGATION_REQUIRED,-com.laoer.bbscs.exception.BbscsException
				</prop>
				<prop key="del*">
					PROPAGATION_REQUIRED,-com.laoer.bbscs.exception.BbscsException//出错,报BbscsException
				</prop>
				<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>//只读
			</props>
		</property>
	</bean>
-->
<bean id="myTransactionManager"  //事务管理器
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
-->
<bean id="sessionFactory"  //session工厂
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource">
			<ref local="dataSource" /> //dataSource!!数据源bean.
		</property>
		<property name="mappingResources">
			<list>
				<value>com/laoer/bbscs/bean/UserInfo.hbm.xml</value>
					........
				<value> com/laoer/bbscs/bean/Elite-{datasource.type}.hbm.xml
				</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					${hibernate.dialect}
				</prop>
				<prop key="hibernate.show_sql">
					${hibernate.show_sql}
				</prop>
				<prop key="hibernate.jdbc.fetch_size">
					${hibernate.jdbc.fetch_size}
				</prop>
				<prop key="hibernate.jdbc.batch_size">
					${hibernate.jdbc.batch_size}
				</prop>
			</props>
		</property>
	</bean>
OK!我们回到login.bbscs?action=check,这将getAction()-->check!首先它将执行execute方法:
public String execute() {
		this.setUrlRewrite(Constant.USE_URL_REWRITE); //public static boolean USE_URL_REWRITE = false;
		this.setUserAuthCodeValue();
		....
接下来,根据if (this.getAction().equalsIgnoreCase("index")) {...
}if (this.getAction().equalsIgnoreCase("admin")) {..
}if (this.getAction().equalsIgnoreCase("login")) {
			return this.login();
		}

		if (this.getAction().equalsIgnoreCase("check")) {
			return this.check();
		}
来进行流程的选择(这就是所为的逻辑吧)!
public String check() { //对cookie的检测!
		if (StringUtils.isNotBlank(this.getUserCookie().getUserName())
				&& StringUtils.isNotBlank(this.getUserCookie().getPasswd())) {
			return this.cookieLogin();//有cookie
		} else {
			return this.index();
		}
	}
--->
	public String index() {
		this.setAction("login");
		this.setHiddenLogin(0);
		if (Constant.USE_URL_REWRITE) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -