Struts的模型结构
MVC设计模型
视图:就是JSP文件和ActionForm Bean(java bean)文件 主要为画面显示提供支持
控制器:就是Struts用来控制应用程序流程的核心组件,它主要的作用就是指向并执行相应的Action代码,完成逻辑处理
模型:就是应用程序的状态和业务逻辑.
Struts的工作流程
1. 初始化从struts-config.Xml文件中读取配置信息
2. 检索和用户请求相匹配的ActionMapping实例,如果不存在,就返回用户请求路径无效的信息。
3. 如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据存到ActionForm对象中.
4. 判断是否验证,需要验证的话调用ActionForm的validate()方法.
5. 如果validate方法返回的是NULL就说明验证成功
6. 通过xml文件中的映射把请求转发发送到指定的Action,调用此Action的Execute()方法.
7. Execute方法返回的对象把客户端请求转发给相对应的JSP文件.
8. JSP产生画面发送给客户
针对以上学习的流程,对项目登陆画面从新进行了流程分析
Struts 首先是读取两个XML文件,web和struts-config.根据这2个文件来装载和配置Web应用.
重点代码:
web.xml文件的配置
<servlet>
<servlet-name>action</servlet-name>//指定servlet的名称
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>//指定servlet的完整类名
//声明Servlet 初始化参数,指明了Struts的配置文件在什么位置
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>//用来指定ActionServlet可以处理哪些URL
//此处的名字必须和<servlet>里面的<servlet-name>一致
<servlet-name>action</servlet-name>
//此处/do/*表明如果用户请求的URL必须是以do为前缀的,还有一种为.do,他的意思为以do
//为后缀,只有符合这个要求的URL才会被ActionServlet处理
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
//指定访问WEB应用时自动调用的页面
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
其他标签
<error-page>
<error-code>400</error-code>
<location>/jsp/error/400BadRequest.jsp</location>
</error-page>
//用来对产生的错误指定显示的页面
struts-config.xml文件的配置
struts-config配置文件里面的标签和每一个类相对应
<action>和ActionMapping类对应 <forward>和ActionForward相对应 产生的对象用来保存运行时的信息
<form-beans>
<form-bean name="LoginForm"
type="jp.co.yamatake.ybs.buildingscope.presentation.login.LoginForm"/>
</form-beans>
//配置ActioForm bean 。name指定唯一标识,type指定完整类名
<global-exceptions>
<exception
key="Error.Unexpected"
handler="jp.co.yamatake.ybs.ybscom.framework.struts.BscExceptionHandler"
type="java.lang.Exception"
path="/WEB-INF/jsp/common/error/error.jsp"/>
</global-exceptions>
//配置异常处理key指定异常消息path异常产生时转向的路径type指定处理异常的类的名字
<global-forwards>
<forward name="welcome" path="/do/buildingscope/Welcome"/>
<forward name="logout" path="/do/buildingscope/Logout"/>
</global-forwards>
//声明全局的转发关系forwar用来把逻辑名映射到特定的URL
<action path="/buildingscope/Login"
name="LoginForm"
type="jp.co.yamatake.ybs.buildingscope.presentation.login.LoginAction"
scope="request"
input="/do/buildingscope/Welcome"
validate="true">
<forward name="success" path="/do/buildingscope/building/BuilList?method=view"/>
<forward name="failure" path="/do/buildingscope/Welcome"/>
</action>
//<action>描述了从特定的请求路径到相应的Action类的映射path访问Action路径type指定//Action的完整类名name指定了form-bean中的相关的名字forward对应的是return //mapping.findForward(target);
调用index.jsp文件
文件重点代码:
<logic:redirect forward="welcome"/>
此文件里面设置了一个转向,这样处理的原因是:由于在<welcome-file-list>属性中是不能配置Servlet映射,所以采用了变通的方法在struts-config.Xml中设置了全局转发,通过此页面的转发来调用指定的Action
1. <forward name="welcome" path="/do/buildingscope/Welcome"/>全局转发,因为前缀为do,所以执行相对应的Action
2.
<action path="/buildingscope/Welcome"
type="jp.co.yamatake.ybs.buildingscope.presentation.login.WelcomeAction">
<forward name="success" path="/WEB-INF/jsp/buildingscope/login/login.jsp"/>
</action>
此Action 指向jp.co.yamatake.ybs.buildingscope.presentation.login.WelcomeAction类
3. public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception
{
//设定target为success
String target = WebConstants.FORWARD_SUCCESS;
//调用此句执行
//<forward name="success" path="/WEB-INF/jsp/buildingscope/login/login.jsp"/>
// target为success就转向/WEB-INF/jsp/buildingscope/login/login.jsp
return mapping.findForward(target);
}
3. 调用/WEB-INF/jsp/buildingscope/login/login.jsp页面
里面<html:form action="/buildingscope/Login" focus="loginUser" method="post">表示点击确定提交按钮后调用/buildingscope/Login的Action
4. <action path="/buildingscope/Login"
name="LoginForm"
type="jp.co.yamatake.ybs.buildingscope.presentation.login.LoginAction"
scope="request"
input="/do/buildingscope/Welcome"
validate="true">
<forward name="success" path="/do/buildingscope/building/BuilList?method=view"/>
<forward name="failure" path="/do/buildingscope/Welcome"/>
</action>
此句首先调用了name为"LoginForm"的<form-beans>
5.执行<form-bean name="LoginForm"
type="jp.co.yamatake.ybs.buildingscope.presentation.login.LoginForm"/>
执行jp.co.yamatake.ybs.buildingscope.presentation.login.LoginForm类
6.通过这个类把页面上用户名和密码的输入筐的数据放入类中的私有变量中
private String _loginUser = "";
private String _password = "";
7.执行完成以后执行Action类jp.co.yamatake.ybs.buildingscope.presentation.login.LoginAction
LoginForm loginForm = (LoginForm) form;
创建一个Bean的对象获得从ActionForm传来的数据
LoginService loginService = LoginServiceFactory.getServiceInstance();
调用LoginServiceFactory类的静态方法getServiceInstance();
方法new 了LoginServiceImpl()对象,调用构造函数
_daoFactory = DataAccessFactory.getFactory("DaoFactory");
通过传入”DaoFactory”字符串,创建对象, getFactory方法执行了下面的语句
ConfigReader conf = PropertyConfigReader.getInstance();
String className = conf.getValue(implClassRef);
result = (DataAccessFactory) Class.forName(className).newInstance();
此处implClassRef="DaoFactory"
getValue(implClassRef)函数为
public String getValue(String key)//key为DaoFactory
{
String result =_properties.getProperty(key);
// result为jp.co.yamatake.ybs.buildingscope.daoimpl.bstype.facade.BsDataAccessFactory
if(result == null)
{
_log.error("KEY[" + key + "] is not found in " + RESOURCE_FILE);
}
return result;
}
Class.forName(className).newInstance();创建了
jp.co.yamatake.ybs.buildingscope.daoimpl.bstype.facade.BsDataAccessFactory类的实例
初始化
_buildingDAO = _daoFactory.createBuildingDAO();
new BuildingDAOImpl();
9. 结束上面的步骤之后回来继续调用了loginService.isUser()
isUser()函数调用的是LoginServiceImpl类的方法,这个方法是用来判断用户名和密码是否为空
其中还调用了_buildingDAO.getBuilCustomer(loginUser);
getBuilCustomer(loginUser)方法调用的是BuildingDAOImpl类的方法.
如果密码错误target设置为failure
之后调用
return mapping.findForward(target);发送请求
根据target的值执行相应的url地址
<forward name="success" path="/do/buildingscope/building/BuilList?method=view"/>
<forward name="failure" path="/do/buildingscope/Welcome"/>
success 进入下个页面 failure 返回原来页面