Model2MVC
h+p://www.javaworld.com/javaworld/jw‐12‐1999/jw‐12‐ssj‐jspmvc.html
LifewithoutMVC
WithMediatorPa+ern
MediatorPa+ernThemediatorpa+ernprovidesaunifiedinterfacetoasetofinterfacesinasubsystem.Thispa+ernisconsideredtobeabehavioralpa+ernduetothewayitcanaltertheprogram'srunningbehavior.Aprogrammaybemadeupofalargenumberofclasses.ThelogicandcomputaJonisdistributedamongtheseclasses.TheproblemofcommunicaJonbetweentheseclassesmaybecomemorecomplex.Thismakestheprogramhardertoreadandmaintain:anychangemayaffectcodeinseveralotherclasses.Withthemediatorpa+ern,communicaJonbetweenobjectsisencapsulatedwithamediatorobject.Objectsnolongercommunicatedirectlywitheachother,butinsteadcommunicatethroughthemediator.ThisreducesthedependenciesbetweencommunicaJngobjects,therebyloweringthecoupling.
FromWikipedia
MVCmodel1
ShortcomingsofMVCmodel1
MVCmodel2
BenefitsofMVCmodel2
IntroducJontoStruts2
Aminiapp
startup.jsp login.jsp
Welcome.jsp
Error
Success
Link
Link
customer.jspValidaJonerrors
successCustomer.jsp
Success
Installstruts2inNetbeans
h+p://plugins.netbeans.org/plugin/23467/netbeans‐struts2‐support
h+p://forums.netbeans.org/topic39893.html
ForEclipsesee
h+p://viralpatel.net/blogs/2009/12/tutorial‐create‐struts‐2‐applicaJon‐eclipse‐example.html
sun‐web.xml‐base<?xmlversion="1.0"encoding="UTF‐8"?><!DOCTYPEsun‐web‐appPUBLIC"‐//SunMicrosystems,Inc.//DTDGlassFishApplicaJonServer3.0Servlet3.0//EN""h+p://www.sun.com/sofware/appserver/dtds/sun‐web‐app_3_0‐0.dtd"><sun‐web‐apperror‐url=""><context‐root>/WebApplicaJon3</context‐root><class‐loaderdelegate="true"/><jsp‐config><propertyname="keepgenerated"value="true"><descripJon>Keepacopyofthegeneratedservletclass'javacode.</descripJon></property></jsp‐config></sun‐web‐app>
web.xml<?xmlversion="1.0"encoding="UTF‐8"?><web‐appversion="3.0"xmlns="h+p://java.sun.com/xml/ns/javaee"xmlns:xsi="h+p://www.w3.org/2001/XMLSchema‐instance"xsi:schemaLocaJon="h+p://java.sun.com/xml/ns/javaeeh+p://java.sun.com/xml/ns/javaee/web‐app_3_0.xsd">
<filter><filter‐name>struts2</filter‐name><filter‐class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter‐class></filter>
<filter‐mapping><filter‐name>struts2</filter‐name><url‐pa+ern>/*</url‐pa+ern>
</filter‐mapping><session‐config><session‐Jmeout>30
</session‐Jmeout></session‐config><welcome‐file‐list><welcome‐file>startup.jsp</welcome‐file>
</welcome‐file‐list></web‐app>
NOTE:inthegeneratedbase,thewelcomefileisindex.jsp
UseStruts2
UseStruts2‐how
Defaultpagetobeloaded
struts.xml‐base<!DOCTYPEstrutsPUBLIC"‐//ApacheSofwareFoundaJon//DTDStrutsConfiguraJon2.0//EN"
"h+p://struts.apache.org/dtds/struts‐2.0.dtd">
<struts>
<!‐‐ConfiguraJonforthedefaultpackage.‐‐>
<packagename="default"extends="struts‐default">
</package>
</struts>
struts.xml<?xmlversion="1.0"encoding="UTF‐8"?><!DOCTYPEstrutsPUBLIC"‐//ApacheSofwareFoundaJon//DTDStrutsConfiguraJon2.0//EN""h+p://struts.apache.org/dtds/struts‐2.0.dtd"><struts><constantname="struts.enable.DynamicMethodInvocaJon"value="false"/><constantname="struts.devMode"value="false"/><constantname="struts.custom.i18n.resources"value="ApplicaJonResources"/><packagename="default"extends="struts‐default"namespace="/"><acJonname="login"class="Demo.LoginAcJon"><resultname="success">Welcome.jsp</result><resultname="error">Login.jsp</result></acJon></package></struts>
Accessthebundle
Definethecontrollinglogic
ApplicaJonResources.properJeslabel.username=Usernamelabel.password=Passwordlabel.login=Loginerror.login=InvalidUsername/Password.Pleasetryagain.name=Nameage=Ageemail=Emailtelephone=Telephonelabel.add.customer=AddCustomererrors.invalid=${getText(fieldName)}isinvalid.errors.required=${getText(fieldName)}isrequired.errors.number=${getText(fieldName)}mustbeanumber.errors.range=${getText(fieldName)}isnotintherange${min}and${max}
Startup.jsp<%@pagecontentType="text/html"pageEncoding="UTF‐8"%><!DOCTYPEHTMLPUBLIC"‐//W3C//DTDHTML4.01TransiJonal//EN""h+p://www.w3.org/TR/html4/loose.dtd"><html><head><metah+p‐equiv="Content‐Type"content="text/html;charset=UTF‐8"><Jtle>JSPPage</Jtle></head><body><h1>Hello.Pleasegotothe<ahref="Login.jsp">registraJon</a></h1></body></html>
Login.jsp<%@pagecontentType="text/html;charset=UTF‐8"%><%@taglibprefix="s"uri="/struts‐tags"%><html><head><Jtle>Struts2‐LoginApplicaJon</Jtle></head><body><h2>Struts2‐LoginApplicaJon</h2><s:acJonerror/><s:formacJon="login"namespace="/"method="get"><s:texwieldname="username"key="label.username"size="20"/><s:passwordname="password"key="label.password"size="20"/><s:submitmethod="execute"key="label.login"align="center"/></s:form></body></html>
Datafromthebundle
ApplicaJonResources.properJeslabel.username=Usernamelabel.password=Passwordlabel.login=Loginerror.login=InvalidUsername/Password.Pleasetryagain.name=Nameage=Ageemail=Emailtelephone=Telephonelabel.add.customer=AddCustomererrors.invalid=${getText(fieldName)}isinvalid.errors.required=${getText(fieldName)}isrequired.errors.number=${getText(fieldName)}mustbeanumber.errors.range=${getText(fieldName)}isnotintherange${min}and${max}
Aminiapp
startup.jsp login.jsp
Welcome.jsp
Error
Success
Link
Link
customer.jspValidaJonerrors
successCustomer.jsp
Success
struts.xml<?xmlversion="1.0"encoding="UTF‐8"?><!DOCTYPEstrutsPUBLIC"‐//ApacheSofwareFoundaJon//DTDStrutsConfiguraJon2.0//EN""h+p://struts.apache.org/dtds/struts‐2.0.dtd"><struts><constantname="struts.enable.DynamicMethodInvocaJon"value="false"/><constantname="struts.devMode"value="false"/><constantname="struts.custom.i18n.resources"value="ApplicaJonResources"/><packagename="Demo"namespace="/"extends="struts‐default"><acJonname="login"class="Demo.LoginAcJon"><interceptor‐refname="loggingStack"></interceptor‐ref><resultname="success">Welcome.jsp</result><resultname="error">Login.jsp</result></acJon></package></struts>
LoginAcJon.javapackageDemo;importcom.opensymphony.xwork2.AcJonSupport;publicclassLoginAcJonextendsAcJonSupport{privateStringusername;privateStringpassword;publicStringexecute(){if(this.username.equals("admin")&&this.password.equals("admin123")){return"success";}else{addAcJonError(getText("error.login"));return"error";}}publicStringgetUsername(){returnusername;}publicvoidsetUsername(Stringusername){this.username=username;}publicStringgetPassword(){returnpassword;}publicvoidsetPassword(Stringpassword){this.password=password;}}
Welcome.jsp
<%@pagecontentType="text/html;charset=UTF‐8"%><%@taglibprefix="s"uri="/struts‐tags"%><html><head><Jtle>Welcome</Jtle></head><body><h2>Howdy,<s:propertyvalue="username"/>...!</h2><s:ahref="Customer.jsp">AddCustomer</s:a></body></html>
Customer.jsp<%@pagecontentType="text/html;charset=UTF‐8"%><%@taglibprefix="s"uri="/struts‐tags"%><html><head><Jtle>CustomerForm‐Struts2Demo</Jtle></head><body><h2>CustomerForm</h2><s:formacJon="customer"namespace="/"method="post"validate="false"><s:texwieldname="name"key="name"size="20"/><s:texwieldname="age"key="age"size="20"/><s:texwieldname="email"key="email"size="20"/><s:texwieldname="telephone"key="telephone"size="20"/><s:submitmethod="addCustomer"key="label.add.customer"align="center"/></s:form></body></html>
struts.xml
<packagename="Demo"namespace="/"extends="struts‐default">…
<acJonname="customer"
class="Demo.CustomerAcJon">
<resultname="success">SuccessCustomer.jsp</result>
<resultname="input">Customer.jsp</result>
</acJon>
</package>
Demo.CustomerAcJonpackageDemo;importcom.opensymphony.xwork2.AcJonSupport;publicclassCustomerAcJonextendsAcJonSupport{privateStringname;privateIntegerage;privateStringemail;privateStringtelephone;publicStringaddCustomer(){returnSUCCESS;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicIntegergetAge(){returnage;}publicvoidsetAge(Integerage){this.age=age;publicStringgetEmail(){returnemail;}publicvoidsetEmail(Stringemail){this.email=email;}publicStringgetTelephone(){returntelephone;}publicvoidsetTelephone(Stringtelephone){this.telephone=telephone;}}
CustomerAcJon‐validaJon.xml<?xmlversion="1.0"encoding="UTF‐8"?><!DOCTYPEvalidatorsPUBLIC"‐//OpenSymphonyGroup//XWorkValidator1.0.2//EN""h+p://www.opensymphony.com/xwork/xwork‐validator‐1.0.2.dtd"><validators><fieldname="name"><field‐validatortype="requiredstring"><paramname="trim">true</param><messagekey="errors.required"/></field‐validator></field><fieldname="age"><field‐validatortype="required"><messagekey="errors.required"/></field‐validator><field‐validatortype="int"><paramname="min">1</param><paramname="max">100</param><messagekey="errors.range"/></field‐validator></field><fieldname="email"><field‐validatortype="requiredstring"><messagekey="errors.required"/></field‐validator><field‐validatortype="email"><messagekey="errors.invalid"/></field‐validator></field><fieldname="telephone"><field‐validatortype="requiredstring"><messagekey="errors.required"/></field‐validator></field></validators>
CustomerSuccess.jsp
<%@pagecontentType="text/html;charset=UTF‐8"%><%@taglibprefix="s"uri="/struts‐tags"%>
<html>
<head>
<Jtle>CustomerPage‐Struts2Demo</Jtle>
</head>
<body>
<h2>CustomerAddedSuccessfully.</h2></body>
</html>
Addinginterceptors<packagename="Demo"namespace="/"extends="struts‐default"><interceptors><interceptorname="mylogging"class="Demo.Interceptors.MyLoggingInterceptor"></interceptor><interceptor‐stackname="loggingStack"><interceptor‐refname="mylogging"/><interceptor‐refname="defaultStack"/></interceptor‐stack></interceptors><acJonname="login"class="Demo.LoginAcJon"><interceptor‐refname="loggingStack"></interceptor‐ref><resultname="success">Welcome.jsp</result><resultname="error">Login.jsp</result></acJon>…</package>
MyLoggingInterceptor.javapackageDemo.Interceptors;importcom.opensymphony.xwork2.AcJonInvocaJon;importcom.opensymphony.xwork2.interceptor.Interceptor;publicclassMyLoggingInterceptorimplementsInterceptor{privatestaJcfinallongserialVersionUID=1L;publicStringintercept(AcJonInvocaJoninvocaJon)throwsExcepJon{StringclassName=invocaJon.getAcJon().getClass().getName();longstartTime=System.currentTimeMillis();System.out.println("BeforecallingacJon:"+className);Stringresult=invocaJon.invoke();longendTime=System.currentTimeMillis();System.out.println("AfercallingacJon:"+className+"Timetaken:"+(endTime‐startTime)+"ms");returnresult;}publicvoiddestroy(){System.out.println("DestroyingMyLoggingInterceptor...");}publicvoidinit(){System.out.println("IniJalizingMyLoggingInterceptor...");}}
BEFORE
AFTER