SSH-理解struts1架构

看两个JSP模型

一、Model1模型   

                                    

    这是model1模型,用户在浏览器端输入,发送请求,JSP页面收集用户输入的数据,并通过调用JavaBean操作(增、删、改、查)数据库。将操作数据库的结果返回给JSP页面,JSP页面接收返回的数据,在页面上显示给用户。

Model1模型分析:

优点:这样的结构简单,JSP页面接收了用户的请求,并调用了操作数据库的类,又收集了操作数据库的类返回的结果,显示在JSP页面上。这些,都是JSP页面完成的。

缺点:JSP页面既将显示逻辑和业务逻辑放到了一起,页面上嵌入了验证和控制流转以及大量的java代码,jsp页面需要做的工作量很大,页面也很乱。


二、Model2模型

                                   

 

这是Model2模型,用户在浏览器输入,发送请求,Servlet创建resquest收集用户在JSP页面上输入的信息,经过处理,通过调用JavaBeans操作(增、删、改、查)数据库,实现逻辑处理。最后Servelt得到操作数据库的结果信息,调用返回的JSP页面,将数据呈现给用户。

 

Model2模型分析:

优点:与Model1结构相比,Model1是将页面逻辑和业务逻辑都放在了JSP页面上,Model2是将二者分开。页面逻辑放在JSP页面上,业务逻辑放在了Servlet类中,页面逻辑和业务逻辑分开了,各部分的职责和明确。调理很清晰,益于扩展。

缺点:添加了新类,结构比Model1复杂。


两种模型比较:

Model1Model2都完成了用户请求,Model1结构虽简单,JSP页面兼并了页面逻辑和业务逻辑的功能,分工并不明确,适合小型项目开发。相比之下,Model2将页面逻辑和业务逻辑分开,分别放在了JSP页面和Servlet类中,虽然复杂了些,但是分工明确,逻辑很清晰,适合大型项目开发。

 

三、struts1模型

有了Model2这种MVC的结构,来了解struts1结构,就很容易了解了。

                                                                                                                                                                  

                                    

         通过MVC设计模式来分析Struts1的结构,如上图:Mode(M)l业务逻辑处理,View(V)视图,ActionServlet(C)即中央控制器Controller。用户在浏览器端输入,发送请求。中央控制器ActionServlet收集用户请求,并访问对应的Action,Action处理用户请求,调用Model操作数据库,Action得到操作数据库的结果信息,并指定要访问的JSP页面。通过JSP页面显示给用户。


四、详细对比Model2和Struts1的对比

通过上面的分析,从宏观上了解了Modle2和Struts1的结构设计,好像看不出Struts1和Model2相比,struts1的优势在哪里。下面通过详细的调用流程来分析。


Model2:用户发送请求,Servlet收集用户的请求信息,放到request中,读取web.xml中的配置信息。

web.xml配置文件:

<servlet>
  	<servlet-name>TestServlet</servlet-name>
  	<servlet-class>com.powernode.servlet.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>TestServlet</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

根据<Servlet>配置信息,找到Servlet类(TestServlet)。在TestSevlet中根据用户请求的地址,调用相应的Action。

public class TestServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 截取用户请求的地址
		String userURI = request.getRequestURI();
		System.out.println("requestURI=" + userURI);
		
		String path = userURI.substring(userURI.indexOf("/",1),userURI.indexOf("."));
		System.out.println("path=" + path);
		
		//固定的请求地址和截取到的请求地址,比较,调用Action对象
		Action action = null;
		if("/servlet/addUser".equals(path)){
			action = new AddUserAction();
		}else if("/servlet/delUser".equals(path)){
			action = new DelUserAction();
		}else if("/servlet/modifyUser".equals(path)){
			action = new ModifyUserAction();
		}else if("/servlet/queryUser".equals(path)){
			action = new QueryUserAction();
		}else{
			throw new RuntimeException("请求失败!");
		};
		String forward = null;
		try{                                                                                                                                                              //在action中业务处理,操作数据库的结果放到request,并返回要访问的JSP页面地址
			forward = action.execute(request, response);
		}catch(Exception e){
			e.printStackTrace();
		}
	       //转发到要访问的JSP页面                                                                                                                                   request.getRequestDispatcher(forward).forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request,response);
	}
	
}

看了上面的代码片段和注释,就知道了在action中调用了Model,进行业务处理,操作数据得到结果以及要访问的JSP页面。


在Servlet中,我们可以看到两个缺点:1.多个IF..ELSE..分支判断。if...else..很不稳定,如果要进行扩展,就需要修改这里的代码,违反了对修改关闭,对扩展开放的原则。

2.分支判断中,比较用户访问的请求地址时,是固定的字符串。如果要修改,也还得修改这里的代码。


Struts1结构:

用户在浏览器端发送请求,ActionServlet收集用户请求,读取struts-config.xml配置文件。

struts-config.xml配置文件:

<struts-config>
	<form-beans>
		<form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"></form-bean>
	</form-beans>
	<action-mappings>
		<action path="/login"
				type="com.bjpowernode.struts.LoginAction"
				name="loginForm"
				scope="request"
				>
			<forward name="success" path="/login_success.jsp"></forward>
			<forward name="error" path="/login_error.jsp"></forward>
		</action>
	</action-mappings>
  
</struts-config>
ActionServlet通过比较用户请求地址和配置文件中的<action>中的path属性。调用相应的Action。因为在配置文件<action-mapping>中配置好了path和Action的对应。有了用户的请求地址,就能找到要调用的Action。


public class LoginAction extends Action {

	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		LoginActionForm laf = (LoginActionForm)form;
		String username = laf.getUsername();
		String password = laf.getPassword();
		
		UserManager userManager = new UserManager();
		try{
			//调用相应的业务逻辑处理类
			userManager.login(username, password);
			
			//跳转到登录成功页面
			return mapping.findForward("success");
			
			//用自己封装的异常类捕获异常——用户不能找到
		}catch(UserNotFoundException e){
			e.printStackTrace();
			//将错误信息存放到request中
			request.setAttribute("msg", "用户不能找到,用户名称=【" + username +"】");
			
			//用自己封装的异常类捕获异常——密码错误
		}catch(PasswordErrorException e){
			//将错误信息放到request中
			request.setAttribute("msg", "密码错误!");
		}
		
		//跳转到错误页面
		return mapping.findForward("error");
	}

}
Action中调用Model,进行业务处理,操作数据库,得到操作结果。以及返回要访问的JSP页面。在配置文件中,通过<forward>标签页定义了要跳转的JSP页面。


对比Model2,Struts1里边,没有了If。。else。。判断语句,配置文件解决了这个问题,通过配置文件,将请求地址和要调用的Action匹配好了。通过这样的绑定,有了请求地址,就找到了要访问的Action。(其实是ActionServlet操作了这个跳转的过程ActionServlet读取配置文件,将<action-mapping>中的信息放到map中,以键值对的形式存在。ActionServlet分析截取用户的请求地址,得到key,通过这个key从map中拿到value.即要跳转到的action)。


再看刚才Model2中分析的两个缺点,f。。else。。判断语句的问题就这样被解决掉了。那第二个问题,分支判断中都是用的固定的字符串比较的。这个在struts1中是通过模糊匹配的方式解决的。可以参看http://blog.csdn.net/xujiaolf/article/details/43968399。这篇博客了说明了Struts1中的模糊匹配。


以上就是Model1,Model2和Struts1的对比,每一次的演变都带来巨大的便利。都是智慧的结晶啊,前人怎么就这么聪明呢?!


发布了106 篇原创文章 · 获赞 78 · 访问量 29万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章