【SSH 基础】SSH框架--struts深入详解(一)

来源:互联网 发布:京东红菩提软件 编辑:程序博客网 时间:2024/06/05 01:56

 学习了struts,但是对于它的由来,以及为什么使用actionstruts.xml的方式而不采用以前的servlet方式,有些疑问,到底之前的方式有什么弊端,struts又给我们带来了什么便利?

下面一一为大家解答!

 

struts的由来:

 

随着JSP与Servlet 技术大量应用于以Web为基础的应用程序,为了提升Web 应用程序可维护性与重复使用性,Java开发人员提出了一些较佳的开发模式。比较常见的两种JSP应用架构分别为Model1 与Model 2。详情参见(JAVA学习篇--JAVA的两种编程模式对比)

 

简单回顾两种模型:

 

    Mode1 1是一个以JSP文件为中心的模式, JSP不仅负责表现逻辑,也负责控制逻辑。逻辑耦合在页面中,这种处理方式,对一些规模很小的项目是可以的,但是用在开发大型项目时,页面很难把握流向,界面间关联性太强,使得程序的修改与维护变得困难;此外程序逻辑与页面显示交叉,既不便于分工合作也不利于代码的重用,这样的程序其健壮性和可伸缩性都不好。


    Model 2Servlet扮演前端Controller角色,客户端的请求不再直接送给JSP,而是送给Servlet,再由Servlet根据具体的请求调用不同的事务逻辑,并将处理结果返回到合适的页面。最重要的是Model2将业务逻辑从JSP文件剥离,分离后,JSP文件单纯只是显示,这就是常说的View;而独立出来的事务逻辑和数据处理等是常说的Model,再加上控制器Control本身,即为MVC模式。

    MVC模式为大型程序的开发及维护提供了巨大的便利。但是Model2的优点也造成了他的缺点,因为解耦,分层,使得Model2的编写变得复杂,尤其是大型项目,Servlet过多,转向频繁,流程,配置等不易集中管理。

 

    所以基于以上这些原因,Struts将某些功能进行提取,然后做了一个封装,能让我们更好的使用。上面说的都太过笼统,也许大家还是很难想象。下面结合具体实例说明一下不使用struts的弊端!

 

具体示例分析(不使用struts

 

add.html

[html] view plaincopyprint?
  1. <HTML>  
  2. <BODY>  
  3.     <FORM ACTION="../addGrade" METHOD="POST">  
  4.         学号:<INPUT TYPE="TEXT" NAME="USERID" ><BR>  
  5.         姓名:<INPUT TYPE="TEXT" NAME="USERNAME" ><BR>  
  6.         语文:<INPUT TYPE="TEXT" NAME="CHINESE" ><BR>  
  7.         数学:<INPUT TYPE="TEXT" NAME="MATHS" ><BR>  
  8.         英语:<INPUT TYPE="TEXT" NAME="ENGLISH" ><BR>  
  9.         <INPUT TYPE="SUBMIT" VALUE="保存">  
  10.         <INPUT TYPE="RESET" VALUE="取消">  
  11.     </FORM>  
  12. </BODY>  
  13. </HTML>  

配置文件

[html] view plaincopyprint?
  1. <servlet>  
  2.     <servlet-name>addgradeservlet</servlet-name>  
  3.     <servlet-class>servlet.addGradeServlet</servlet-class>  
  4. </servlet>  
  5. <servlet-mapping>  
  6.     <servlet-name>addgradeservlet</servlet-name>  
  7.     <url-pattern>/addGrade</url-pattern>  
  8. </servlet-mapping>  

addGradeServlet.java:对应的servlet

[java] view plaincopyprint?
  1. public class addGradeServlet extends HttpServlet{  
  2.       
  3.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  4.         String strUserId = request.getParameter("USERID");  
  5.         String strUserName = request.getParameter("USERNAME");  
  6.         String strChinese = request.getParameter("CHINESE");  
  7.         String strMaths = request.getParameter("MATHS");  
  8.         String strEnglish = request.getParameter("ENGLISH");  
  9.           
  10.         Grade grade=new Grade();  
  11.         grade.setUSERID(strUserId);  
  12.         grade.setUSERNAME(strUserName);  
  13.         grade.setCHINESE(strChinese);  
  14.         grade.setMATHS(strMaths);  
  15.         grade.setENGLISH(strEnglish);  
  16.           
  17.         gradeDao gradedao=new gradeDao();  
  18.         gradedao.insertGrade(grade);   
  19.           
  20.         ArrayList<Grade> gradeList=(ArrayList)gradedao.listGrade();  
  21.           
  22.         HttpSession session=request.getSession();  
  23.         ServletContext scx=session.getServletContext();  
  24.         scx.setAttribute("gradeList",gradeList);  
  25.         response.sendRedirect("javabean_test/show.jsp");  
  26.           
  27.     }  
  28.       
  29.     public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{  
  30.         this.doPost(request, response);  
  31.     }  

分析:此段代码完成的功能是得到学号,姓名,语文,数学,英语等信息,进行相应的操作,并转向相应的页面。


问题1:对于跳转页来说,就是项目中的页面名称,比如:show.jsp等等这些东西都写死了,比如想换一个页面,因为文件名都已经写死在了程序中,改动起来很麻烦,也不符合OCP原则。

而且对于上面的代码我们不难发现,每个方法的跳转代码几乎相同,只有跳转的具体页面有差别,那么我们就可以将那些不需要改动的内容抽取出来,做成框架,需要改动的部分拿出来,想要用什么配置一下就可以,比如想改jsp名,只需要配置一下就可以了。

 

问题2:就上面的添加功能来说,我们需要从前台获取多个参数,然后再一个一个的设置到对象中,不但增加了我们的代码量,还使我们的程序难于维护。代码如下:

[java] view plaincopyprint?
  1. String strUserId = request.getParameter("USERID");  
  2. String strUserName = request.getParameter("USERNAME");  
  3. String strChinese = request.getParameter("CHINESE");  
  4. String strMaths = request.getParameter("MATHS");  
  5. String strEnglish = request.getParameter("ENGLISH");  
  6.   
  7. Grade grade=new Grade();  
  8. grade.setUSERID(strUserId);  
  9. grade.setUSERNAME(strUserName);  
  10. grade.setCHINESE(strChinese);  
  11. grade.setMATHS(strMaths);  
  12. grade.setENGLISH(strEnglish);  

问题3:上面采用的是添加使用addServlet,那么删除,修改,查询呢,对于一个功能块来说,就最少需要4servlet来管理,那么这么多个servlet,增加了程序的负担,使我们不容易维护。而即使我们将一个功能块的所有servlet都统一管理,那么我们就又需要添加if判断语句,类似如下代码:

[java] view plaincopyprint?
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response)  
  2.         throws ServletException, IOException {  
  3.     if(Constants.SHOW_ADD.equals(getCommand())){  
  4.         showAdd(request,response);  
  5.     }else if(Constants.ADD.equals(getCommand())){  
  6.         add(request,response);  
  7.     }else if(Constants.DEL.equals(getCommand())){  
  8.         del(request,response);  
  9.     }else if(Constants.AUDIT.equals(getCommand())){  
  10.         audit(request,response);  
  11.     }else {  
  12.         //分页查询  
  13.         search(request,response);  
  14.     }  
  15. }  
  16.   
  17. /** 
  18.      * 删除 
  19.      * @param request 
  20.      * @param response 
  21.      * @throws ServletException 
  22.      * @throws IOException 
  23.      */  
  24.     private void del(HttpServletRequest request, HttpServletResponse response)  
  25.     throws ServletException, IOException {  
  26.         String[] flowCardVouNos=request.getParameterValues("selectFlag");  
  27.         flowCardManager.delFlowCard(flowCardVouNos);  
  28.         response.sendRedirect(request.getContextPath()+"/servlet/flowcard/FlowCardServlet");  
  29.     }  

    但是这样写又有什么弊端呢?因为if语句的不稳定性,为什么这么说呢?上面有了添加,删除,查询,送审的功能,那么现在我要添加修改的功能,我就需要修改代码--违反了OCP原则。所以它适应需求的能力就比较差。

 

    以上是针对struts能解决的问题,再反过来看我们不用struts时我们程序中会出现的问题进行陈述,当然struts不仅仅只解决了这些问题,上面所述只是为了帮助大家理解简单的举例,理解的不对还请大家指正!下篇博客将继续叙述struts是如何解决上述问题的及它的实现原理!


 补充:struts2执行流程

  

当Web容器收到 请求(HttpServletRequest)它将请求传递给一个标准的的过滤链包括
(ActionContextCleanUp)过滤器,然后经过Other filters(SiteMesh ,etc),接下来需要调用FilterDispatcher核心控制器,然后它调用ActionMapper确定请求哪个Action,ActionMapper返回一个收集Action详细信息的ActionMaping对象。
接下来FilterDispatcher将控制权委派给ActionProxy,ActionProxy调用配置管理器(ConfigurationManager) 从配置文件中读取配置信息(struts.xml),然后创建ActionInvocation对象,ActionInvocation在调用Action之前会依次的调用所用配置拦截器(Interceptor N) 一旦执行结果返回结果字符串ActionInvocation负责查找结果字符串对应的(Result)然后执行这个Result Result会调用一些模版(JSP)来呈现页面,之后拦截器(Interceptor N)会再被执行(顺序和Action执行之前相反)最后响应(HttpServletResponse)被返回在web.xml中配置的那些过滤器和(核心控制器)(FilterDispatcher)。

0 0