一、struts运行原理
ActionServlet: 总控制器,只需配置,不需编写。(在web.xml中配置struts-config.xml的位置信息,以及对哪些请求进行处理等)
表单(form): 总控制器在处理请求时,会查询struts-config.xml,将用户提交的数据填充到对应的表单中去,表单实际上是一个javaBean,用户提交哪些数据,它都有应该有对应的成员属性去存储(通过set和get方法)
Action: 用来处理请求,在struts-config.xml中有表单和Action的对应关系
struts-config.xml: 记录表单和Action的详细信息,以及它们之间的对应关系
1.浏览器(含登录表单<form action=”xxx.do”>)发出http登录请求。
2.解析主机名(查询hosts和DNS获得主机对应ip)
3.开始连接web服务器
4.通过http协议发送request请求(GET/myWeb/ABC)到web服务器上。
5.web服务器查询web.xml之后将请求转发给ActionServlet(web.xml中配置了让ActionServlet处理xxx.do的请求)
6.ActionServlet查询struts-config.xml把用户提交的数据填充到对应表单(ActionForm)中。
7.ActionServlet查询struts-config.xml调用指定的action,action从对应的ActionForm获取数据。
8.action调用处理函数,并将执行结果返回给ActionServlet(总控制器),ActionServlet查询struts-config.xml,根据不同的结果,跳转到不同的界面。
9.返回静态页面给web服务器,web服务器以http回应的形式返回给浏览器。
二、入门案例
1.创建web项目StrutsLogin,并引入struts开发包
2.在WEB-INF下编写login.jsp(jsp里用户表单含Name和password),并将首页面设为自动跳转到login.jsp(jsp:forward)
<form action="login.do" method="post"> u:<input type="text" name="name"><br/> p:<input type="password" name="password"><br/> <input type="submit" value="提交"> </form>
3.在包com.forms下编写UserForm.java(继承ActionForm)、login.jsp中form里的name需对应ActionForm里属性的set和get方法、本质上是一个javaBean
package com.forms; import org.apache.struts.action.ActionForm; public class UserForm extends ActionForm { private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
4.在包com.actions下编写LoginAction.java(继承自Action)、并重写其中的execute方法(这个方法是用来处理业务逻辑,会被自动调用)。
package com.actions; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import com.forms.UserForm; public class LoginAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub UserForm userForm=(UserForm)form; if(userForm.getName().equals("1")&&userForm.getPassword().equals("1")){ return mapping.findForward("ok"); } else{ return mapping.findForward("err"); } } }
5.在WEB-INF下编写struts-config.xml文件,该文件用于配置action、actionForm的对应关系,以及跳转的配置。
<struts-config> <!-- 配置表单 --> <form-beans> <!-- name是表单名字,可以随便写,一般ActionForm名小写 --> <form-bean name="userForm" type="com.forms.UserForm"></form-bean> </form-beans> <!-- 配置action --> <action-mappings> <!-- path表示将来访问该action的资源名,可以随意取,/login就表示它是代表为login.do的action
--> <!-- attribute表示后面scope设置的key值,默认就是表单名小写--> <!-- name与表单name相同,即将action与Actionform关联 --> <!-- attribute="userForm" scope="request"相当于request.setAttribute("userForm",userForm) --> <!--attribute="userForm" scope="session"相当于session.setAttribute("userForm",userForm) --> <action path="/login" attribute="userForm" name="userForm" scope="request" type="com.actions.LoginAction"> <!-- 这里配置跳转关系,action处理之后会返回一个结果,如果返回ok,就跳转到ok.jsp,如果返回err就跳转到err.jsp --> <forward name="ok" path="/WEB-INF/ok.jsp"></forward> <forward name="err" path="/WEB-INF/err.jsp"></forward> </action> </action-mappings> </struts-config>
6.在WEB-INF下新建ok.jsp和err.jsp,并编写一些内容以标识LoginAction的处理结果
7.在web.xml下配置ActionServlet(servlet的配置),并使能够读取到struts-config.xml。
<servlet> <!-- 配置actionServlet --> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <!-- 配置struts-config.xml --> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <!-- 让jsp发出的.do请求经过actionServlet--> <url-pattern>*.do</url-pattern> </servlet-mapping>
7.浏览http://localhost:8080/StrutsLogin,如果输入用户名和密码都为1,则跳到ok.jsp,否则跳转到err.jsp
三、运行思路
1.用户在login.jsp提交了用户名和密码(name和password),提交给login.do。
2.连接到web服务器之后,web.xml查询到相应的servlet去处理它。我们配置的ActionServlet又是处理*.do的,所以交给ActionServlet处理。
3.通过web.xml的配置找到ActionServlet类的路径。
4.找到ActionServlet,发现ActionServlet的处理方法是根据找到web.xml下的param-name为config的文件进行处理,找得是名为struts-config.xml且在WEB-INF目录下。找到后,ActionServlet便会一直使用此找得的文件,直到下次找不到文件,才会重写寻找param-name为config的文件。
5.查询struts-config.xml知道,login.do的交给com.actions.LoginAction处理,而且对应表单是userForm,再根据struts-config.xml的配置找到userForm的路径是com.forms.UserForm。
6.填充数据,找到userForm调用userForm里的setName和setPassword,将用户提交的数据填入。
7.找到LoginAction,执行里面的处理方法--execute,此时的userForm已经作为参数传入了,此时在execute里执行相应处理,处理完返回对应的ActionForward(给ActionServlet)。
8.ActionServlet再查询到LoginAction的配置,根据不同的ActionForward决定跳转到哪个页面。
四、乱码处理。
我们在loginAction中处理乱码是没有效果的,因为在调用loginAction之前,用户数据已经被填充到userForm中了。
所以在struts中处理乱码必须使用过滤器。我们在web服务器和ActionServlet之间加入过滤器。
我们在com.myz.filters下创建一个servlet并实现javax.servlet.Filter接口。
实现dofilter方法:
arg0.setCharacterEncoding("utf-8");//设置接收编码 arg1.setCharacterEncoding("utf-8");//设置回应编码 arg2.doFilter(arg0, arg1);//必须写这句话,否则过滤后将不会往下走
配置filter:
<filter> <filter-name>MyFilter1</filter-name> <filter-class>com.myz.filters.MyFilter1</filter-class> </filter> <filter-mapping> <filter-name>MyFilter1</filter-name> <!-- 表示针对所有的都过滤 --> <url-pattern>/*</url-pattern> </filter-mapping>
五、struts的好处和坏处
程序更加规范化
程序开发的效率提高了
程序的可读性增加
程序的可维护性增加了
Form表单有点鸡肋
Action是单态(对网站并发性的处理有影响)
(单态:在整个程序的运行过程中,始终是一个对象)
六、注意
1.Struts-config.xml的位置可以随意,但是需要在web.xml下重新配置。
2.一个项目中可以有多个struts配置文件,在web.xml配置时用逗号隔开即可。
3.增加数据库验证:
com.myz.domain下创建User类,该类是javaBean,主要是方便UserDao的传参等。
其实不创建该类,使用UserForm也是可以的
com.myz.service下创建DBDAO和UserDAO,DBDAO用于连接数据库,UserDAO用于操作数据库(如loginCheck)。
在loginAction中根据传入UserForm的数据调用loginCheck方法,进行验证。