快速學(xué)習(xí)使用springmvc、strust2、strust1以及它們的對(duì)比
1、如何快速學(xué)習(xí)springmvc
首先,我們需要在復(fù)制spring相關(guān)的jar包到web-inf/lib里面去,然后在web.xml里面加入以下代碼,相當(dāng)于springmvc里面的servlet,這里只說(shuō)明了一些常見(jiàn)的用法,如果要了解springmvc里面的控制器這些詳細(xì)原理可以到網(wǎng)上再去找好詳細(xì)學(xué)習(xí)。
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
然后再在application.xml里面配置下面代碼,
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<!-- 自動(dòng)掃描的包名 -->
<context:component-scan base-package="com.shishuo.studio"></context:component-scan>
<mvc:annotation-driven />
<task:annotation-driven />
<tx:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<!-- 在XML配置文件中加入外部屬性文件,當(dāng)然也可以指定外部文件的編碼 -->
<bean id="propertyConfigurer" class="com.shishuo.studio.util.PropertyUtils">
<property name="locations">
<list>
<value>classpath:shishuo.studio.properties</value> <!-- 指定外部文件的編碼 -->
</list>
</property>
</bean>
<!-- FreeMarker的配置 -->
<bean id="freeMarkerConfigurer"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl" /><!--
指定路徑 -->
<property name="defaultEncoding" value="UTF-8" /><!-- 指定編碼格式 -->
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="defaultEncoding">UTF-8</prop>
<prop key="url_escaping_charset">UTF-8</prop>
<prop key="locale">zh_CN</prop>
<prop key="boolean_format">true,false</prop>
<prop key="time_format">HH:mm:ss</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="number_format">#.##</prop>
<prop key="whitespace_stripping">true</prop>
<prop key="classic_compatible">true</prop>
</props>
</property>
</bean>
<!-- 配置 FreeMarker視圖解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"></property>
<property name="cache" value="false" />
<property name="prefix" value="/" />
<property name="suffix" value=".ftl" /><!--可為空,方便實(shí)現(xiàn)自已的依據(jù)擴(kuò)展名來(lái)選擇視圖解釋類(lèi)的邏輯 -->
<property name="contentType" value="text/html;charset=utf-8" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeSpringMacroHelpers" value="true" />
</bean>
我們?cè)噲D模板用的是freemarker,所以后綴名是以.ftl結(jié)束,如果是用的jsp,那這個(gè)配置文件里面的
<property name="suffix" value=".ftl" />valeu改為.jsp
然后我再給出類(lèi)給大家看見(jiàn)
package com.shishuo.studio.action;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.shishuo.studio.constant.SystemConstant;
import com.shishuo.studio.entity.Category;
import com.shishuo.studio.entity.vo.CourseVo;
import com.shishuo.studio.entity.vo.PageVo;
import com.shishuo.studio.exception.CategoryNotFoundException;
import com.shishuo.studio.exception.notfound.StorageNotFoundException;
import com.shishuo.studio.service.CategoryService;
import com.shishuo.studio.service.UserService;
/**
* @author Herbert
*
*/
@Controller
@RequestMapping("/category")
public class CategoryAction extends BaseAction {
protected final Logger logger = Logger.getLogger(this.getClass());
@Autowired
protected CategoryService categoryService;
@Autowired
protected UserService userService;
/**
* 首頁(yè)
*
* @param modelMap
* @return
*/
@RequestMapping(value = "/{categoryId}.htm", method = RequestMethod.GET)
public String category(@PathVariable long categoryId, ModelMap modelMap,
@RequestParam(value = "p", defaultValue = "1") int p) {
try {
// 獲得數(shù)據(jù)
Category category = categoryService.getCategoryById(categoryId);
// 獲取當(dāng)前目錄下的所有課程
PageVo<CourseVo> coursePageVo = courseService
.getCoursePageByIdForUser(categoryId, p, 24);
// 增加屬性
modelMap.addAttribute("category", category);
modelMap.put("coursePageVo", coursePageVo);
return "category";
} catch (CategoryNotFoundException e) {
return SystemConstant.PAGE_404;
} catch (StorageNotFoundException e) {
// TODO Auto-generated catch block
return SystemConstant.PAGE_404;
}
}
}
package com.shishuo.studio.action;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.shishuo.studio.action.auth.AuthBaseAction;
@Controller
@RequestMapping("/about")
public class AboutAction extends AuthBaseAction {
/**
* 跳轉(zhuǎn)到關(guān)于我們頁(yè)面
*
* @param modelMap
* @param request
* @return
*/
@RequestMapping(value = "/about.htm", method = RequestMethod.GET)
public String about(ModelMap modelMap, HttpServletRequest request) {
return "/about/about";
}
/**
* 跳轉(zhuǎn)到服務(wù)協(xié)議頁(yè)面
*
* @param modelMap
* @param request
* @return
*/
@RequestMapping(value = "/service.htm", method = RequestMethod.GET)
public String service(ModelMap modelMap, HttpServletRequest request) {
return "/about/service";
}
/**
* 跳轉(zhuǎn)到投訴舉報(bào)頁(yè)面
*
* @param modelMap
* @param request
* @return
*/
@RequestMapping(value = "/complain.htm", method = RequestMethod.GET)
public String complain(ModelMap modelMap, HttpServletRequest request) {
return "/about/complain";
}
/**
* 跳轉(zhuǎn)到版權(quán)聲明頁(yè)面
*
* @param modelMap
* @param request
* @return
*/
@RequestMapping(value = "/copyright.htm", method = RequestMethod.GET)
public String copyright(ModelMap modelMap, HttpServletRequest request) {
return "/about/copyright";
}
/**
* 跳轉(zhuǎn)到聯(lián)系我們頁(yè)面
*
* @param modelMap
* @param request
* @return
*/
@RequestMapping(value = "/connect.htm", method = RequestMethod.GET)
public String connect(ModelMap modelMap, HttpServletRequest request) {
return "/about/connect";
}
}
下面是使用springmvc的經(jīng)驗(yàn):
return "system/comment/comment";后面不需要東西
return "redirect:/admin/comment/page.htm";一般當(dāng)我改變一個(gè)狀態(tài)的時(shí)候 我需要還是顯示在當(dāng)前頁(yè)面 就需要再進(jìn)入Action 相當(dāng)于再到數(shù)據(jù)庫(kù)訪問(wèn)一次把 我改變的數(shù)據(jù)同個(gè)pageVo 顯示到頁(yè)面
spring的注解學(xué)習(xí)
@RequestParam("description") String description,
@PathVariable
請(qǐng)求路徑上有個(gè)id的變量值,可以通過(guò)@PathVariable來(lái)獲取 @RequestMapping(value = "/page/{id}", method = RequestMethod.GET)
@autowired 自動(dòng)配置 不需要寫(xiě)getter() setter()方法
@Deprecated 過(guò)時(shí)
@Repository 用在接口前面的類(lèi) 比如ibits接口類(lèi)的最前面
@ResponseBody當(dāng)控制器返回頁(yè)面不是字符串的時(shí)候 比如返回一個(gè)json對(duì)象用這個(gè)注解
@Controller控制器 加在控制器類(lèi)的最前面
@RequestMapping("/admin/file")
放在類(lèi)前面是這個(gè)路徑下
@RequestMapping(value = "/index.htm", method = RequestMethod.GET)如果這個(gè)注解放在方法的前面 表示上面那個(gè)路徑的基礎(chǔ)下然后再是這個(gè)路勁
@RequestParam(value = "fileId", defaultValue = "1")當(dāng)url傳入?yún)?shù)的時(shí)候就可以拿到值
比如@RequestMapping(value = "/update.htm", method = RequestMethod.GET)
public String update(
@RequestParam(value = "fileId", defaultValue = "1") long fileId,
ModelMap modelMap) throws Exception {}
簡(jiǎn)單原理:
spring mvc請(qǐng)所有的請(qǐng)求都提交給在web.xml中配置的DispatcherServlet,由它查詢(xún)一個(gè)或多個(gè)HandlerMapping,找到處理請(qǐng)求的Controller,并且將請(qǐng)求提交給這個(gè)類(lèi)。
Controller進(jìn)行業(yè)務(wù)邏輯處理后,會(huì)返回一個(gè)ModelAndView
Dispathcher查詢(xún)一個(gè)或多個(gè) ViewResolver視圖解析器,找到ModelAndView對(duì)象指定的視圖對(duì)象 ,視圖對(duì)象負(fù)責(zé)渲染返回給客戶(hù)端。
2、如何快速學(xué)習(xí)strust2
1 導(dǎo)入struts2.x的相關(guān)jar包到WEB-INF/lib下
2 在項(xiàng)目的src目錄下新建struts.properties或struts.xml
struts.properties和struts.xml具有相同的配置作用,配置項(xiàng)目相關(guān)
3 web.xml加入:
<filter>
<filter-name>ActionContextCleanUp</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<!-- 若有其他相關(guān)的filter 需要加在這個(gè)地方-->
<!--配置struts2過(guò)濾器-->
<filter>
<filter-name>webwork</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>ActionContextCleanUp</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
編寫(xiě)action請(qǐng)求處理類(lèi).可以繼承struts2的 ActionSupport也可以不繼承,(不過(guò)一般為了方便獲取 request,response以及session 最好自己編寫(xiě)一個(gè)類(lèi)繼承ActionSupport,并在類(lèi)中獲取request等,讓請(qǐng)求處理類(lèi)繼承這個(gè)類(lèi)),然后根據(jù)頁(yè)面和struts.xml配置決定請(qǐng)求的處理方法.
例1:
頁(yè)面中
<s:form action="login.action" method="post">
<s:textfield key="username" name="user.username"/>
<s:password key="password" name="user.password" />
<s:submit key="submit" />
</s:form>
strust.xml中
<action name="login" class="cc.dynasoft.action.LoginAction">
<result name="success">/welcome.jspresult>
<result name="error">/login.jspresult>
</action>
這時(shí)請(qǐng)求會(huì)交由LoginAction的默認(rèn)方法execute來(lái)處理,在LoginAaction中有user對(duì)象及其set方法,頁(yè)面屬性會(huì)自動(dòng)注入到此user對(duì)象中,返回字符串[success],匹配struts.xml此action內(nèi)的result值確定調(diào)轉(zhuǎn)的展示頁(yè)面
例2:
-----頁(yè)面
<s:form action="submit.action">
<s:textfield name="msg"label="輸入內(nèi)容"/>
<s:submit name="save"value="保存"align="left"method="save"/>
<s:submit name="print"value="打印"align="left"method="print"/>
</s:form>
struts.xml
-----struts.xml:
<action name="submit" class="action.MoreSubmitAction">
<result name="save">/result.jsp</result>
<result name="print">/result.jsp</result>
</action>
由頁(yè)面submit的method方法來(lái)指定對(duì)應(yīng)的處理方法,方法返回字符串.繼而確定調(diào)轉(zhuǎn)展示頁(yè)面
例3:
-----設(shè)置自定義的url后綴,有struts2處理例如struts.action.extension=php.默認(rèn)為action,即處理所有*.action的請(qǐng)求
-----頁(yè)面
<form method="post" action="Kinder_add.php"
<input type="text" name="kinder.name">
<input type="text"name="kinder.zip">
<input type="submit" value="提交">
</form>
-----strust.xml
<action name="*_*" method="{2}" class="ostar.lg.action.{1}Action">
<result name="success">/default.jsp</result>
</action>
這樣的意思是:所有由'_'間隔的請(qǐng)求都會(huì)有'_'前面的字符串同名的action類(lèi)處理,并交給這個(gè)類(lèi)的和'_'后面字符串同名的方法處理[簡(jiǎn)化了配置],方法返回字符串繼而確定調(diào)轉(zhuǎn)展示的頁(yè)面.(*_*只是一種自定義格式,可任意配置)
B 流程:
1、客戶(hù)端初始化一個(gè)對(duì)服務(wù)器的請(qǐng)求(tomcat);
2、這個(gè)請(qǐng)求經(jīng)過(guò)一系列的過(guò)濾器(Filter)(這些過(guò)濾器中有一個(gè)叫做ActionContextCleanUp的可選過(guò)濾器,這個(gè)過(guò)濾器對(duì)于 Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin);
3、接著FilterDispatcher被調(diào)用,F(xiàn)ilterDispatcher詢(xún)問(wèn)ActionMapper來(lái)決定這個(gè)請(qǐng)求是否需要調(diào)用某個(gè) Action;
4、如果ActionMapper決定需要調(diào)用某個(gè)Action,F(xiàn)ilterDispatcher把請(qǐng)求的處理交給ActionProxy;
5、ActionProxy通過(guò)Configuration Manager詢(xún)問(wèn)框架的配置文件,找到需要調(diào)用的Action類(lèi);
6、ActionProxy創(chuàng)建一個(gè)ActionInvocation的實(shí)例。
7、ActionInvocation實(shí)例使用命名模式來(lái)調(diào)用,在調(diào)用Action的過(guò)程前后,涉及到相關(guān)攔截器(Intercepter)的調(diào)用。
8、一旦Action執(zhí)行完畢,ActionInvocation負(fù)責(zé)根據(jù)struts.xml中的配置找到對(duì)應(yīng)的返回結(jié)果。返回結(jié)果通常是(但不總是,也可能是另外的一個(gè)Action鏈)一個(gè)需要被表示的JSP或者FreeMarker的模版。
C特性分析:
1 線程模式,每一次請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的實(shí)例處理請(qǐng)求. 多線程環(huán)境沒(méi)有數(shù)據(jù)同步問(wèn)題.
2 引入數(shù)據(jù)的依賴(lài)注入
[頁(yè)面表單數(shù)據(jù)到action的注入,實(shí)例對(duì)象的注入,都是通過(guò)set注入,需要提供set方法]
3 基于AOP的攔截器,可以在每次請(qǐng)求前后靈活控制
4 配置文件支持表達(dá)式,基于約定優(yōu)于配置的話可簡(jiǎn)化配置文件
4 內(nèi)置以插件形式支持ajax如dojo,支持多種模板展示jsp、freemarker,Velocity等
3、如何快速學(xué)習(xí)strust1
1 導(dǎo)入struts1.x的jar包到web-inf/lib下面
2 在web-inf目錄下新建struts-config.xml文件,配置struts相關(guān)內(nèi)容
3 web.xml配置加入:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
配置隨容器啟動(dòng)的servlet,并初始化struts的配置文件.設(shè)置由struts處理的請(qǐng)求標(biāo)識(shí)
4 編寫(xiě)action控制類(lèi),繼承Action[復(fù)雜情況繼承DispactureAction],同時(shí)在struts-config.xml中配置這個(gè)控制類(lèi)action.例如:
<action path="/stock"
parameter="method"
name="stocklogForm"
type="com.xuanmu.struts.action.stock.StockAction"
scope="request">
<forward name="LIST" path="/productsList.jsp" />
</action>
當(dāng)截取到請(qǐng)求為stock時(shí)就由StockAaction處理.[繼承DispactureAction的話分發(fā)到parameter值對(duì)應(yīng)的方法中去], 該方法返回由字符串封裝[LIST]的ActionForward對(duì)象,然后再struts-config.xml中的匹配 ,決定返回呈現(xiàn)的頁(yè)面
B流程:
1預(yù)備工作:服務(wù)器啟動(dòng),Web應(yīng)用啟動(dòng)時(shí)就會(huì)加載web.xml初始化actionServlet和記載struts配置文件(struts-config.xml),讀配置信息到內(nèi)存中,供以后action調(diào)用
2(由請(qǐng)求定位action控制類(lèi))
用戶(hù)通過(guò)客戶(hù)端向服務(wù)器發(fā)出一個(gè)請(qǐng)求,http://localhost:8080/struts_login/login.do
我們已經(jīng)在web.xml配置了所有符合某特定格式的請(qǐng)求都將由struts指定的Servlet來(lái)處理。比如:只要是以.do結(jié)尾的請(qǐng)求(*.do)都由 org.apache.struts.action.ActionServlet來(lái)對(duì)其進(jìn)行處理.ActionServlet會(huì)拿到用戶(hù)的請(qǐng)求,并且去分析這個(gè)URL,它會(huì)截下 /login. 截下來(lái)之后,它是為了去struts-config.xml這個(gè)配置文件里面找<action>標(biāo)簽path屬性的值等于所截部分的那個(gè) Action.
3(頁(yè)面數(shù)據(jù)注入)
找到對(duì)應(yīng)的action之后,ActionServlet會(huì)把表單提交的數(shù)據(jù)給存放(生成對(duì)應(yīng)調(diào)用 set/get方法)到struts-config中相應(yīng)的action標(biāo)簽的name屬性值指定的actionform類(lèi)中(若有, [actionform的子類(lèi),并且在form-bean標(biāo)簽中配置了,若要進(jìn)行數(shù)據(jù)驗(yàn)證可以在actionform中覆蓋validate方法,推薦使用js,減輕服務(wù)器負(fù)擔(dān)]).同時(shí)把a(bǔ)ctionform和當(dāng)前HttpServletrequest 對(duì)象注入到代調(diào)用的action方法中.
4(調(diào)用action的處理方法)
[默認(rèn)是execute方法可以通過(guò)dispactureAction分發(fā)請(qǐng)求給自定義的方法]可以在方法中取得請(qǐng)求附屬的數(shù)據(jù)(若需要),編寫(xiě)業(yè)務(wù)邏輯代碼處理請(qǐng)求.
5(返回到view層的頁(yè)面)
Action的業(yè)務(wù)邏輯方法會(huì)返回一個(gè)ActionForward對(duì)象 ,ActionForward對(duì)象根據(jù)此action配置的<forward>匹配name進(jìn)而調(diào)轉(zhuǎn)到對(duì)應(yīng)path的jsp頁(yè)面上.
表現(xiàn)層常見(jiàn)框架的對(duì)比
springmvc和strust2比較
1、spring mvc是基于方法的設(shè)計(jì),而sturts是基于類(lèi),每次發(fā)一次請(qǐng)求都會(huì)實(shí)例一個(gè)action,每個(gè)action都會(huì)被注入屬性,而spring基于方法,粒度更細(xì),但要小心把握像在servlet控制數(shù)據(jù)一樣。spring3 mvc是方法級(jí)別的攔截,攔截到方法后根據(jù)參數(shù)上的注解把request數(shù)據(jù)注入進(jìn)去,在spring3 mvc中,一個(gè)方法對(duì)應(yīng)一個(gè)request上下文。而struts2框架是類(lèi)級(jí)別的攔截,每次來(lái)了請(qǐng)求就創(chuàng)建一個(gè)Action,然后調(diào)用setter getter方法把request中的數(shù)據(jù)注入,struts2實(shí)際上是通過(guò)setter getter方法與request打交道的,struts2中,一個(gè)Action對(duì)象對(duì)應(yīng)一個(gè)request上下文。
2、 參數(shù)傳遞struts是在接受參數(shù)的時(shí)候,可以用屬性來(lái)接受參數(shù),這就說(shuō)明參數(shù)是讓多個(gè)方法共享的。
3、 設(shè)計(jì)思想上,struts更加符合oop(面向?qū)ο缶幊?的編程思想, spring就比較謹(jǐn)慎,在servlet上擴(kuò)展。
4. intercepter的實(shí)現(xiàn)機(jī)制,struts有以自己的interceptor機(jī)制,spring mvc用的是獨(dú)立的AOP方式。這樣導(dǎo)致struts的配置文件量還是比spring mvc大,雖然struts的配置能繼承,所以我覺(jué)得論使用上來(lái)講,spring mvc使用更加簡(jiǎn)潔,開(kāi)發(fā)效率Spring MVC確實(shí)比struts2高。spring mvc是方法級(jí)別的攔截,一個(gè)方法對(duì)應(yīng)一個(gè)request上下文,而方法同時(shí)又跟一個(gè)url對(duì)應(yīng),所以說(shuō)從架構(gòu)本身上spring3 mvc就容易實(shí)現(xiàn)restful url。struts2是類(lèi)級(jí)別的攔截,一個(gè)類(lèi)對(duì)應(yīng)一個(gè)request上下文實(shí)現(xiàn)restful url要費(fèi)勁因?yàn)閟truts2 action的一個(gè)方法可以對(duì)應(yīng)一個(gè)url而其類(lèi)屬性卻被所有方法共享這也就無(wú)法用注解或其他方式標(biāo)識(shí)其所屬方法了。spring3 mvc的方法之間基本上獨(dú)立的獨(dú)享request response數(shù)據(jù)請(qǐng)求數(shù)據(jù)通過(guò)參數(shù)獲取處理結(jié)果通過(guò)ModelMap交回給框架方法之間不共享變量而struts2搞的就比較亂雖然方法之間也是獨(dú)立的但其所有Action變量是共享的這不會(huì)影響程序運(yùn)行卻給我們編碼讀程序時(shí)帶來(lái)麻煩。
5. 另外spring3 mvc的驗(yàn)證也是一個(gè)亮點(diǎn),支持JSR303處理ajax的請(qǐng)求更是方便,只需一個(gè)注解@ResponseBody ,然后直接返回響應(yīng)文本即可。
6.springmvc沒(méi)有那么多配置,而strust2配置太多了,spring 2.5之后annotation開(kāi)始簡(jiǎn)化之前的xml配置。眾所周知,一個(gè)項(xiàng)目或者產(chǎn)品到達(dá)一定的建設(shè)程度,如果xml配置文件過(guò)多,維護(hù)起來(lái)確實(shí)比較麻煩,spring MVC通過(guò)一個(gè)spring-config.xml的配置文件配置跳轉(zhuǎn)路徑,在controller簡(jiǎn)單@指向即可。從這點(diǎn)上,項(xiàng)目的干凈程度,可維護(hù)性不言而喻是struts.xml不能比擬的。
7、從設(shè)計(jì)實(shí)現(xiàn)角度來(lái)說(shuō),我覺(jué)得SpringMVC更加清晰。即使我們?nèi)?duì)比Struts2的原理圖和SpringMVC的類(lèi)圖,它依然很讓人困惑,遠(yuǎn)沒(méi)有SpringMVC更加直觀:
8、組件化的設(shè)計(jì)方案和特定的設(shè)計(jì)原則讓SpringMVC形散神聚。
神 —— SpringMVC總是沿著一條固定的邏輯主線運(yùn)行
形 —— SpringMVC卻擁有多種不同的行為模式
SpringMVC是一個(gè)基于組件的開(kāi)發(fā)框架,組件的不同實(shí)現(xiàn)體系構(gòu)成了“形”;組件的邏輯串聯(lián)構(gòu)成了“神”。因此,“形散神不散”: SpringMVC的邏輯主線始終不變,而行為模式卻可以多種多樣。
9、springmvc更加靈活,效率高,擴(kuò)展性更好,有點(diǎn)類(lèi)似ioc 、aop
10、Struts2對(duì)于Controller的改造徹底與web容器解耦,更方便單元測(cè)試,而擺脫了Servlet束縛,在Controller中徹底杜絕引入HttpServletRequest或者HttpServletResponse這樣的原生Servlet對(duì)象,將請(qǐng)求參數(shù)和響應(yīng)數(shù)據(jù)都從響應(yīng)方法中剝離到了Controller中的屬性變量。
strust2和strust1對(duì)比
1、在Action實(shí)現(xiàn)類(lèi)方面的對(duì)比:Struts 1要求Action類(lèi)繼承一個(gè)抽象基類(lèi);Struts 1的一個(gè)具體問(wèn)題是使用抽象類(lèi)編程而不是接口。Struts 2 Action類(lèi)可以實(shí)現(xiàn)一個(gè)Action接口,也可以實(shí)現(xiàn)其他接口,使可選和定制的服務(wù)成為可能。Struts 2提供一個(gè)ActionSupport基類(lèi)去實(shí)現(xiàn)常用的接口。即使Action接口不是必須實(shí)現(xiàn)的,只有一個(gè)包含execute方法的POJO類(lèi)都可以用作Struts 2的Action。
2、 線程模式方面的對(duì)比:Struts 1 Action是單例模式并且必須是線程安全的,因?yàn)閮H有Action的一個(gè)實(shí)例來(lái)處理所有的請(qǐng)求。單例策略限制了Struts 1 Action能做的事,并且要在開(kāi)發(fā)時(shí)特別小心。Action資源必須是線程安全的或同步的;Struts 2 Action對(duì)象為每一個(gè)請(qǐng)求產(chǎn)生一個(gè)實(shí)例,因此沒(méi)有線程安全問(wèn)題。
3、Servlet依賴(lài)方面的對(duì)比:Struts 1 Action依賴(lài)于Servlet API,因?yàn)镾truts 1 Action的execute方法中有HttpServletRequest和HttpServletResponse方法。Struts 2 Action不再依賴(lài)于Servlet API,從而允許Action脫離Web容器運(yùn)行,從而降低了測(cè)試Action的難度。 當(dāng)然,如果Action需要直接訪問(wèn)HttpServletRequest和HttpServletResponse參數(shù),Struts 2 Action仍然可以訪問(wèn)它們。但是,大部分時(shí)候,Action都無(wú)需直接訪問(wèn)HttpServetRequest和HttpServletResponse,從而給開(kāi)發(fā)者更多靈活的選擇。
4、可測(cè)性方面的對(duì)比:測(cè)試Struts 1 Action的一個(gè)主要問(wèn)題是execute方法依賴(lài)于Servlet API,這使得Action的測(cè)試要依賴(lài)于Web容器。為了脫離Web容器測(cè)試Struts 1的Action,必須借助于第三方擴(kuò)展:Struts TestCase,該擴(kuò)展下包含了系列的Mock對(duì)象(模擬了HttpServetRequest和HttpServletResponse對(duì)象),從而可以脫離Web容器測(cè)試Struts 1的Action類(lèi)。Struts 2 Action可以通過(guò)初始化、設(shè)置屬性、調(diào)用方法來(lái)測(cè)試。
5、 封裝請(qǐng)求參數(shù)的對(duì)比:Struts 1使用ActionForm對(duì)象封裝用戶(hù)的請(qǐng)求參數(shù),所有的ActionForm必須繼承一個(gè)基類(lèi):ActionForm。普通的JavaBean不能用作ActionForm,因此,開(kāi)發(fā)者必須創(chuàng)建大量的ActionForm類(lèi)封裝用戶(hù)請(qǐng)求參數(shù)。雖然Struts 1提供了動(dòng)態(tài)ActionForm來(lái)簡(jiǎn)化ActionForm的開(kāi)發(fā),但依然需要在配置文件中定義ActionForm;Struts 2直接使用Action屬性來(lái)封裝用戶(hù)請(qǐng)求屬性,避免了開(kāi)發(fā)者需要大量開(kāi)發(fā)ActionForm類(lèi)的煩瑣,實(shí)際上,這些屬性還可以是包含子屬性的Rich對(duì)象類(lèi)型。如果開(kāi)發(fā)者依然懷念Struts 1 ActionForm的模式,Struts 2提供了ModelDriven模式,可以讓開(kāi)發(fā)者使用單獨(dú)的Model對(duì)象來(lái)封裝用戶(hù)請(qǐng)求參數(shù),但該Model對(duì)象無(wú)需繼承任何Struts 2基類(lèi),是一個(gè)POJO,從而降低了代碼污染。
6、表達(dá)式語(yǔ)言方面的對(duì)比:Struts 1整合了JSTL,因此可以使用JSTL表達(dá)式語(yǔ)言。這種表達(dá)式語(yǔ)言有基本對(duì)象圖遍歷,但在對(duì)集合和索引屬性的支持上則功能不強(qiáng);Struts 2可以使用JSTL,但它整合了一種更強(qiáng)大和靈活的表達(dá)式語(yǔ)言:OGNL(Object Graph Notation Language),因此,Struts 2下的表達(dá)式語(yǔ)言功能更加強(qiáng)大。
7、 — 綁定值到視圖的對(duì)比:Struts 1使用標(biāo)準(zhǔn)JSP機(jī)制把對(duì)象綁定到視圖頁(yè)面;Struts 2使用“ValueStack”技術(shù),使標(biāo)簽庫(kù)能夠訪問(wèn)值,而不需要把對(duì)象和視圖頁(yè)面綁定在一起。
8、類(lèi)型轉(zhuǎn)換的對(duì)比:Struts 1 ActionForm 屬性通常都是String類(lèi)型。Struts 1使用Commons-Beanutils進(jìn)行類(lèi)型轉(zhuǎn)換,每個(gè)類(lèi)一個(gè)轉(zhuǎn)換器,轉(zhuǎn)換器是不可配置的;Struts 2使用OGNL進(jìn)行類(lèi)型轉(zhuǎn)換,支持基本數(shù)據(jù)類(lèi)型和常用對(duì)象之間的轉(zhuǎn)換。
9、 數(shù)據(jù)校驗(yàn)的對(duì)比:Struts 1支持在ActionForm重寫(xiě)validate方法中手動(dòng)校驗(yàn),或者通過(guò)整合Commons alidator框架來(lái)完成數(shù)據(jù)校驗(yàn)。Struts 2支持通過(guò)重寫(xiě)validate方法進(jìn)行校驗(yàn),也支持整合XWork校驗(yàn)框架進(jìn)行校驗(yàn)。
10、 Action執(zhí)行控制的對(duì)比:Struts 1支持每一個(gè)模塊對(duì)應(yīng)一個(gè)請(qǐng)求處理(即生命周期的概念),但是模塊中的所有Action必須共享相同的生命周期。Struts 2支持通過(guò)攔截器堆棧(Interceptor Stacks)為每一個(gè)Action創(chuàng)建不同的生命周期。開(kāi)發(fā)者可以根據(jù)需要?jiǎng)?chuàng)建相應(yīng)堆棧,從而和不同的Action一起使用。
11、捕獲輸入:Struts1 使用ActionForm對(duì)象捕獲輸入。所有的ActionForm必須繼承一個(gè)基類(lèi)。因?yàn)槠渌鸍avaBean不能用作ActionForm,開(kāi)發(fā)者經(jīng)常創(chuàng)建多余的類(lèi)捕獲輸入。動(dòng)態(tài)Bean(DynaBeans)可以作為創(chuàng)建傳統(tǒng)ActionForm的選擇,但是,開(kāi)發(fā)者可能是在重新描述(創(chuàng)建)已經(jīng)存在的JavaBean(仍然會(huì)導(dǎo)致有冗余的javabean)。Struts 2直接使用Action屬性作為輸入屬性,消除了對(duì)第二個(gè)輸入對(duì)象的需求。輸入屬性可能是有自己(子)屬性的rich對(duì)象類(lèi)型。Action屬性能夠通過(guò) web頁(yè)面上的taglibs訪問(wèn)。Struts2也支持ActionForm模式。rich對(duì)象類(lèi)型,包括業(yè)務(wù)對(duì)象,能夠用作輸入/輸出對(duì)象。這種 ModelDriven 特性簡(jiǎn)化了taglib對(duì)POJO輸入對(duì)象的引用。
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門(mén)到禿頭 或掃描下面二維碼
零基礎(chǔ)入門(mén)進(jìn)階人工智能(鏈接)