Вы находитесь на странице: 1из 69

For Struts Developers

Me
• Scott Stanlick
– Drummer
– Techie
– Instructor
– Connoisseur of cereal malt beverages

2
Agenda
• Hello Struts 2
• Action/Interceptor/Result
• Configuration
• OGNL/Value Stack
• Tag Libraries
• Business Validation
• Plug-ins
• Wrap up

3
Hello Struts 2

The History

4
What is Struts 2?
• Not Struts 1.x!
• EE5 Web Framework
• Originally OpenSymphony WebWork
• WebWork + Struts + Apache Incubator
– Struts 2 was hatched in ‘07

5
Built Specifically For…
• Developer Productivity
– Simple HTTP-free code
– Easy Spring integration
– Reusable UI templates
– Plug-in architecture
– Crazy cool type conversions
– Rich validation
– Easy to test
– And so much more!

6
Configuration Styles
• Packaged actions (namespace)
• Package inheritance
• Wildcard mappings
• Generic actions
• Annotations
• Ruby-On-Rails Rest-style mappings
– Convention over configuration

7
Plug-in Architecture
• Similar to Firefox and Eclipse
• Add features by dropping in a jar
• Several bundled plug-ins
– Tiles
– JFreeChart
– JasperReports
– REST-Style URI mappings
• Plug-in registry growing steadily

8
The Core Components
• Actions
• Interceptors
• Results

9
Differences from Struts Classic
• No form beans
• Actions are no longer singletons
• HTTP-free
• Intelligent defaults
• Easy to extend with
– Interceptors
– Results
– Plug-ins

10
Action/Interceptor/Result

The Request Pipeline

11
ActionContext
(ThreadLocal)

12
MVC2
• Where C=Cool!
• Request
– FilterDispatcher
• Dispatcher
– StrutsActionProxy
» ActionInvocation [ThreadLocal]

13
Action
• Packaged according to like kind
– Sort of like Java packages
• ThreadLocal (safe)
• Typically extend ActionSupport
• Contain your domain model
– Can be model driven
• May contain multiple methods
• Not tangled up with Servlet/API
• Easy to test!

14
Action Mapping

<package name="hr" namespace="/hr" extends="starter">


<action
name=“uri“ class=“class“ method=“method">
<result>destination</result>
</action>
<package>

15
Wildcard Action Mapping

<package name="hr" namespace="/hr" extends="starter">


<action
name=“employeeAction_*"
class=“HREmployeeManager"
method=“{1} ">
<result>/employee/{1}.jsp</result>
</action>
<package>

16
HREmployeeManager Action
class HREmployeeManager {

private Employee model;


private EmployeeService service;

public List getList(){…}


}

17
Interceptor
• Intercepts request
– Think AOP
• Called before/after your action
• Useful for cross-cutting concerns
• Built-ins cover 98+% of all use cases
• Configured at package or action level
• Is central to the framework itself
– Eat your own dog food!

18
Interceptor Stack
• An interceptor has a specific role
– Parameter interception
– Validation
– Workflow
• Named “stacks” provide pluggable lists
pre-assembled for goal specific cases
– defaultStack
– fileUploadStack
– modelDrivenStack
– paramsPrepareParamsStack

19
Interceptor Configuration
• Easy to configure wrong!
• config-browser plug-in provides a
glimpse into the runtime
– More about this later

20
Timer Interceptor
• Stopwatch feature for action execution
– “starts” before your action
– “stops” afterward
• Writes performance timings to log
• Order of interceptors is interesting
– See next slide

21
Timer Interceptor (cont.)
<interceptors>
<interceptor-stack name="stackWithTimer">
<interceptor-ref name="timer"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

records action's execution with interceptors

22
Timer Interceptor (cont.)
<interceptors>
<interceptor-stack name="stackWithTimer">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="timer"/>
</interceptor-stack>
</interceptors>

records only the action's execution time

23
Default Stack
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>

24
Result
• What should be returned to requester?
• Many provided out of the box
• It’s easy to write your own
– Graphics
– JSON
– PDF
• It’s another configurable object

25
Result Types
<result-types>
<result-type name="chain" class=“…"/>
<result-type name="dispatcher" class=“…" default="true"/>
<result-type name="freemarker" class=“…"/>
<result-type name="httpheader" class=“…"/>
<result-type name="redirect" class=“…"/>
<result-type name="redirectAction" class=“…"/>
<result-type name="stream" class=“…"/>
<result-type name="velocity" class=“…"/>
<result-type name="xslt" class=“…"/>
<result-type name="plainText" class=“…" />
<result-type name="plaintext" class=“…" />
</result-types>

26
Result Example
<action …>
<result name="success" type="dispatcher">
/employee/list.jsp
</result>
</action>

• name and type are optional


– name defaults to success
– type default can be set by package

27
Connecting the Wildcard Dots

<action name=“employeeAction_*“
class=“HREmployeeManager“ method=“{1} ">
<result>/employee/{1}.jsp</result>
</action>

• www.foo.com/employeeAction_list
• list()
• list.jsp
28
Configuration

Declaring the Web Site Capabilities

29
struts.xml
• Core configuration file for framework
• Can contain multiple packages
<struts>
<package name=“base" extends="struts-default">
<action...>
</package>
<include file=“hr.xml"/>
<include file=“logon.xml"/>
<include file=“preferences.xml"/>
</struts>

30
struts-default.xml
• Most of your packages will extend this
– Directly/Indirectly
• Contains about everything you need
• Packages form inheritance hierarchies
• The key sections are
– package
– result-types
– interceptors/stacks

31
Package Inheritance
<package name=“hr" extends=“base“ namespace="/hr">
<action name=“…”/>
</package>

• struts-default
• base
• hr

32
Intelligent Configuration
• Declarative architecture
• Configurable defaults
• Extendable
– Framework extension points
– Sub-packages
• Shipped in the struts2-core-2.m.n.jar
– struts-default.xml

33
Sample Declaration
<package name=“hr“ extends=“base“ namespace="/hr">

<action name="list“
method=“preload” class=“HREmployeeManager”>
<result>/pages/hr/employee/list.jsp</result>
</action>

</package>

34
Constant Configuration
• Modify framework and plug-in behavior
• Can be declared at multiple levels
• Searched in the following order
– struts-default.xml
– struts-plugin.xml
– struts.xml
– struts.properties
– web.xml
• Subsequent files override previous ones

35
struts.properties
struts.devMode=true
struts.objectFactory=spring
struts.configuration.xml.reload=true
struts.freemarker.templatesCache=true
struts.ui.theme=simple
struts.enable.DynamicMethodInvocation=false
struts.custom.i18n.resources=resources.Messages

36
OGNL/ValueStack

Dynamic Data/Object Graph

37
Dynamic Data
• Where is dynamic data stored?
– Data to generate pages
– User input from pages
• Form beans are gone
• Dependence on Servlet/API is bad
• Welcome to the ValueStack

38
ValueStack
• Leverages the OGNL framework
– Object Graph Navigation Language
• Extends OGNL to support searching stack
– Top down to locate object/property
• Where Interceptors put/get object data
• Thread Safe
• ActionContext.getContext().getValueStack()

39
Struts 2 and OGNL

OGNL Context (ActionContext) Value Stack (OGNL root)


|___Action
|___other objects…
OGNL

#parameters
#request
#session
#application
#attr (searches p, r, s, then a)

40
ValueStack
• Request “Object Stack”
• OGNL expressions search it top down
• Can specify object level
• Common operations
– peek
– pop
– push

41
Type Conversions
• OGNL uses reflection to convert types
• JavaBeans convention provides “hint”
• Custom converters can be added
– Scope
• Bean/Model
• Action
• Application

42
Tag Libraries

The UI

43
Struts 2 Tags
• Tags are divided into 2 sets
– UI
• Form/Non-Form
• Ajax
– Leverages dojo
– Generic
• Control
– if, else, iterator
• Data
– bean, text, url

44
Struts 2 Tags
• Decoupled from underlying view
technology
– JSP
– Velocity
– FreeMarker
• Markup via Freemarker templates

45
S2 Tag Syntax
• The value attribute is not a string
– It’s an OBJECT
• What you pass is evaluated as an
expression!
• <s:sometag … value=“foo”/>
– Looks for getFoo()
• <s:sometag … value=“{‘foo’}”/>
– String literal is passed

46
Tag Templates
• The markup generated is your choice
– HTML
– XML
– JSON
– WML
–…

47
UI Tag Templates
• Template technology is FreeMarker
• CSS classes can be used to control L&F
• You may tweak provided templates
• Tight affinity with ValueStack

48
Base select Component
• View technology agnostic
• org.apache.struts2.components.Select
• Generates markup via TemplateEngine
• S2 provides FreeMarkerTemplateEngine
– Unites ValueStack & FreeMarker

49
<s:select/> JSP Custom Tag
• org.apache.struts2.views.jsp.ui.SelectTag
• Renders a select widget

50
<@s.select/> FreeMarker Tag
• org.apache.struts2.views.freemarker.tags.SelectModel
• Renders a select widget

51
StrutsRequestWrapper
• JSTL does not know OGNL
• This class wraps the Struts request
• Delegates to the Value Stack
• ${customer.address.city}
– Resolves to stack.find under the covers

52
S2 and JSTL
• OGNL values are exposed to JSP/JSTL
• Expression syntax is a little different
– JSTL: ${a.b.c}
– OGNL: %{a.b.c}
• Beware of JSP 2.1 Unified EL JSR 245
– EL has been expanded to interpret #{}
– Clashes with OGNL usage for Maps
• #{ "foo" : "foo value", "bar" : "bar value" }

53
Themes
• S2 UI tags grouped into themes
– simple - minimal with no "bells and whistles"
– xhtml - uses common HTML practices
– css_xhtml - xhtml theme re-implemented
using strictly CSS for layout
– Ajax - based on the xhtml theme that provides
advanced AJAX features
• Specified globally or at the tag level

54
Simple Theme
<H2>Employee Save</H2>
<s:form>
<s:textfield key="employee.name“ required="true"/>
<s:textfield key="employee.department“ required="true"/>
</s:form>

55
XHTML Theme
<H2>Employee Save</H2>
<s:form>
<s:textfield key="employee.name“ required="true"/>
<s:textfield key="employee.department“ required="true"/>
</s:form>

56
Business Validation

Rules and Regulations

57
Validation Styles
• Annotations
• XML
• Java

58
Simple Field Example
• Form
– <s:textfield key="age"/>
• Action
– private int age; get/set
• Validator <ActionClassName>-validation.xml
<field name="age">
<field-validator type="int">
<param name="min">13</param>
<param name="max">19</param>
<message>Only people ages 13 to 19 allowed</message>
</field-validator>
</field>

59
Validator Types
• conversion
• date
• email
• short – int – long - double
• regex <takes a regular expression>
• required
• requiredstring
• stringlength
• url
• visitor - conditionalvisitor
• fieldexpression <resolves an OGNL expression>
• expression <resolves an OGNL expression>

60
Another Field Example
<field name=“password">
<field-validator type="expression">
<param name="expression">
password.equals(password2)
</param>
<message>
Password 2 must equal ${password}
</message>
</field-validator>
</field>

61
Non-Field Validation

<validators>
<validator type="expression">
<param name="expression“> ( (a==b) && (b==c) )</param>
<message>all three fields must be the same></message>
</validator>
</validators>

62
Plug-ins

Extensions Simplified

63
Benefits of plug-ins
• Strategic points in the framework where
you can
– Provide you own implementations
– Add new features
• Add functionality without modifying code
– Open-Closed Principle

64
Configuration Browser
• Exposes the runtime configuration
• Accessed via a browser
– http://.../config-browser/index.action

65
OGNL Viewer
• Provides debugging screens to provide
insight into the data behind the page
• Accessed via a browser
– http://..?debug={flag}
• Flag values
– xml, console, command, browser
• Make sure
– DebuggingInterceptor is included
– struts.devMode=true

66
Wrap up

Odds & Ends

67
My Web Site
• www.struts2inaction.com
• The cobbler’s children have no shoes
• Too many paying gigs to lace up my
own site!
• Vacation time coming
• It will rock!

68
Resources
• Manning
• Nabble
• Google

• Also watch for


– Struts 2 in Practice (Wes Wannemacher)

69

Вам также может понравиться