首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过Struts了解MVC框架,兼说如何在面试中利用Struts证明自己

通过Struts了解MVC框架,兼说如何在面试中利用Struts证明自己

作者头像
用户1153489
发布2018-01-12 16:46:17
6870
发布2018-01-12 16:46:17
举报

    虽然目前Struts MVC框架不怎么用了,但它确是个能帮助大家很好地入门Web MVC框架,而且,一些历史项目可能还用Struts,反正技多不压身,大家如果能在面试中通过项目证明自己Struts这块也很熟,这也是个非常好的加分项。

    这里我们就从搭建Struts基本框架入手,再深入讲解些面试中常会靠到的Struts知识点,本文的文字和案例根据java web轻量级开发面试教程改编。

///////////////////////////////////////////////////////////////////////////////////////

1 搭建Struts框架

1.1 开发前端的JSP代码

    创建一个Java Web项目,名为strutsDemo,在其中的WebRoot目录下,创建前端的JSP代码calSum.jsp。    

 1 1    <%@ page language="java" pageEncoding="GBK" %>
 2 2    <%@ taglib prefix="s" uri="/struts-tags"%>
 3 3    <html>
 4 4    <head>
 5 5    <title>输入操作数</title>
 6 6    </head>
 7 7    <body>
 8 8    求和<br/>
 9 9    <s:form action="mystruts/calSum" >
10 10    <s:textfield name="num1" label="数1"/>
11 11    <s:textfield name="num2"  label="数2" />
12 12    <s:submit value="求和" />
13 13    </s:form>
14 14    </body>
15 15    </html>

    这个页面的效果下图所示。

    在第2行里引入了Struts的标签,前缀是s,所以可以用s:form和s:textfield来定义form和文本框。

    在第9行到第13行的form里,定义了两个输入框和一个提交按钮。当用户输入两个数字后,单击“求和”按钮后,本页面将根据定义在第9行的定义,跳转到mystruts/calSum.action。

1.2 在web.xml里声明使用Struts

    如果要使用基于Struts的MVC,则必须要在web.xml里声明,否则系统服务器是不会知道在项目里用到了基于Struts的MVC处理器。web.xml的代码如下。

1    <?xml version="1.0" encoding="UTF-8"?>
2    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
3    <filter>
4    <filter-name>struts2</filter-name>
5    <filter-class>
6            org.apache.struts2.dispatcher.FilterDispatcher            
7    </filter-class>
8    </filter>
9    <filter-mapping>
10    <filter-name>struts2</filter-name>
11    <url-pattern>/*</url-pattern>
12    </filter-mapping>
13    </web-app>

    从第2行到第13行之间的web-app元素里,我们声明了两件事:

    (1)通过第11行的url-pattern,说明/*,也就是任何请求,都将由名为struts2的过滤器来处理。

    (2)在第3行到第8行之间,指定了struts2这个过滤器它的后台处理类。

综合上述两点可知,本项目的任何请求,都将由Struts的后台处理类来处理。     

1.3 配置struts.xml文件 

    在calSum.jsp里指定了form跳转的目的地。

    <s:form action="mystruts/calSum" >

    那么这个目的地究竟是哪里?一起来看一下struts.xml这个配置文件。    

1    <?xml version="1.0" encoding="UTF-8" ?>
2    <!DOCTYPE struts PUBLIC
      "-//Apache Software Foundation//DTD Struts Configuration2.0//EN"
      "http://struts.apache.org/dtds/struts-2.0.dtd">
3    <struts>
4    <package name="struts2" namespace="/mystruts"
5       extends="struts-default">
6    <action name="calSum" class="action.myAction">
7    <result name="Positive">/positive.jsp</result>
8    <result name="Negative">/negative.jsp</result>
9    </action>
10    </package>
11    </struts>   

    在第4和第5行里,能看到名为calSum的action处于/mystruts这个命名空间里,它所对应的是action.myAction这个处理类。也就是说,calSum.jsp的请求最终是由action.myAction接收和处理。

1.4 开发Action类

     随后开发myAction.java,它是放在action这个package下的。    

1	package action;
2	import com.opensymphony.xwork2.ActionSupport;
3	public class myAction extends ActionSupport
4	{
5	    private int num1;
6	    private int num2;
7	
8	    public String execute() throws Exception
9	    {
10		// 如果和大于等于0,则跳到positive.jsp页面
11		if (getSum() >= 0)  
12	        {
13	            return "Positive";
14	        }
15		//否则跳到negative.jsp页面
16	        else  
17	        {
18	            return "Negative";
19	        }
20	    }   
21	    public int getNum1() {
22			return num1;
23		}
24		public void setNum1(int num1) {
25			this.num1 = num1;
26		}
27		public int getNum2() {
28			return num2;
29		}
30		public void setNum2(int num2) {
31			this.num2 = num2;
32		}
33		public int getSum()
34	    {
35	        return num1 + num2;  // 计算两个整数的代码数和
36	    }
37	}

    作为一个Struts的Action,本类继承了ActionSupport类。当一个请求最终到达本Action时,如果没有额外的配置,就会如同本类一样,由execute方法来处理请求。

    在第8行的execute方法里可能看到,如果两个数的和大于0,则返回Positive字符串,反之则返回Negative。这两个返回是和struts.xml里的配置相对应的。

    在struts.xml的第6行和第7行里,看到有如下的配置。

    <result name="Positive">/positive.jsp</result>

    <result name="Negative">/negative.jsp</result>

    这说明根据不同的字符串,Struts处理容器将会跳转到两个不同的jsp里。在这个Action代码里,并没有给num1和num2赋值,这是因为它们和calSum.jsp里form中的两个输入框同名,所以会自动拿到我们输入的值。

1.5 开发两个跳转结果页面

    上文提到过,Action的execute方法里返回的不同字符串后,Struts MVC处理器会读取struts.xml里的配置,并相应地,跳转到不同的页面。下面就来编写这两个页面的代码。先来看一下positive.jsp。   

1	<%@ page language="java" pageEncoding="GBK"%>
2	<%@ taglib prefix="s" uri="/struts-tags" %>
3	<html>
4	<head>
5	<title>显示和</title>
6	</head>
7	<body>
8	结果大于或等于0,<h1><s:property value="sum" /></h1>
9	</body>
10	</html>

     这里的关键代码是在第8行,通过一个Struts的标签,来获取在Action里名为”sum”的属性对象。在myAction.java里,定义了一个getSum的方法,所以就会自动生成一个sum的属性。结果是两个操作数之和。

    Negative.jsp代码和positive.jsp很相似。唯一的差别在第8行,这里的叙述文字是“结果小于0”。   

1	<%@ page language="java" pageEncoding="GBK"%>
2	<%@ taglib prefix="s" uri="/struts-tags" %>
3	<html>
4	<head>
5	<title>显示和</title>
6	</head>
7	<body>
8	结果小于0,<h1><s:property value="sum" /></h1>
9	</body>
10	</html>

2 通过运行,了解Struts的工作流程

   现在来总结一下整个程序的运行和跳转流程。

    第一,打开Tomcat服务器,并在浏览器里输入http://localhost:8080/strutsDemo/calSum.jsp,能看到如下图所示的页面

    当输入两个数字,并单击“求和”按钮后,根据如下form里的定义,会跳转到mystruts/calSum里。

    <s:form action="mystruts/calSum" >    

    第二,根据web.xml的定义,可知这个跳转请求将由struts来处理。再根据struts.xml的定义,得知这个请求最终将由myAction.java来处理。

    <action name="calSum" class="action.myAction">

        <result name="Positive">/positive.jsp</result>

       <result name="Negative">/negative.jsp</result>

    </action>

    第三,在myAction.java的execute方法里,根据最终sum的值,分别返回两个不同的字符串,从上文struts.xml片段的第3行和第4行得知,根据两个不同的返回值,会跳转到两个不同的页面里。

3 和JSP+Servlet+JavaBean框架的比较

    在一个项目里,我们应更关注“业务该怎么处理”这个问题,而不应把大多数精力放在调试JSP到Servlet之类的跳转上。

    Struts给我们提供了一套跳转机制,我们可以简单地通过编写struts.xml和web.xml,就能比较省心地实现从前端JSP跳转到具体业务处理类的功能。而且,也只需在Action类里编写返回字符串,同时在struts.xml里编写返回字符串和跳转页面的对应关系,就能根据业务执行结果方便地跳转回前端页面。

    Struts框架是基于MVC的,它的View部分主要由JSP页面实现。Controler部分主要由Action类来承担,而Model部分主要由ActionForm组成。需要说明的是,在Struts2.0以上的版本里,开发者不需要额外定义ActionForm,由用户在前端Form里传入的数据将被自动封装成ActionFrom对象,并被最终转发给Action。

    通过下表对比一下Struts和前文提到的JSP+Servlet+JavaBean框架,综合各项对比的指标,Struts略优于JSP+Servlet+JavaBean框架。

比较项

Struts

JSP+Servlet+JavaBean

结论

如何在后端接收前端传来的参数

参数组装成ActionForm,并自动发送到Action里

需要在Servlet里编写接收参数的代码

Struts比较省心

如何把前端的请求发送到合适的处理页面

可以在struts.xml里统一定义请求和处理类的对应关系

可以在web.xml里统一定义请求和处理类的对应关系

基本持平

后端处理请求的方式

定义在Action里

大多定义在Servlet类的doPost或doGet方法里

基本持平

如何把后端的处理结果再回传到前端

可以在struts.xml里统一地定义处理结果和返回页面的对应关系

需要在Servlet里手动地跳转

Struts略优

项目的开发方式

程序员的工作量比较少,在必要的地方(比如Action类和Struts.xml)里填写必要的代码即可,Struts处理器能方便地实现MVC之间的跳转

程序员可能得操心必要的细节,比如Servlet里如何接收参数,如何跳转到前端,等等

Struts的开发流程比较省心

4 对Struts框架的进一步了解

    Struts作为一个基于MVC的框架,能很好地处理跳转业务,能让程序员把精力更多地集中到业务开发上,通过它,程序员能很好地了解框架编程的思路和一般方法。

    不过任何框架都不是十全十美的,当你比较熟悉Struts框架后,一定能感受到它在项目开发里的一些缺陷。对于Struts的局限性,不同的人有不同的观点。但是请大家记住,在面试时,当你结合你的项目自信地说出Struts框架的局限时,即使面试官和你的观点不一致,他也一定会认为你对Struts有足够的认识。这里罗列出一些局限性供大家参考,如表所示。

局限性

结合项目说明

为每个请求创建一个Action

Struts2里,会为每个http请求实例化一个Action 对象,这对处理高并发会有些难度

对Action 执行前和后的处理支持不大好

比如每次进到Action前我们需要打印内存使用量,执行后需要记录跳转目标URL,这个当然可以直接写到Action里,但大家比较下Spring的AOP处理方式,就会发现单纯把前后处理写到Action里有什么不足

对跳转的支持

如果在一个Action里,根据处理结果可能会跳转到10个页面,那么代码可能会比较烦琐。而且一旦跳转目标页面出现变更,比如换了目录,那么在修改配置文件后,可能要求重新部署和重启Web服务器,无法实现轻量级修改

安全性上的瑕疵

我们可以通过类似方式直接执行Action里的方法:http://url:8080/proName/userLogin!list 但事实上,该系统需要用户先登录才能开放用户列表。虽然我们可以通过定义拦截器来弥补这个缺陷,但毕竟属于额外的工作量

属于侵入式

在使用Struts时,需要继承struts的类,而且要编写execute方法。这样Struts框架就侵入到项目里了。比如做的是银行业务,如果哪天要把这套业务移植到其他Spring等框架项目里,可能工作量就比较大了

5 关于Struts面试点的归纳

   Struts的地位似乎有些尴尬,一些小型(比如10个页面左右)的商业项目可能直接会用JSP+Servlet+JavaBean+DB的开发模式,一些大型基于企业级的项目往往采用Spring+MyBatis的框架。

    我们在面试初级程序员时,如果候选人没有在商业项目里用过Struts框架,这很正常,如果他在学校或者培训机构学过Struts,这或许也可以成为一个加分项。但如果我们看到某人在最近的商业项目里用过,那么就会详细问原因,为什么这个公司现在还要用Struts框架?反而有不少人,在这个问题上会弄巧成拙。我们听到的最多的合理回答是,基于某种原因,比如历史原因或者客户要求,这个项目还是得用Struts框架。

    具体到面试题,大家可以从网上找,在必要的时候,大家也可以多多益善地突击准备。我们给大家推荐回答问题的方式是“结合项目”,请大家看如下的问题点。

    第一,说明在这个项目里,都用到了Struts的哪些组件,比如拦截器或者验证器,你是怎么用的?

    第二,结合项目,说明自己做了哪些工作,比如在Action里,你怎么和业务以及数据库代码耦合?

    第三,能结合项目,告诉考官一些技术细节,比如拦截器是怎么用的,在该项目里结合一个需求,告诉考官拦截器的工作流程和开发方式。或者结合项目说明下验证器的用法。

    也就是说,任何技术都别停留在纸上,需要结合项目说明。

    第四,说明使用Struts框架给这个项目带来哪些痛点?

    第五,和Spring框架相比,你感觉各自有什么优缺点,请结合项目说明,不要空谈。

    当你学好了Spring框架后就知道该怎么说?

    第六,你的项目经常会扩展,业务实现方式也经常会变更,结合Struts框架说明一旦出现变更了你需要做哪些事?

    比如需要更改业务,你该更改哪些文件?一旦更改了代码,如何部署到服务器上?

    第七,这个项目的访问量是多少?最高的并发访问量能达到多少?Struts框架能否很好地处理高并发的情况?

    关于常用的技术问题,在本章里都已经提到,我们通过如下问题点来对本章做个总结。

    ①在Struts2里,如何实现一个Action?

    ②怎么指定进入Action后该调用哪个方法?

    ③定义验证器的步骤是什么?

    ④定义拦截器的步骤是什么?

    ⑤Struts2中的type类型有哪些?如果不写type,默认是什么?

    ⑥如何通过配置type类型,实现一个Action往另外一个Action的跳转?

    ⑦描述下Struts MVC的工作流程和开发模式。

    ⑧和JSP+Servlet+JavaBean的开发模式相比,Struts MVC有哪些好处,同时,说明下Struts框架有哪些不足。     

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 搭建Struts框架
    • 1.1 开发前端的JSP代码
      • 1.2 在web.xml里声明使用Struts
        • 1.3 配置struts.xml文件 
          • 1.4 开发Action类
            • 1.5 开发两个跳转结果页面
            • 2 通过运行,了解Struts的工作流程
            • 3 和JSP+Servlet+JavaBean框架的比较
            • 4 对Struts框架的进一步了解
            • 5 关于Struts面试点的归纳
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档