Render reference documentation with Asciidoctor

This commit removes docbook from the documentation toolchain and
instead makes use of asciidoctor to render the reference documentation
in HTML and PDF formats.

The main Gradle build has been refactored with the documentation tasks
and sniffer tasks extracted to their own gradle file in the "gradle"
folder.

A new asciidoctor Spring theme is also used to render the HTML5 backend.

Issue: SPR-14997
This commit is contained in:
Brian Clozel
2017-01-04 17:51:58 +01:00
parent c5bcefbd07
commit 924adaec6c
93 changed files with 1030 additions and 311 deletions

View File

@@ -0,0 +1,7 @@
<html>
<body>
<p>
This is the public API documentation for the <a href="http://github.com/SpringSource/spring-framework" target="_top">Spring Framework</a>.
</p>
</body>
</html>

599
src/docs/api/stylesheet.css Normal file
View File

@@ -0,0 +1,599 @@
/* Javadoc style sheet */
/*
Overall document style
*/
@import url('resources/fonts/dejavu.css');
body {
background-color:#ffffff;
color:#353833;
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
font-size:14px;
margin:0;
}
a:link, a:visited {
text-decoration:none;
color:#4A6782;
}
a:hover, a:focus {
text-decoration:none;
color:#bb7a2a;
}
a:active {
text-decoration:none;
color:#4A6782;
}
a[name] {
color:#353833;
}
a[name]:hover {
text-decoration:none;
color:#353833;
}
pre {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
}
h1 {
font-size:20px;
}
h2 {
font-size:18px;
}
h3 {
font-size:16px;
font-style:italic;
}
h4 {
font-size:13px;
}
h5 {
font-size:12px;
}
h6 {
font-size:11px;
}
ul {
list-style-type:disc;
}
code, tt {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
padding-top:4px;
margin-top:8px;
line-height:1.4em;
}
dt code {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
padding-top:4px;
}
table tr td dt code {
font-family:'DejaVu Sans Mono', monospace;
font-size:14px;
vertical-align:top;
padding-top:4px;
}
sup {
font-size:8px;
}
/*
Document title and Copyright styles
*/
.clear {
clear:both;
height:0px;
overflow:hidden;
}
.aboutLanguage {
float:right;
padding:0px 21px;
font-size:11px;
z-index:200;
margin-top:-9px;
}
.legalCopy {
margin-left:.5em;
}
.bar a, .bar a:link, .bar a:visited, .bar a:active {
color:#FFFFFF;
text-decoration:none;
}
.bar a:hover, .bar a:focus {
color:#bb7a2a;
}
.tab {
background-color:#0066FF;
color:#ffffff;
padding:8px;
width:5em;
font-weight:bold;
}
/*
Navigation bar styles
*/
.bar {
background-color:#4D7A97;
color:#FFFFFF;
padding:.8em .5em .4em .8em;
height:auto;/*height:1.8em;*/
font-size:11px;
margin:0;
}
.topNav {
background-color:#4D7A97;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
font-size:12px;
}
.bottomNav {
margin-top:10px;
background-color:#4D7A97;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
font-size:12px;
}
.subNav {
background-color:#dee3e9;
float:left;
width:100%;
overflow:hidden;
font-size:12px;
}
.subNav div {
clear:left;
float:left;
padding:0 0 5px 6px;
text-transform:uppercase;
}
ul.navList, ul.subNavList {
float:left;
margin:0 25px 0 0;
padding:0;
}
ul.navList li{
list-style:none;
float:left;
padding: 5px 6px;
text-transform:uppercase;
}
ul.subNavList li{
list-style:none;
float:left;
}
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
color:#FFFFFF;
text-decoration:none;
text-transform:uppercase;
}
.topNav a:hover, .bottomNav a:hover {
text-decoration:none;
color:#bb7a2a;
text-transform:uppercase;
}
.navBarCell1Rev {
background-color:#F8981D;
color:#253441;
margin: auto 5px;
}
.skipNav {
position:absolute;
top:auto;
left:-9999px;
overflow:hidden;
}
/*
Page header and footer styles
*/
.header, .footer {
clear:both;
margin:0 20px;
padding:5px 0 0 0;
}
.indexHeader {
margin:10px;
position:relative;
}
.indexHeader span{
margin-right:15px;
}
.indexHeader h1 {
font-size:13px;
}
.title {
color:#2c4557;
margin:10px 0;
}
.subTitle {
margin:5px 0 0 0;
}
.header ul {
margin:0 0 15px 0;
padding:0;
}
.footer ul {
margin:20px 0 5px 0;
}
.header ul li, .footer ul li {
list-style:none;
font-size:13px;
}
/*
Heading styles
*/
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
background-color:#dee3e9;
border:1px solid #d0d9e0;
margin:0 0 6px -8px;
padding:7px 5px;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
background-color:#dee3e9;
border:1px solid #d0d9e0;
margin:0 0 6px -8px;
padding:7px 5px;
}
ul.blockList ul.blockList li.blockList h3 {
padding:0;
margin:15px 0;
}
ul.blockList li.blockList h2 {
padding:0px 0 20px 0;
}
/*
Page layout container styles
*/
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
clear:both;
padding:10px 20px;
position:relative;
}
.indexContainer {
margin:10px;
position:relative;
font-size:12px;
}
.indexContainer h2 {
font-size:13px;
padding:0 0 3px 0;
}
.indexContainer ul {
margin:0;
padding:0;
}
.indexContainer ul li {
list-style:none;
padding-top:2px;
}
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
font-size:12px;
font-weight:bold;
margin:10px 0 0 0;
color:#4E4E4E;
}
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
margin:5px 0 10px 0px;
font-size:14px;
font-family:'DejaVu Sans Mono',monospace;
}
.serializedFormContainer dl.nameValue dt {
margin-left:1px;
font-size:1.1em;
display:inline;
font-weight:bold;
}
.serializedFormContainer dl.nameValue dd {
margin:0 0 0 1px;
font-size:1.1em;
display:inline;
}
/*
List styles
*/
ul.horizontal li {
display:inline;
font-size:0.9em;
}
ul.inheritance {
margin:0;
padding:0;
}
ul.inheritance li {
display:inline;
list-style:none;
}
ul.inheritance li ul.inheritance {
margin-left:15px;
padding-left:15px;
padding-top:1px;
}
ul.blockList, ul.blockListLast {
margin:10px 0 10px 0;
padding:0;
}
ul.blockList li.blockList, ul.blockListLast li.blockList {
list-style:none;
margin-bottom:15px;
line-height:1.4;
}
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
padding:0px 20px 5px 10px;
border:1px solid #ededed;
background-color:#f8f8f8;
}
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
padding:0 0 5px 8px;
background-color:#ffffff;
border:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
margin-left:0;
padding-left:0;
padding-bottom:15px;
border:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
list-style:none;
border-bottom:none;
padding-bottom:0;
}
table tr td dl, table tr td dl dt, table tr td dl dd {
margin-top:0;
margin-bottom:1px;
}
/*
Table styles
*/
.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
width:100%;
border-left:1px solid #EEE;
border-right:1px solid #EEE;
border-bottom:1px solid #EEE;
}
.overviewSummary, .memberSummary {
padding:0px;
}
.overviewSummary caption, .memberSummary caption, .typeSummary caption,
.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
position:relative;
text-align:left;
background-repeat:no-repeat;
color:#253441;
font-weight:bold;
clear:none;
overflow:hidden;
padding:0px;
padding-top:10px;
padding-left:1px;
margin:0px;
white-space:pre;
}
.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
color:#FFFFFF;
}
.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
padding-bottom:7px;
display:inline-block;
float:left;
background-color:#F8981D;
border: none;
height:16px;
}
.memberSummary caption span.activeTableTab span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
margin-right:3px;
display:inline-block;
float:left;
background-color:#F8981D;
height:16px;
}
.memberSummary caption span.tableTab span {
white-space:nowrap;
padding-top:5px;
padding-left:12px;
padding-right:12px;
margin-right:3px;
display:inline-block;
float:left;
background-color:#4D7A97;
height:16px;
}
.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
padding-top:0px;
padding-left:0px;
padding-right:0px;
background-image:none;
float:none;
display:inline;
}
.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
display:none;
width:5px;
position:relative;
float:left;
background-color:#F8981D;
}
.memberSummary .activeTableTab .tabEnd {
display:none;
width:5px;
margin-right:3px;
position:relative;
float:left;
background-color:#F8981D;
}
.memberSummary .tableTab .tabEnd {
display:none;
width:5px;
margin-right:3px;
position:relative;
background-color:#4D7A97;
float:left;
}
.overviewSummary td, .memberSummary td, .typeSummary td,
.useSummary td, .constantsSummary td, .deprecatedSummary td {
text-align:left;
padding:0px 0px 12px 10px;
width:100%;
}
th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
vertical-align:top;
padding-right:0px;
padding-top:8px;
padding-bottom:3px;
}
th.colFirst, th.colLast, th.colOne, .constantsSummary th {
background:#dee3e9;
text-align:left;
padding:8px 3px 3px 7px;
}
td.colFirst, th.colFirst {
white-space:nowrap;
font-size:13px;
}
td.colLast, th.colLast {
font-size:13px;
}
td.colOne, th.colOne {
font-size:13px;
}
.overviewSummary td.colFirst, .overviewSummary th.colFirst,
.overviewSummary td.colOne, .overviewSummary th.colOne,
.memberSummary td.colFirst, .memberSummary th.colFirst,
.memberSummary td.colOne, .memberSummary th.colOne,
.typeSummary td.colFirst{
width:25%;
vertical-align:top;
}
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
font-weight:bold;
}
.tableSubHeadingColor {
background-color:#EEEEFF;
}
.altColor {
background-color:#FFFFFF;
}
.rowColor {
background-color:#EEEEEF;
}
/*
Content styles
*/
.description pre {
margin-top:0;
}
.deprecatedContent {
margin:0;
padding:10px 0;
}
.docSummary {
padding:0;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
font-style:normal;
}
div.block {
font-size:14px;
font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
}
td.colLast div {
padding-top:0px;
}
td.colLast a {
padding-bottom:3px;
}
/*
Formatting effect styles
*/
.sourceLineNo {
color:green;
padding:0 30px 0 0;
}
h1.hidden {
visibility:hidden;
overflow:hidden;
font-size:10px;
}
.block {
display:block;
margin:3px 10px 2px 0px;
color:#474747;
}
.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
font-weight:bold;
}
.deprecationComment, .emphasizedPhrase, .interfaceName {
font-style:italic;
}
div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
div.block div.block span.interfaceName {
font-style:normal;
}
div.contentContainer ul.blockList li.blockList h2{
padding-bottom:0px;
}
/*
Spring
*/
pre.code {
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
overflow: auto;
padding: 10px;
margin: 4px 20px 2px 0px;
}
pre.code code, pre.code code * {
font-size: 1em;
}
pre.code code, pre.code code * {
padding: 0 !important;
margin: 0 !important;
}

View File

@@ -0,0 +1,19 @@
require 'asciidoctor'
require 'erb'
require 'fileutils'
FileUtils.mkdir_p('build')
FileUtils.cp_r('images','build')
guard 'shell' do
watch(/^.*\.adoc$/) {|m|
if m[0] != "index.adoc"
Asciidoctor.render_file(m[0], :to_dir => "build", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'doctype' => 'book', 'toc' => 'left', 'toclevels' => '2', 'spring-version' => '4.2.0.BUILD-SNAPSHOT', 'revnumber' => '4.2.0.BUILD-SNAPSHOT' })
end
Asciidoctor.render_file("index.adoc", :to_dir => "build", :safe => Asciidoctor::SafeMode::UNSAFE, :attributes=> {'idprefix' => '', 'idseparator' => '-', 'copycss' => '', 'icons' => 'font', 'source-highlighter' => 'prettify', 'sectanchors' => '', 'doctype' => 'book', 'toc' => 'left', 'toclevels' => '1', 'spring-version' => '4.2.0.BUILD-SNAPSHOT', 'revnumber' => '4.2.0.BUILD-SNAPSHOT' })
}
end
guard 'livereload' do
watch(%r{build/.+\.(css|js|html)$})
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,496 @@
[[spring-tld]]
= spring JSP Tag Library
[[spring.tld-intro]]
== Introduction
One of the view technologies you can use with the Spring Framework is Java Server Pages
(JSPs). To help you implement views using Java Server Pages the Spring Framework
provides you with some tags for evaluating errors, setting themes and outputting
internationalized messages.
Please note that the various tags generated by this form tag library are compliant with
the http://www.w3.org/TR/xhtml1/[XHTML-1.0-Strict specification] and attendant
http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict[DTD].
This appendix describes the `spring.tld` tag library.
* <<spring.tld.argument>>
* <<spring.tld.bind>>
* <<spring.tld.escapeBody>>
* <<spring.tld.hasBindErrors>>
* <<spring.tld.htmlEscape>>
* <<spring.tld.message>>
* <<spring.tld.nestedPath>>
* <<spring.tld.param>>
* <<spring.tld.theme>>
* <<spring.tld.transform>>
* <<spring.tld.url>>
* <<spring.tld.eval>>
[[spring.tld.argument]]
== The argument tag
Argument tag based on the JSTL fmt:param tag. The purpose is to support arguments
inside the message and theme tags.
[[spring.tld.argument.table]]
[cols="1,1,1,3"]
.Attributes
|===
| Attribute| Required?| Runtime Expression?| Description
| value
| false
| true
| The value of the argument.
|===
[[spring.tld.bind]]
== The bind tag
Provides BindStatus object for the given bind path. The HTML escaping flag participates
in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a
"defaultHtmlEscape" context-param in web.xml).
[[spring.tld.bind.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| ignoreNestedPath
| false
| true
| Set whether to ignore a nested path, if any. Default is to not ignore.
| path
| true
| true
| The path to the bean or bean property to bind status information for. For instance
account.name, company.address.zipCode or just employee. The status object will
exported to the page scope, specifically for this bean or bean property
|===
[[spring.tld.escapeBody]]
== The escapeBody tag
Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by
HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
[[spring.tld.escapeBody.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| javaScriptEscape
| false
| true
| Set JavaScript escaping for this tag, as boolean value. Default is false.
|===
[[spring.tld.eval]]
== The eval tag
Evaluates a Spring expression (SpEL) and either prints the result or assigns it to a
variable.
[[spring.tld.eval.table]]
[cols="1,1,1,3"]
.Attributes
|===
| Attribute| Required?| Runtime Expression?| Description
| expression
| true
| true
| The expression to evaluate.
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML
escaping setting for the current page.
| javaScriptEscape
| false
| true
| Set JavaScript escaping for this tag, as a boolean value. Default is false.
| scope
| false
| true
| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
supported. Defaults to page scope. This attribute has no effect unless the var
attribute is also defined.
| var
| false
| true
| The name of the variable to export the evaluation result to. If not specified the
evaluation result is converted to a String and written as output.
|===
[[spring.tld.hasBindErrors]]
== The hasBindErrors tag
Provides Errors instance in case of bind errors. The HTML escaping flag participates in
a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape"
context-param in web.xml).
[[spring.tld.hasBindErrors.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| name
| true
| true
| The name of the bean in the request, that needs to be inspected for errors. If errors
are available for this bean, they will be bound under the 'errors' key.
|===
[[spring.tld.htmlEscape]]
== The htmlEscape tag
Sets default HTML escape value for the current page. Overrides a "defaultHtmlEscape"
context-param in web.xml, if any.
[[spring.tld.htmlEscape.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| defaultHtmlEscape
| true
| true
| Set the default value for HTML escaping, to be put into the current PageContext.
|===
[[spring.tld.message]]
== The message tag
Retrieves the message with the given code, or text if code isn't resolvable. The HTML
escaping flag participates in a page-wide or application-wide setting (i.e. by
HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
[[spring.tld.message.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| arguments
| false
| true
| Set optional message arguments for this tag, as a (comma-)delimited String (each
String argument can contain JSP EL), an Object array (used as argument array), or a
single Object (used as single argument).
| argumentSeparator
| false
| true
| The separator character to be used for splitting the arguments string value; defaults
to a 'comma' (',').
| code
| false
| true
| The code (key) to use when looking up the message. If code is not provided, the text
attribute will be used.
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| javaScriptEscape
| false
| true
| Set JavaScript escaping for this tag, as boolean value. Default is false.
| message
| false
| true
| A MessageSourceResolvable argument (direct or through JSP EL). Fits nicely when used
in conjunction with Spring's own validation error classes which all implement the
MessageSourceResolvable interface. For example, this allows you to iterate over all of
the errors in a form, passing each error (using a runtime expression) as the value of
this 'message' attribute, thus effecting the easy display of such error messages.
| scope
| false
| true
| The scope to use when exporting the result to a variable. This attribute is only used
when var is also set. Possible values are page, request, session and application.
| text
| false
| true
| Default text to output when a message for the given code could not be found. If both
text and code are not set, the tag will output null.
| var
| false
| true
| The string to use when binding the result to the page, request, session or application
scope. If not specified, the result gets outputted to the writer (i.e. typically
directly to the JSP).
|===
[[spring.tld.nestedPath]]
== The nestedPath tag
Sets a nested path to be used by the bind tag's path.
[[spring.tld.nestedPath.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| path
| true
| true
| Set the path that this tag should apply. E.g. 'customer' to allow bind paths like
'address.street' rather than 'customer.address.street'.
|===
[[spring.tld.param]]
== The param tag
Parameter tag based on the JSTL c:param tag. The sole purpose is to support params
inside the url tag.
[[spring.tld.param.table]]
[cols="1,1,1,3"]
.Attributes
|===
| Attribute| Required?| Runtime Expression?| Description
| name
| true
| true
| The name of the parameter.
| value
| false
| true
| The value of the parameter.
|===
[[spring.tld.theme]]
== The theme tag
Retrieves the theme message with the given code, or text if code isn't resolvable. The
HTML escaping flag participates in a page-wide or application-wide setting (i.e. by
HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
[[spring.tld.theme.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| arguments
| false
| true
| Set optional message arguments for this tag, as a (comma-)delimited String (each
String argument can contain JSP EL), an Object array (used as argument array), or a
single Object (used as single argument).
| argumentSeparator
| false
| true
| The separator character to be used for splitting the arguments string value; defaults
to a 'comma' (',').
| code
| false
| true
| The code (key) to use when looking up the message. If code is not provided, the text
attribute will be used.
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| javaScriptEscape
| false
| true
| Set JavaScript escaping for this tag, as boolean value. Default is false.
| message
| false
| true
| A MessageSourceResolvable argument (direct or through JSP EL).
| scope
| false
| true
| The scope to use when exporting the result to a variable. This attribute is only used
when var is also set. Possible values are page, request, session and application.
| text
| false
| true
| Default text to output when a message for the given code could not be found. If both
text and code are not set, the tag will output null.
| var
| false
| true
| The string to use when binding the result to the page, request, session or application
scope. If not specified, the result gets outputted to the writer (i.e. typically
directly to the JSP).
|===
[[spring.tld.transform]]
== The transform tag
Provides transformation of variables to Strings, using an appropriate custom
PropertyEditor from BindTag (can only be used inside BindTag). The HTML escaping flag
participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a
'defaultHtmlEscape' context-param in web.xml).
[[spring.tld.transform.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping
setting for the current page.
| scope
| false
| true
| The scope to use when exported the result to a variable. This attribute is only used
when var is also set. Possible values are page, request, session and application.
| value
| true
| true
| The value to transform. This is the actual object you want to have transformed (for
instance a Date). Using the PropertyEditor that is currently in use by the
'spring:bind' tag.
| var
| false
| true
| The string to use when binding the result to the page, request, session or application
scope. If not specified, the result gets outputted to the writer (i.e. typically
directly to the JSP).
|===
[[spring.tld.url]]
== The url tag
Creates URLs with support for URI template variables, HTML/XML escaping, and Javascript
escaping. Modeled after the JSTL c:url tag with backwards compatibility in mind.
[[spring.tld.url.table]]
.Attributes
[cols="1,1,1,3"]
|===
| Attribute| Required?| Runtime Expression?| Description
| value
| true
| true
| The URL to build. This value can include template {placeholders} that are replaced
with the URL encoded value of the named parameter. Parameters must be defined using
the param tag inside the body of this tag.
| context
| false
| true
| Specifies a remote application context path. The default is the current application
context path.
| var
| false
| true
| The name of the variable to export the URL value to. If not specified the URL is
written as output.
| scope
| false
| true
| The scope for the var. 'application', 'session', 'request' and 'page' scopes are
supported. Defaults to page scope. This attribute has no effect unless the var
attribute is also defined.
| htmlEscape
| false
| true
| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML
escaping setting for the current page.
| javaScriptEscape
| false
| true
| Set JavaScript escaping for this tag, as a boolean value. Default is false.
|===

View File

@@ -0,0 +1,44 @@
[[spring-core]]
= Core Technologies
:doc-root: https://docs.spring.io
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
[partintro]
--
This part of the reference documentation covers all of those technologies that are
absolutely integral to the Spring Framework.
Foremost amongst these is the Spring Framework's Inversion of Control (IoC) container. A
thorough treatment of the Spring Framework's IoC container is closely followed by
comprehensive coverage of Spring's Aspect-Oriented Programming (AOP) technologies. The
Spring Framework has its own AOP framework, which is conceptually easy to understand,
and which successfully addresses the 80% sweet spot of AOP requirements in Java
enterprise programming.
Coverage of Spring's integration with AspectJ (currently the richest - in terms of
features - and certainly most mature AOP implementation in the Java enterprise space) is
also provided.
* <<beans>>
* <<resources>>
* <<validation>>
* <<expressions>>
* <<aop>>
* <<aop-api>>
--
include::core/core-beans.adoc[leveloffset=+1]
include::core/core-resources.adoc[leveloffset=+1]
include::core/core-validation.adoc[leveloffset=+1]
include::core/core-expressions.adoc[leveloffset=+1]
include::core/core-aop.adoc[leveloffset=+1]
include::core/core-aop-api.adoc[leveloffset=+1]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,666 @@
[[resources]]
= Resources
[[resources-introduction]]
== Introduction
Java's standard `java.net.URL` class and standard handlers for various URL prefixes
unfortunately are not quite adequate enough for all access to low-level resources. For
example, there is no standardized `URL` implementation that may be used to access a
resource that needs to be obtained from the classpath, or relative to a
`ServletContext`. While it is possible to register new handlers for specialized `URL`
prefixes (similar to existing handlers for prefixes such as `http:`), this is generally
quite complicated, and the `URL` interface still lacks some desirable functionality,
such as a method to check for the existence of the resource being pointed to.
[[resources-resource]]
== The Resource interface
Spring's `Resource` interface is meant to be a more capable interface for abstracting
access to low-level resources.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
----
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
----
Some of the most important methods from the `Resource` interface are:
* `getInputStream()`: locates and opens the resource, returning an `InputStream` for
reading from the resource. It is expected that each invocation returns a fresh
`InputStream`. It is the responsibility of the caller to close the stream.
* `exists()`: returns a `boolean` indicating whether this resource actually exists in
physical form.
* `isOpen()`: returns a `boolean` indicating whether this resource represents a handle
with an open stream. If `true`, the `InputStream` cannot be read multiple times, and
must be read once only and then closed to avoid resource leaks. Will be `false` for
all usual resource implementations, with the exception of `InputStreamResource`.
* `getDescription()`: returns a description for this resource, to be used for error
output when working with the resource. This is often the fully qualified file name or
the actual URL of the resource.
Other methods allow you to obtain an actual `URL` or `File` object representing the
resource (if the underlying implementation is compatible, and supports that
functionality).
The `Resource` abstraction is used extensively in Spring itself, as an argument type in
many method signatures when a resource is needed. Other methods in some Spring APIs
(such as the constructors to various `ApplicationContext` implementations), take a
`String` which in unadorned or simple form is used to create a `Resource` appropriate to
that context implementation, or via special prefixes on the `String` path, allow the
caller to specify that a specific `Resource` implementation must be created and used.
While the `Resource` interface is used a lot with Spring and by Spring, it's actually
very useful to use as a general utility class by itself in your own code, for access to
resources, even when your code doesn't know or care about any other parts of Spring.
While this couples your code to Spring, it really only couples it to this small set of
utility classes, which are serving as a more capable replacement for `URL`, and can be
considered equivalent to any other library you would use for this purpose.
It is important to note that the `Resource` abstraction does not replace functionality:
it wraps it where possible. For example, a `UrlResource` wraps a URL, and uses the
wrapped `URL` to do its work.
[[resources-implementations]]
== Built-in Resource implementations
There are a number of `Resource` implementations that come supplied straight out of the
box in Spring:
[[resources-implementations-urlresource]]
=== UrlResource
The `UrlResource` wraps a `java.net.URL`, and may be used to access any object that is
normally accessible via a URL, such as files, an HTTP target, an FTP target, etc. All
URLs have a standardized `String` representation, such that appropriate standardized
prefixes are used to indicate one URL type from another. This includes `file:` for
accessing filesystem paths, `http:` for accessing resources via the HTTP protocol,
`ftp:` for accessing resources via FTP, etc.
A `UrlResource` is created by Java code explicitly using the `UrlResource` constructor,
but will often be created implicitly when you call an API method which takes a `String`
argument which is meant to represent a path. For the latter case, a JavaBeans
`PropertyEditor` will ultimately decide which type of `Resource` to create. If the path
string contains a few well-known (to it, that is) prefixes such as `classpath:`, it will
create an appropriate specialized `Resource` for that prefix. However, if it doesn't
recognize the prefix, it will assume the this is just a standard URL string, and will
create a `UrlResource`.
[[resources-implementations-classpathresource]]
=== ClassPathResource
This class represents a resource which should be obtained from the classpath. This uses
either the thread context class loader, a given class loader, or a given class for
loading resources.
This `Resource` implementation supports resolution as `java.io.File` if the class path
resource resides in the file system, but not for classpath resources which reside in a
jar and have not been expanded (by the servlet engine, or whatever the environment is)
to the filesystem. To address this the various `Resource` implementations always support
resolution as a `java.net.URL`.
A `ClassPathResource` is created by Java code explicitly using the `ClassPathResource`
constructor, but will often be created implicitly when you call an API method which
takes a `String` argument which is meant to represent a path. For the latter case, a
JavaBeans `PropertyEditor` will recognize the special prefix `classpath:` on the string
path, and create a `ClassPathResource` in that case.
[[resources-implementations-filesystemresource]]
=== FileSystemResource
This is a `Resource` implementation for `java.io.File` handles. It obviously supports
resolution as a `File`, and as a `URL`.
[[resources-implementations-servletcontextresource]]
=== ServletContextResource
This is a `Resource` implementation for `ServletContext` resources, interpreting
relative paths within the relevant web application's root directory.
This always supports stream access and URL access, but only allows `java.io.File` access
when the web application archive is expanded and the resource is physically on the
filesystem. Whether or not it's expanded and on the filesystem like this, or accessed
directly from the JAR or somewhere else like a DB (it's conceivable) is actually
dependent on the Servlet container.
[[resources-implementations-inputstreamresource]]
=== InputStreamResource
A `Resource` implementation for a given `InputStream`. This should only be used if no
specific `Resource` implementation is applicable. In particular, prefer
`ByteArrayResource` or any of the file-based `Resource` implementations where possible.
In contrast to other `Resource` implementations, this is a descriptor for an __already__
opened resource - therefore returning `true` from `isOpen()`. Do not use it if you need
to keep the resource descriptor somewhere, or if you need to read a stream multiple
times.
[[resources-implementations-bytearrayresource]]
=== ByteArrayResource
This is a `Resource` implementation for a given byte array. It creates a
`ByteArrayInputStream` for the given byte array.
It's useful for loading content from any given byte array, without having to resort to a
single-use `InputStreamResource`.
[[resources-resourceloader]]
== The ResourceLoader
The `ResourceLoader` interface is meant to be implemented by objects that can return
(i.e. load) `Resource` instances.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public interface ResourceLoader {
Resource getResource(String location);
}
----
All application contexts implement the `ResourceLoader` interface, and therefore all
application contexts may be used to obtain `Resource` instances.
When you call `getResource()` on a specific application context, and the location path
specified doesn't have a specific prefix, you will get back a `Resource` type that is
appropriate to that particular application context. For example, assume the following
snippet of code was executed against a `ClassPathXmlApplicationContext` instance:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
----
What would be returned would be a `ClassPathResource`; if the same method was executed
against a `FileSystemXmlApplicationContext` instance, you'd get back a
`FileSystemResource`. For a `WebApplicationContext`, you'd get back a
`ServletContextResource`, and so on.
As such, you can load resources in a fashion appropriate to the particular application
context.
On the other hand, you may also force `ClassPathResource` to be used, regardless of the
application context type, by specifying the special `classpath:` prefix:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
----
Similarly, one can force a `UrlResource` to be used by specifying any of the standard
`java.net.URL` prefixes:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
----
[source,java,indent=0]
[subs="verbatim,quotes"]
----
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
----
The following table summarizes the strategy for converting ``String``s to ``Resource``s:
[[resources-resource-strings]]
.Resource strings
|===
| Prefix| Example| Explanation
| classpath:
| `classpath:com/myapp/config.xml`
| Loaded from the classpath.
| file:
| `file:///data/config.xml`
| Loaded as a `URL`, from the filesystem. footnote:[But see also
pass:specialcharacters,macros[<<resources-filesystemresource-caveats>>].]
| http:
| `http://myserver/logo.png`
| Loaded as a `URL`.
| (none)
| `/data/config.xml`
| Depends on the underlying `ApplicationContext`.
|===
[[resources-resourceloaderaware]]
== The ResourceLoaderAware interface
The `ResourceLoaderAware` interface is a special marker interface, identifying objects
that expect to be provided with a `ResourceLoader` reference.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}
----
When a class implements `ResourceLoaderAware` and is deployed into an application
context (as a Spring-managed bean), it is recognized as `ResourceLoaderAware` by the
application context. The application context will then invoke the
`setResourceLoader(ResourceLoader)`, supplying itself as the argument (remember, all
application contexts in Spring implement the `ResourceLoader` interface).
Of course, since an `ApplicationContext` is a `ResourceLoader`, the bean could also
implement the `ApplicationContextAware` interface and use the supplied application
context directly to load resources, but in general, it's better to use the specialized
`ResourceLoader` interface if that's all that's needed. The code would just be coupled
to the resource loading interface, which can be considered a utility interface, and not
the whole Spring `ApplicationContext` interface.
As of Spring 2.5, you can rely upon autowiring of the `ResourceLoader` as an alternative
to implementing the `ResourceLoaderAware` interface. The "traditional" `constructor` and
`byType` autowiring modes (as described in <<beans-factory-autowire>>) are now capable
of providing a dependency of type `ResourceLoader` for either a constructor argument or
setter method parameter respectively. For more flexibility (including the ability to
autowire fields and multiple parameter methods), consider using the new annotation-based
autowiring features. In that case, the `ResourceLoader` will be autowired into a field,
constructor argument, or method parameter that is expecting the `ResourceLoader` type as
long as the field, constructor, or method in question carries the `@Autowired`
annotation. For more information, see <<beans-autowired-annotation>>.
[[resources-as-dependencies]]
== Resources as dependencies
If the bean itself is going to determine and supply the resource path through some sort
of dynamic process, it probably makes sense for the bean to use the `ResourceLoader`
interface to load resources. Consider as an example the loading of a template of some
sort, where the specific resource that is needed depends on the role of the user. If the
resources are static, it makes sense to eliminate the use of the `ResourceLoader`
interface completely, and just have the bean expose the `Resource` properties it needs,
and expect that they will be injected into it.
What makes it trivial to then inject these properties, is that all application contexts
register and use a special JavaBeans `PropertyEditor` which can convert `String` paths
to `Resource` objects. So if `myBean` has a template property of type `Resource`, it can
be configured with a simple string for that resource, as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<bean id="myBean" class="...">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
----
Note that the resource path has no prefix, so because the application context itself is
going to be used as the `ResourceLoader`, the resource itself will be loaded via a
`ClassPathResource`, `FileSystemResource`, or `ServletContextResource` (as appropriate)
depending on the exact type of the context.
If there is a need to force a specific `Resource` type to be used, then a prefix may be
used. The following two examples show how to force a `ClassPathResource` and a
`UrlResource` (the latter being used to access a filesystem file).
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
----
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
----
[[resources-app-ctx]]
== Application contexts and Resource paths
[[resources-app-ctx-construction]]
=== Constructing application contexts
An application context constructor (for a specific application context type) generally
takes a string or array of strings as the location path(s) of the resource(s) such as
XML files that make up the definition of the context.
When such a location path doesn't have a prefix, the specific `Resource` type built from
that path and used to load the bean definitions, depends on and is appropriate to the
specific application context. For example, if you create a
`ClassPathXmlApplicationContext` as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
----
The bean definitions will be loaded from the classpath, as a `ClassPathResource` will be
used. But if you create a `FileSystemXmlApplicationContext` as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");
----
The bean definition will be loaded from a filesystem location, in this case relative to
the current working directory.
Note that the use of the special classpath prefix or a standard URL prefix on the
location path will override the default type of `Resource` created to load the
definition. So this `FileSystemXmlApplicationContext`...
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
----
... will actually load its bean definitions from the classpath. However, it is still a
`FileSystemXmlApplicationContext`. If it is subsequently used as a `ResourceLoader`, any
unprefixed paths will still be treated as filesystem paths.
[[resources-app-ctx-classpathxml]]
==== Constructing ClassPathXmlApplicationContext instances - shortcuts
The `ClassPathXmlApplicationContext` exposes a number of constructors to enable
convenient instantiation. The basic idea is that one supplies merely a string array
containing just the filenames of the XML files themselves (without the leading path
information), and one __also__ supplies a `Class`; the `ClassPathXmlApplicationContext`
will derive the path information from the supplied class.
An example will hopefully make this clear. Consider a directory layout that looks like
this:
[literal]
[subs="verbatim,quotes"]
----
com/
foo/
services.xml
daos.xml
MessengerService.class
----
A `ClassPathXmlApplicationContext` instance composed of the beans defined in the
`'services.xml'` and `'daos.xml'` could be instantiated like so...
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class);
----
Please do consult the `ClassPathXmlApplicationContext` javadocs for details
on the various constructors.
[[resources-app-ctx-wildcards-in-resource-paths]]
=== Wildcards in application context constructor resource paths
The resource paths in application context constructor values may be a simple path (as
shown above) which has a one-to-one mapping to a target Resource, or alternately may
contain the special "classpath*:" prefix and/or internal Ant-style regular expressions
(matched using Spring's `PathMatcher` utility). Both of the latter are effectively
wildcards
One use for this mechanism is when doing component-style application assembly. All
components can 'publish' context definition fragments to a well-known location path, and
when the final application context is created using the same path prefixed via
`classpath*:`, all component fragments will be picked up automatically.
Note that this wildcarding is specific to use of resource paths in application context
constructors (or when using the `PathMatcher` utility class hierarchy directly), and is
resolved at construction time. It has nothing to do with the `Resource` type itself.
It's not possible to use the `classpath*:` prefix to construct an actual `Resource`, as
a resource points to just one resource at a time.
[[resources-app-ctx-ant-patterns-in-paths]]
==== Ant-style Patterns
When the path location contains an Ant-style pattern, for example:
[literal]
[subs="verbatim"]
----
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
----
The resolver follows a more complex but defined procedure to try to resolve the
wildcard. It produces a Resource for the path up to the last non-wildcard segment and
obtains a URL from it. If this URL is not a `jar:` URL or container-specific variant
(e.g. `zip:` in WebLogic, `wsjar` in WebSphere, etc.), then a `java.io.File` is
obtained from it and used to resolve the wildcard by traversing the filesystem. In the
case of a jar URL, the resolver either gets a `java.net.JarURLConnection` from it or
manually parses the jar URL and then traverses the contents of the jar file to resolve
the wildcards.
[[resources-app-ctx-portability]]
===== Implications on portability
If the specified path is already a file URL (either explicitly, or implicitly because
the base `ResourceLoader` is a filesystem one, then wildcarding is guaranteed to work in
a completely portable fashion.
If the specified path is a classpath location, then the resolver must obtain the last
non-wildcard path segment URL via a `Classloader.getResource()` call. Since this is just
a node of the path (not the file at the end) it is actually undefined (in the
`ClassLoader` javadocs) exactly what sort of a URL is returned in this case. In
practice, it is always a `java.io.File` representing the directory, where the classpath
resource resolves to a filesystem location, or a jar URL of some sort, where the
classpath resource resolves to a jar location. Still, there is a portability concern on
this operation.
If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to
get a `java.net.JarURLConnection` from it, or manually parse the jar URL, to be able to
walk the contents of the jar, and resolve the wildcard. This will work in most
environments, but will fail in others, and it is strongly recommended that the wildcard
resolution of resources coming from jars be thoroughly tested in your specific
environment before you rely on it.
[[resources-classpath-wildcards]]
==== The Classpath*: portability classpath*: prefix
When constructing an XML-based application context, a location string may use the
special `classpath*:` prefix:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
----
This special prefix specifies that all classpath resources that match the given name
must be obtained (internally, this essentially happens via a
`ClassLoader.getResources(...)` call), and then merged to form the final application
context definition.
[NOTE]
====
The wildcard classpath relies on the `getResources()` method of the underlying
classloader. As most application servers nowadays supply their own classloader
implementation, the behavior might differ especially when dealing with jar files. A
simple test to check if `classpath*` works is to use the classloader to load a file from
within a jar on the classpath:
`getClass().getClassLoader().getResources("<someFileInsideTheJar>")`. Try this test with
files that have the same name but are placed inside two different locations. In case an
inappropriate result is returned, check the application server documentation for
settings that might affect the classloader behavior.
====
The `classpath*:` prefix can also be combined with a `PathMatcher` pattern in the
rest of the location path, for example `classpath*:META-INF/*-beans.xml`. In this
case, the resolution strategy is fairly simple: a `ClassLoader.getResources()` call is
used on the last non-wildcard path segment to get all the matching resources in the
class loader hierarchy, and then off each resource the same PathMatcher resolution
strategy described above is used for the wildcard subpath.
[[resources-wildcards-in-path-other-stuff]]
==== Other notes relating to wildcards
Please note that `classpath*:` when combined with Ant-style patterns will only work
reliably with at least one root directory before the pattern starts, unless the actual
target files reside in the file system. This means that a pattern like
`classpath*:*.xml` will not retrieve files from the root of jar files but rather only
from the root of expanded directories. This originates from a limitation in the JDK's
`ClassLoader.getResources()` method which only returns file system locations for a
passed-in empty string (indicating potential roots to search).
Ant-style patterns with `classpath:` resources are not guaranteed to find matching
resources if the root package to search is available in multiple class path locations.
This is because a resource such as
[literal]
[subs="verbatim,quotes"]
----
com/mycompany/package1/service-context.xml
----
may be in only one location, but when a path such as
[literal]
[subs="verbatim,quotes"]
----
classpath:com/mycompany/**/service-context.xml
----
is used to try to resolve it, the resolver will work off the (first) URL returned by
`getResource("com/mycompany")`;. If this base package node exists in multiple
classloader locations, the actual end resource may not be underneath. Therefore,
preferably, use " `classpath*:`" with the same Ant-style pattern in such a case, which
will search all class path locations that contain the root package.
[[resources-filesystemresource-caveats]]
=== FileSystemResource caveats
A `FileSystemResource` that is not attached to a `FileSystemApplicationContext` (that
is, a `FileSystemApplicationContext` is not the actual `ResourceLoader`) will treat
absolute vs. relative paths as you would expect. Relative paths are relative to the
current working directory, while absolute paths are relative to the root of the
filesystem.
For backwards compatibility (historical) reasons however, this changes when the
`FileSystemApplicationContext` is the `ResourceLoader`. The
`FileSystemApplicationContext` simply forces all attached `FileSystemResource` instances
to treat all location paths as relative, whether they start with a leading slash or not.
In practice, this means the following are equivalent:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/context.xml");
----
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx =
new FileSystemXmlApplicationContext("/conf/context.xml");
----
As are the following: (Even though it would make sense for them to be different, as one
case is relative and the other absolute.)
[source,java,indent=0]
[subs="verbatim,quotes"]
----
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");
----
[source,java,indent=0]
[subs="verbatim,quotes"]
----
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");
----
In practice, if true absolute filesystem paths are needed, it is better to forgo the use
of absolute paths with `FileSystemResource` / `FileSystemXmlApplicationContext`, and
just force the use of a `UrlResource`, by using the `file:` URL prefix.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");
----
[source,java,indent=0]
[subs="verbatim,quotes"]
----
// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:///conf/context.xml");
----

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 ejb.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.25667in"
height="2.64in" viewBox="0 0 306.48 190.08" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:metric="true"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.833336em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.75em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(0.24012,-0.24)">
<title>Box.1</title>
<desc>Application Server (e.g. JBoss, WebLogic)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="153" cy="104.622" width="306" height="170.916"/>
<rect x="0" y="19.164" width="306" height="170.916" class="st1"/>
<text x="59.35" y="185.62" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Application Server (e.g. JBoss, WebLogic)</text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(30.1749,-23.3831)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="49.8912" cy="159.506" width="99.79" height="61.1476"/>
<rect x="0" y="128.932" width="99.7826" height="61.1476" class="st3"/>
<text x="4" y="174.51" class="st2" v:langID="1033"><v:paragraph/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Core </text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(161.223,-89.6263)">
<title>Box.3</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="51.8869" cy="159.506" width="103.78" height="61.1476"/>
<rect x="0" y="128.932" width="103.774" height="61.1476" class="st3"/>
<text x="33.65" y="174.51" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Context</text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(6.89229,-150.773)">
<title>Box</title>
<desc>EJB Access layer using SlsbInvokers</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="69.8477" cy="170.547" width="139.71" height="39.0665"/>
<g id="shadow4-11" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.014" width="139.696" height="39.0665" class="st5"/>
</g>
<rect x="0" y="151.014" width="139.696" height="39.0665" class="st6"/>
<text x="22.83" y="167.85" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EJB Access layer using <tspan
x="44.09" dy="1.2em" class="st8">SlsbInvokers</tspan></text> </g>
<g id="shape5-16" v:mID="5" v:groupContext="shape" transform="translate(161.888,-23.3831)">
<title>Box.4</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="51.2216" cy="159.506" width="102.46" height="61.1476"/>
<rect x="0" y="128.932" width="102.443" height="61.1476" class="st3"/>
<text x="45.09" y="174.51" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape6-19" v:mID="6" v:groupContext="shape" transform="translate(26.5572,-60.768)">
<title>Box.5</title>
<desc>Spring-managed EJBs (using AbstractEnterpriseBean</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.1564" cy="149.315" width="162.33" height="81.5301"/>
<g id="shadow6-20" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="108.55" width="162.313" height="81.5301" class="st5"/>
</g>
<rect x="0" y="108.55" width="162.313" height="81.5301" class="st6"/>
<text x="36.12" y="152.02" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring-managed EJBs</text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,253 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 full.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.97167in"
height="3.59998in" viewBox="0 0 357.96 259.199" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.666664em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.499992em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(3.12,-11.3134)">
<title>Box.1</title>
<desc>Servlet Container (Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="176.4" cy="140.913" width="352.8" height="236.571"/>
<rect x="0" y="22.6271" width="352.8" height="236.571" class="st1"/>
<text x="116.6" y="248.91" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (Tomcat / Jetty)<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(16.08,-37.4777)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="239.778" width="163.8" height="38.8414"/>
<rect x="0" y="220.357" width="163.8" height="38.8414" class="st3"/>
<text x="60.56" y="246.98" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/>Spring Core</text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(180.24,-37.4777)">
<title>Box.3</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="239.778" width="163.81" height="38.8414"/>
<rect x="0" y="220.357" width="163.8" height="38.8414" class="st3"/>
<text x="60.56" y="246.98" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(180.24,-74.7955)">
<title>Box.4</title>
<desc>Spring ORM</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="240.395" width="163.8" height="37.6071"/>
<rect x="0" y="221.591" width="163.8" height="37.6071" class="st3"/>
<text x="11" y="238" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/> Spring ORM <v:newlineChar/></text> </g>
<g id="shape5-13" v:mID="5" v:groupContext="shape" transform="translate(16.44,-143.999)">
<title>Box.5</title>
<desc>Spring Web</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="241.199" width="327.6" height="36"/>
<rect x="0" y="223.199" width="327.6" height="36" class="st3"/>
<text x="142.9" y="243.6" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Web</text> </g>
<g id="shape7-16" v:mID="7" v:groupContext="shape" transform="translate(16.26,-74.7955)">
<title>Box.7</title>
<desc>Spring AOP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="240.395" width="163.8" height="37.6071"/>
<rect x="0" y="221.591" width="163.8" height="37.6071" class="st3"/>
<text x="4" y="238" class="st2" v:langID="1033"><v:paragraph/><v:tabList/> Spring AOP<v:newlineChar/></text> </g>
<g id="shape9-19" v:mID="9" v:groupContext="shape" transform="translate(114,-65.4848)">
<title>Box</title>
<desc>Hibernate mappings Custom Hibernate DAOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="245.484" width="144.91" height="27.4286"/>
<g id="shadow9-20" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="231.77" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="231.77" width="144.9" height="27.4286" class="st6"/>
<text x="45.6" y="243.68" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hibernate mappings<v:newlineChar/><tspan
x="39.44" dy="1.2em" class="st8">Custom Hibernate DAOs</tspan></text> </g>
<g id="shape10-25" v:mID="10" v:groupContext="shape" transform="translate(16.44,-179.999)">
<title>Box.10</title>
<desc>Spring Web MVC</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="246.052" width="327.6" height="26.2929"/>
<rect x="0" y="232.906" width="327.6" height="26.2929" class="st3"/>
<text x="132.9" y="248.45" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Web MVC</text> </g>
<g id="shape6-28" v:mID="6" v:groupContext="shape" transform="translate(20.4,-211.542)">
<title>Box.6</title>
<desc>Form Controllers handling form interaction</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow6-29" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="13.66" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Form Controllers <tspan
x="17.82" dy="1.2em" class="st8">handling form </tspan><tspan x="22.16" dy="1.2em" class="st8">interaction</tspan></text> </g>
<g id="shape11-35" v:mID="11" v:groupContext="shape" transform="translate(102.48,-211.679)">
<title>Box.11</title>
<desc>Multipart Resolver to handle file uploads</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow11-36" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="11.83" y="235.01" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Multipart Resolver<v:newlineChar/><tspan
x="7.65" dy="1.2em" class="st8">to handle file uploads</tspan></text> </g>
<g id="shape12-41" v:mID="12" v:groupContext="shape" transform="translate(181.68,-211.679)">
<title>Box.12</title>
<desc>Dynamic binding of data to the domain model</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow12-42" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="10.49" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Dynamic binding of <tspan
x="11.15" dy="1.2em" class="st8">data to the domain </tspan><tspan x="27.83" dy="1.2em" class="st8">model</tspan></text> </g>
<g id="shape13-48" v:mID="13" v:groupContext="shape" transform="translate(263.76,-211.679)">
<title>Box.13</title>
<desc>Integration with JSP, FreeMarker, XSLT, PDF, Excel</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="36" cy="236.81" width="72" height="44.7771"/>
<g id="shadow13-49" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="214.421" width="72" height="44.7771" class="st5"/>
</g>
<rect x="0" y="214.421" width="72" height="44.7771" class="st6"/>
<text x="8.49" y="231.41" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Integration with JSP, <tspan
x="7.83" dy="1.2em" class="st8">FreeMarker</tspan>, XSLT, PDF, <tspan x="28.66" dy="1.2em" class="st8">Excel</tspan></text> </g>
<g id="shape15-55" v:mID="15" v:groupContext="shape" transform="translate(16.44,-112.319)">
<title>Box.15</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="243.359" width="327.6" height="31.68"/>
<rect x="0" y="227.519" width="327.6" height="31.68" class="st3"/>
<text x="137.34" y="245.76" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring Context</text> </g>
<g id="shape8-58" v:mID="8" v:groupContext="shape" transform="translate(114,-138.239)">
<title>Box.8</title>
<desc>Declarative transaction management for POJOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow8-59" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="8.31" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Declarative transaction management for POJOs</text> </g>
<g id="shape14-63" v:mID="14" v:groupContext="shape" transform="translate(114,-107.999)">
<title>Box.14</title>
<desc>Custom business logic</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow14-64" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="41.99" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Custom business logic</text> </g>
<g id="shape16-68" v:mID="16" v:groupContext="shape" transform="translate(0.24,-107.999)">
<title>Box.16</title>
<desc>Sending Email</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="23.04" cy="231.839" width="46.08" height="54.72"/>
<g id="shadow16-69" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="204.479" width="46.08" height="54.72" class="st5"/>
</g>
<rect x="0" y="204.479" width="46.08" height="54.72" class="st6"/>
<text x="12.04" y="230.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Sending <tspan
x="15.55" dy="1.2em" class="st8">Email</tspan></text> </g>
<g id="shape17-74" v:mID="17" v:groupContext="shape" transform="translate(309.84,-107.999)">
<title>Box.17</title>
<desc>Remote access via Hession or SOAP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="23.04" cy="231.839" width="46.08" height="54.72"/>
<g id="shadow17-75" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="204.479" width="46.08" height="54.72" class="st5"/>
</g>
<rect x="0" y="204.479" width="46.08" height="54.72" class="st6"/>
<text x="12.55" y="222.84" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Remote <tspan
x="9.04" dy="1.2em" class="st8">access via<v:newlineChar/></tspan><tspan x="11.38" dy="1.2em" class="st8">Hession</tspan>, SOAP</text> </g>
<g id="shape18-82" v:mID="18" v:groupContext="shape" transform="translate(114,-172.799)">
<title>Box.18</title>
<desc>WebApplicationContext providing e.g. messaging</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72" cy="251.999" width="144" height="14.4"/>
<g id="shadow18-83" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="244.799" width="144" height="14.4" class="st5"/>
</g>
<rect x="0" y="244.799" width="144" height="14.4" class="st6"/>
<text x="6.63" y="253.8" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>WebApplicationContext providing e.g. messaging</text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,612 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
<svg
xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6.4728541in"
height="5.9522467in"
viewBox="0 0 466.04561 428.56238"
xml:space="preserve"
class="st5"
id="svg5499"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="mvc-splitted-contexts.svg"
style="font-size:12px;overflow:visible;color-interpolation-filters:sRGB;fill:none;fill-rule:evenodd;stroke-linecap:square;stroke-miterlimit:3"
inkscape:export-filename="/Users/seb/Workspace/spring-framework/src/asciidoc/images/mvc-splitted-contexts.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><metadata
id="metadata5713"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs5711"><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker9162"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path9164" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8834"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8836" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8518"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8520" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker8214"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path8216" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7922"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7924" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7641"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7644" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7373"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7375" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7117"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7119" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6873"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6875" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6641"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6643" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6421"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6423" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6213"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6215" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6017"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path6019" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5833"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5835" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5661"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5663" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5501"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5503" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5353"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5355" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5217"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5219" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5093"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5095" /></marker><marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4981"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"><path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path4983" /></marker><marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always"><path
id="path7394"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) rotate(180) translate(0,0)" /></marker><marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker8121"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path8123"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker8033"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path8035"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker7957"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7959"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7376"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker><marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7388"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" /></marker><marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7370"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" /></marker></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1680"
inkscape:window-height="1005"
id="namedview5709"
showgrid="false"
inkscape:zoom="1.1640492"
inkscape:cx="134.86698"
inkscape:cy="203.59898"
inkscape:window-x="84"
inkscape:window-y="176"
inkscape:window-maximized="0"
inkscape:current-layer="g5503"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><v:documentProperties
v:langID="1033"
v:viewMarkup="false" /><style
type="text/css"
id="style5501"><![CDATA[
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
.st4 {font-size:0.333333em;font-weight:normal}
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]></style><g
v:mID="0"
v:index="1"
v:groupContext="foregroundPage"
id="g5503"
transform="matrix(0.99998201,0,0,1.0824094,-40.812382,-98.908648)"><rect
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6599"
width="382.68423"
height="146.09897"
x="87.884865"
y="148.26482" /><v:userDefs><v:ud
v:nameU="SchemeName"
v:val="VT4(Default)" /></v:userDefs><rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5725"
width="464.31128"
height="374.11411"
x="41.684383"
y="112.3262" /><title
id="title5505">Page-1</title><v:pageProperties
v:drawingScale="0.0393701"
v:pageScale="0.0393701"
v:drawingUnits="24"
v:shadowOffsetX="8.50394"
v:shadowOffsetY="-8.50394" /><v:layer
v:name="Connector"
v:index="0" /><rect
style="fill:#dde2cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.53790233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5715"
width="322.8194"
height="43.63184"
x="119.95335"
y="-135.66222"
transform="scale(1,-1)" /><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.7580471px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="168.843"
y="124.32391"
id="text5717"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan5719"
x="168.843"
y="124.32391"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">DispatcherServlet</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="89.770851"
y="181.20923"
id="text6589"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6591"
x="89.770851"
y="181.20923"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">Servlet WebApplicationContext</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="260.00443"
y="198.41273"
id="text6593"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6595"
x="260.00443"
y="198.41273"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle">(containing controllers, view resolvers,</tspan><tspan
sodipodi:role="line"
x="260.00443"
y="212.83057"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
id="tspan6597">and other web-related beans)</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6620"
width="82.040657"
height="36.72575"
x="114.52653"
y="-259.43161"
transform="scale(1,-1)" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.89166164;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6622"
width="87.843979"
height="36.697304"
x="223.39864"
y="-287.19809"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-264.81918"
x="117.92834"
height="36.72575"
width="82.040657"
id="rect6614"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="121.24728"
y="260.14957"
id="text6616"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6618"
x="121.24728"
y="260.14957"
style="font-size:11.53426838px">Controllers</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6624"
y="282.70709"
x="219.61203"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="282.70709"
x="219.61203"
id="tspan6626"
sodipodi:role="line">ViewResolver</tspan></text>
<rect
transform="scale(1,-1)"
y="-259.30249"
x="332.5405"
height="36.577778"
width="114.4539"
id="rect6628"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.0161339;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="327.51276"
y="255.28464"
id="text6630"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6632"
x="327.51276"
y="255.28464"
style="font-size:11.53426838px">HandlerMapping</tspan></text>
<rect
y="338.69724"
x="87.803261"
height="121.5683"
width="382.84744"
id="rect6634"
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6636"
y="376.61673"
x="108.61351"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif"
y="376.61673"
x="108.61351"
id="tspan6638"
sodipodi:role="line">Root WebApplicationContext</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6640"
y="395.35812"
x="260.93863"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
id="tspan6644"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
y="395.35812"
x="260.93863"
sodipodi:role="line">(containing middle-tier services, datasources, etc.)</tspan></text>
<rect
transform="scale(1,-1)"
y="-440.06805"
x="164.32933"
height="36.72575"
width="82.040657"
id="rect6648"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6650"
width="82.040657"
height="36.72575"
x="167.73116"
y="-445.45563"
transform="scale(1,-1)" /><text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6652"
y="448.55054"
x="175.87148"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="448.55054"
x="175.87148"
id="tspan6654"
sodipodi:role="line">Services</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88435173;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6656"
width="86.393044"
height="36.704323"
x="306.86328"
y="-439.60837"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-444.99475"
x="310.26624"
height="36.701977"
width="86.876686"
id="rect6658"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88679528;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="305.30771"
y="448.55054"
id="text6660"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6662"
x="305.30771"
y="448.55054"
style="font-size:11.53426838px">Repositories</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.76895118px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 265.33234,295.60379 c 0,42.65169 0,42.65169 0,0 z"
id="path7643"
inkscape:connector-curvature="0" /><path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.46028023;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
d="m 270.43505,294.70585 c 0,39.4721 0,39.87903 0,39.87903"
id="path7645"
inkscape:connector-curvature="0" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="352.55331"
y="333.03622"
id="text4963"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
x="352.55331"
y="333.03622"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
id="tspan4965">Delegates if no bean found</tspan></text>
</g></svg>

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -0,0 +1,328 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
<svg
xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6.4728541in"
height="5.9522467in"
viewBox="0 0 466.04561 428.56238"
xml:space="preserve"
class="st5"
id="svg5499"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="mvc-contexts.svg"
style="font-size:12px;overflow:visible;color-interpolation-filters:sRGB;fill:none;fill-rule:evenodd;stroke-linecap:square;stroke-miterlimit:3"
inkscape:export-filename="/Users/seb/Workspace/spring-framework/src/asciidoc/images/mvc-contexts.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><metadata
id="metadata5713"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs5711"><marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true"><path
id="path7376"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" /></marker></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1680"
inkscape:window-height="1005"
id="namedview5709"
showgrid="false"
inkscape:zoom="1.6462142"
inkscape:cx="155.45357"
inkscape:cy="336.8551"
inkscape:window-x="21"
inkscape:window-y="98"
inkscape:window-maximized="0"
inkscape:current-layer="g5503"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><v:documentProperties
v:langID="1033"
v:viewMarkup="false" /><style
type="text/css"
id="style5501"><![CDATA[
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
.st4 {font-size:0.333333em;font-weight:normal}
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]></style><g
v:mID="0"
v:index="1"
v:groupContext="foregroundPage"
id="g5503"
transform="matrix(0.99998201,0,0,1.0824094,-40.812382,-98.908648)"><rect
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6599"
width="382.43433"
height="188.04903"
x="85.781693"
y="258.60324" /><v:userDefs><v:ud
v:nameU="SchemeName"
v:val="VT4(Default)" /></v:userDefs><rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5725"
width="464.32324"
height="369.18631"
x="41.678398"
y="112.32077" /><title
id="title5505">Page-1</title><v:pageProperties
v:drawingScale="0.0393701"
v:pageScale="0.0393701"
v:drawingUnits="24"
v:shadowOffsetX="8.50394"
v:shadowOffsetY="-8.50394" /><v:layer
v:name="Connector"
v:index="0" /><rect
style="fill:#dde2cd;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.53790233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect5715"
width="322.73892"
height="48.939812"
x="119.99358"
y="-141.00999"
transform="scale(1,-1)" /><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.7580471px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="168.843"
y="121.24811"
id="text5717"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan5719"
x="168.843"
y="121.24811"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">DispatcherServlet</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6620"
width="82.040657"
height="36.72575"
x="112.29841"
y="-347.66547"
transform="scale(1,-1)" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.89166164;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6622"
width="87.843979"
height="36.697304"
x="221.17052"
y="-375.43195"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-353.05304"
x="115.70022"
height="36.72575"
width="82.040657"
id="rect6614"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="119.10567"
y="351.94809"
id="text6616"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6618"
x="119.10567"
y="351.94809"
style="font-size:11.53426838px">Controllers</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6624"
y="374.50562"
x="217.47043"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="374.50562"
x="217.47043"
id="tspan6626"
sodipodi:role="line">ViewResolver</tspan></text>
<rect
transform="scale(1,-1)"
y="-347.53635"
x="322.31219"
height="36.577778"
width="114.4539"
id="rect6628"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.0161339;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="317.68164"
y="347.08316"
id="text6630"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6632"
x="317.68164"
y="347.08316"
style="font-size:11.53426838px">HandlerMapping</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6636"
y="293.18585"
x="105.32181"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif"
y="293.18585"
x="105.32181"
id="tspan6638"
sodipodi:role="line">Root WebApplicationContext</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6640"
y="309.14661"
x="262.53387"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
id="tspan6644"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle"
y="309.14661"
x="262.53387"
sodipodi:role="line">(containing all beans)</tspan></text>
<rect
transform="scale(1,-1)"
y="-428.58945"
x="153.3537"
height="36.72575"
width="82.040657"
id="rect6648"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86203903;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6650"
width="82.040657"
height="36.72575"
x="156.75552"
y="-433.97702"
transform="scale(1,-1)" /><text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6652"
y="436.60834"
x="165.32202"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:11.53426838px"
y="436.60834"
x="165.32202"
id="tspan6654"
sodipodi:role="line">Services</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88435173;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1"
id="rect6656"
width="86.393044"
height="36.704323"
x="295.88763"
y="-428.12976"
transform="scale(1,-1)" /><rect
transform="scale(1,-1)"
y="-433.51614"
x="299.29059"
height="36.701977"
width="86.876686"
id="rect6658"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.88679528;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="294.75827"
y="436.60834"
id="text6660"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan6662"
x="294.75827"
y="436.60834"
style="font-size:11.53426838px">Repositories</tspan></text>
<text
transform="scale(1.0403984,0.96117025)"
sodipodi:linespacing="125%"
id="text6773"
y="137.2662"
x="168.56981"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30.7580471px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426838px;font-family:sans-serif;-inkscape-font-specification:sans-serif"
y="137.2662"
x="168.56981"
id="tspan6775"
sodipodi:role="line">(with empty contextConfigLocation)</tspan></text>
<rect
y="159.68262"
x="86.602486"
height="52.970345"
width="383.42438"
id="rect8949"
style="fill:#dde2cd;fill-opacity:1;stroke:#000000;stroke-width:1.53790233;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="89.612297"
y="201.20198"
id="text8951"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
id="tspan8953"
x="89.612297"
y="201.20198"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:23.06853676px;font-family:sans-serif;-inkscape-font-specification:sans-serif">Servlet WebApplicationContext</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="270.91974"
y="244.23273"
id="text8955"
sodipodi:linespacing="125%"
transform="scale(1.0403984,0.96117025)"><tspan
sodipodi:role="line"
x="270.91974"
y="244.23273"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.53426743px;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start"
id="tspan4875">Delegates</tspan></text>
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.33447409;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
d="m 270.42494,213.70262 c 0,40.78465 0,40.78465 0,40.78465"
id="path9077"
inkscape:connector-curvature="0" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:30.7580471px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="274.18076"
y="257.56573"
id="text4867"
sodipodi:linespacing="125%"
transform="scale(1.0403985,0.9611702)"><tspan
sodipodi:role="line"
id="tspan4869"
x="274.18076"
y="257.56573"></tspan></text>
</g></svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 remoting.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.70667in"
height="2.65333in" viewBox="0 0 338.88 191.04" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:metric="true"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.75em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.666664em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="8.99999"
v:shadowOffsetY="-8.99999"/>
<g id="shape1-1" v:mID="1" v:groupContext="shape" transform="translate(0.240333,-10.8)">
<title>Box.1</title>
<desc>Servlet Container (e.g. Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="169.199" cy="126.24" width="338.4" height="129.6"/>
<rect x="0" y="61.4399" width="338.4" height="129.6" class="st1"/>
<text x="93.17" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (e.g. Tomcat / Jetty)<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape2-4" v:mID="2" v:groupContext="shape" transform="translate(12.326,-37.8001)">
<title>Box.2</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="78.5567" cy="158.64" width="157.12" height="64.7999"/>
<rect x="0" y="126.24" width="157.114" height="64.7999" class="st3"/>
<text x="54.54" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Spring Core</text> </g>
<g id="shape3-7" v:mID="3" v:groupContext="shape" transform="translate(169.44,-37.8001)">
<title>Box.3</title>
<desc>Spring Context</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="78.5567" cy="158.64" width="157.12" height="64.7999"/>
<rect x="0" y="126.24" width="157.114" height="64.7999" class="st3"/>
<text x="48.78" y="177.54" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Spring Context </text> </g>
<g id="shape4-10" v:mID="4" v:groupContext="shape" transform="translate(8.09603,-151.2)">
<title>Box.10</title>
<desc>JAX RPC client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="38.3717" cy="171.24" width="76.75" height="39.6"/>
<g id="shadow4-11" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="76.7442" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="76.7442" height="39.6" class="st6"/>
<text x="11.03" y="173.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>JAX RPC client</text> </g>
<g id="shape5-15" v:mID="5" v:groupContext="shape" transform="translate(18.9732,-97.2)">
<title>Box.4</title>
<desc>Transprarent remote access (using remote package)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="150.466" cy="176.64" width="300.94" height="28.8"/>
<g id="shadow5-16" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="162.24" width="300.934" height="28.8" class="st5"/>
</g>
<rect x="0" y="162.24" width="300.934" height="28.8" class="st6"/>
<text x="58.65" y="179.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Transp<tspan
class="st8" v:langID="2057">ar</tspan>ent remote access (using remote package)</text> </g>
<g id="shape6-21" v:mID="6" v:groupContext="shape" transform="translate(18.9732,-68.4)">
<title>Box</title>
<desc>Custom logic contained by beans</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="150.466" cy="176.64" width="300.94" height="28.8"/>
<g id="shadow6-22" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="162.24" width="300.934" height="28.8" class="st5"/>
</g>
<rect x="0" y="162.24" width="300.934" height="28.8" class="st6"/>
<text x="91.55" y="179.04" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Custom logic contained by beans</text> </g>
<g id="shape7-26" v:mID="7" v:groupContext="shape" transform="translate(96.9259,-151.2)">
<title>Box.5</title>
<desc>Hessian client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="36.1057" cy="171.24" width="72.22" height="39.6"/>
<g id="shadow7-27" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="72.212" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="72.212" height="39.6" class="st6"/>
<text x="11.2" y="173.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hessian client</text> </g>
<g id="shape9-36" v:mID="9" v:groupContext="shape" transform="translate(266.126,-151.2)">
<title>Box.7</title>
<desc>RMI client</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(3.99999,3.99999,3.99999,3.99999)"/>
<v:textRect cx="33.6885" cy="171.24" width="67.38" height="39.6"/>
<g id="shadow9-37" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st5"/>
</g>
<rect x="0" y="151.44" width="67.3778" height="39.6" class="st6"/>
<text x="26.37" y="168.84" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RMI<v:newlineChar/><tspan
x="24.36" dy="1.2em" class="st8">client</tspan></text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 spring-overview.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.26772in"
height="11.6929in" viewBox="0 0 595.276 841.89" xml:space="preserve" color-interpolation-filters="sRGB" class="st5">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#969696;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st3 {fill:#000000;font-family:Arial;font-size:2.50001em;font-weight:bold}
.st4 {font-size:0.333333em;font-weight:normal}
.st5 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<v:userDefs>
<v:ud v:nameU="SchemeName" v:val="VT4(Default)"/>
</v:userDefs>
<title>Page-1</title>
<v:pageProperties v:drawingScale="0.0393701" v:pageScale="0.0393701" v:drawingUnits="24" v:shadowOffsetX="8.50394"
v:shadowOffsetY="-8.50394"/>
<v:layer v:name="Connector" v:index="0"/>
<g id="group9-1" transform="translate(549.921,-255.118) scale(-1,1)" v:mID="9" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.9</title>
<desc>Core The IoC container</desc>
<g id="shape10-2" v:mID="10" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.10</title>
<path d="M0 827.72 L521.57 827.72 L507.4 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape11-4" v:mID="11" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.11</title>
<path d="M0 856.06 L14.17 841.89 L14.17 756.85 L0 771.02 L0 856.06 Z" class="st1"/>
</g>
<g id="shape12-6" v:mID="12" v:groupContext="shape">
<title>Sheet.12</title>
<rect x="0" y="756.85" width="521.575" height="85.0394" class="st2"/>
</g>
<g id="shape9-8" v:mID="9" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="260.787" cy="799.37" width="521.58" height="85.0394"/>
<text x="-294.97" y="797.57" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Core<v:newlineChar/><v:newlineChar/><tspan
x="-300.54" dy="2.76em" class="st4">The IoC container</tspan></text> </g>
</g>
<g id="group1-11" transform="translate(269.291,-368.504) scale(-1,1)" v:mID="1" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.1</title>
<desc>AOP Spring AOP AspectJ integration</desc>
<g id="shape2-12" v:mID="2" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.2</title>
<path d="M0 827.72 L240.94 827.72 L226.77 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape3-14" v:mID="3" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.3</title>
<path d="M0 856.06 L14.17 841.89 L14.17 756.85 L0 771.02 L0 856.06 Z" class="st1"/>
</g>
<g id="shape4-16" v:mID="4" v:groupContext="shape">
<title>Sheet.4</title>
<rect x="0" y="756.85" width="240.945" height="85.0394" class="st2"/>
</g>
<g id="shape1-18" v:mID="1" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="120.472" cy="799.37" width="240.95" height="85.0394"/>
<text x="-152.97" y="791.57" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AOP<v:newlineChar/><v:newlineChar/><tspan
x="-146.87" dy="2.76em" class="st4">Spring AOP<v:newlineChar/></tspan><tspan x="-162.99" dy="1.2em"
class="st4">AspectJ integration</tspan></text> </g>
</g>
<g id="group5-22" transform="translate(133.228,-481.89) scale(-1,1)" v:mID="5" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.5</title>
<desc>DAO Spring JDBC Transaction management</desc>
<g id="shape6-23" v:mID="6" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.6</title>
<path d="M0 827.72 L104.88 827.72 L90.71 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape7-25" v:mID="7" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.7</title>
<path d="M0 856.06 L14.17 841.89 L14.17 657.64 L0 671.81 L0 856.06 Z" class="st1"/>
</g>
<g id="shape8-27" v:mID="8" v:groupContext="shape">
<title>Sheet.8</title>
<rect x="0" y="657.638" width="104.882" height="184.252" class="st2"/>
</g>
<g id="shape5-29" v:mID="5" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="52.4409" cy="749.764" width="104.89" height="184.252"/>
<text x="-85.76" y="735.96" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>DAO<v:newlineChar/><v:newlineChar/><tspan
x="-81.33" dy="2.76em" class="st4">Spring JDBC<v:newlineChar/></tspan><tspan x="-78.56" dy="1.2em"
class="st4">Transaction </tspan><tspan x="-81.62" dy="1.2em" class="st4">management</tspan></text> </g>
</g>
<g id="group13-34" transform="translate(413.858,-368.504) scale(-1,1)" v:mID="13" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.13</title>
<desc>JEE JMX JMS JCA Remoting EJBs Email</desc>
<g id="shape14-35" v:mID="14" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.14</title>
<path d="M0 827.72 L113.39 827.72 L99.21 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape15-37" v:mID="15" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.15</title>
<path d="M0 856.06 L14.17 841.89 L14.17 544.25 L0 558.43 L0 856.06 Z" class="st1"/>
</g>
<g id="shape16-39" v:mID="16" v:groupContext="shape">
<title>Sheet.16</title>
<rect x="0" y="544.252" width="113.386" height="297.638" class="st2"/>
</g>
<g id="shape13-41" v:mID="13" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="56.6929" cy="693.071" width="113.39" height="297.638"/>
<text x="-85.04" y="661.27" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>JEE<v:newlineChar/><v:newlineChar/><tspan
x="-66.69" dy="2.76em" class="st4">JMX<v:newlineChar/></tspan><tspan x="-66.69" dy="1.2em" class="st4">JMS<v:newlineChar/></tspan><tspan
x="-66.13" dy="1.2em" class="st4">JCA<v:newlineChar/></tspan><tspan x="-78.08" dy="1.2em" class="st4">Remoting<v:newlineChar/></tspan><tspan
x="-68.36" dy="1.2em" class="st4">EJBs<v:newlineChar/></tspan><tspan x="-69.19" dy="1.2em" class="st4">Email</tspan></text> </g>
</g>
<g id="group17-49" transform="translate(552.756,-368.504) scale(-1,1)" v:mID="17" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.17</title>
<desc>Web Spring Web MVC Framework Integration Struts WebWork Tapes...</desc>
<g id="shape18-50" v:mID="18" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.18</title>
<path d="M0 827.72 L113.39 827.72 L99.21 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape19-52" v:mID="19" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.19</title>
<path d="M0 856.06 L14.17 841.89 L14.17 544.25 L0 558.43 L0 856.06 Z" class="st1"/>
</g>
<g id="shape20-54" v:mID="20" v:groupContext="shape">
<title>Sheet.20</title>
<rect x="0" y="544.252" width="113.386" height="297.638" class="st2"/>
</g>
<g id="shape17-56" v:mID="17" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="56.6929" cy="693.071" width="113.39" height="297.638"/>
<text x="-88.35" y="613.27" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Web<v:newlineChar/><v:newlineChar/><tspan
x="-95.31" dy="2.76em" class="st4">Spring Web MVC<v:newlineChar/></tspan><tspan x="-106.71" dy="1.2em"
class="st4">Framework Integration<v:newlineChar/></tspan><tspan x="-69.75" dy="1.2em" class="st4">Struts<v:newlineChar/></tspan><tspan
x="-78.63" dy="1.2em" class="st4">WebWork<v:newlineChar/></tspan><tspan x="-76.14" dy="1.2em"
class="st4">Tapestry<v:newlineChar/></tspan><tspan x="-65.57" dy="1.2em" class="st4">JSF<v:newlineChar/></tspan><tspan
x="-97.82" dy="1.2em" class="st4">Rich View Support<v:newlineChar/></tspan><tspan x="-68.36" dy="1.2em"
class="st4">JSPs<v:newlineChar/></tspan><tspan x="-74.19" dy="1.2em" class="st4">FreeMarker<v:newlineChar/></tspan><tspan
x="-82.52" dy="1.2em" class="st4">FreeMarker<v:newlineChar/></tspan><tspan x="-66.69" dy="1.2em"
class="st4">PDF<v:newlineChar/></tspan><tspan x="-90.59" dy="1.2em" class="st4">Jasper Reports<v:newlineChar/></tspan><tspan
x="-68.91" dy="1.2em" class="st4">Excel<v:newlineChar/></tspan><tspan x="-99.48" dy="1.2em" class="st4">Spring Portlet MVC</tspan></text> </g>
</g>
<g id="group21-72" transform="translate(269.291,-481.89) scale(-1,1)" v:mID="21" v:groupContext="group">
<v:userDefs>
<v:ud v:nameU="Scale" v:val="VT0(1):26"/>
<v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<title>3-D box.21</title>
<desc>ORM Hibernate JPA TopLink JDO OJB iBatis</desc>
<g id="shape22-73" v:mID="22" v:groupContext="shape" transform="translate(0,14.1732)">
<title>Sheet.22</title>
<path d="M0 827.72 L107.72 827.72 L93.54 841.89 L-14.17 841.89 L0 827.72 Z" class="st1"/>
</g>
<g id="shape23-75" v:mID="23" v:groupContext="shape" transform="translate(-14.1732,0)">
<title>Sheet.23</title>
<path d="M0 856.06 L14.17 841.89 L14.17 657.64 L0 671.81 L0 856.06 Z" class="st1"/>
</g>
<g id="shape24-77" v:mID="24" v:groupContext="shape">
<title>Sheet.24</title>
<rect x="0" y="657.638" width="107.717" height="184.252" class="st2"/>
</g>
<g id="shape21-79" v:mID="21" v:groupContext="groupContent">
<v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/>
<v:textRect cx="53.8583" cy="749.764" width="107.72" height="184.252"/>
<text x="-88.86" y="717.96" transform="scale(-1,1)" class="st3" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>ORM<v:newlineChar/><v:newlineChar/><tspan
x="-75.55" dy="2.76em" class="st4">Hibernate<v:newlineChar/></tspan><tspan x="-63.04" dy="1.2em"
class="st4">JPA<v:newlineChar/></tspan></g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Generated by Microsoft Visio 11.0, SVG Export, v1.0 thirdparty-web.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="4.90667in"
height="3.29238in" viewBox="0 0 353.28 237.051" xml:space="preserve" color-interpolation-filters="sRGB" class="st9">
<v:documentProperties v:langID="1033" v:viewMarkup="false"/>
<style type="text/css">
<![CDATA[
.st1 {fill:#f4f7f0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st2 {fill:#000000;font-family:Arial;font-size:0.833336em}
.st3 {fill:#ecefe2;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st4 {visibility:visible}
.st5 {fill:#84877b;stroke:#84877b;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st6 {fill:#dde2cd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
.st7 {fill:#000000;font-family:Arial;font-size:0.75em}
.st8 {font-size:1em}
.st9 {fill:none;fill-rule:evenodd;font-size:12;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
<title>Page-1</title>
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
<g id="shape11-1" v:mID="11" v:groupContext="shape" transform="translate(0.24,-0.24)">
<title>Box.11</title>
<desc>Servlet Container (Tomcat / Jetty)</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="176.4" cy="118.766" width="352.8" height="236.571"/>
<rect x="0" y="0.48" width="352.8" height="236.571" class="st1"/>
<text x="101.65" y="223.77" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:newlineChar/>Servlet Container (Tomcat / Jetty)</text> </g>
<g id="shape6-4" v:mID="6" v:groupContext="shape" transform="translate(12.84,-25.9543)">
<title>Box.6</title>
<desc>Spring Core</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.22" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring Core</text> </g>
<g id="shape7-7" v:mID="7" v:groupContext="shape" transform="translate(176.64,-25.9543)">
<title>Box.7</title>
<desc>Spring DAO</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.81" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.22" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring DAO</text> </g>
<g id="shape8-10" v:mID="8" v:groupContext="shape" transform="translate(176.64,-87.6686)">
<title>Box.8</title>
<desc>Spring ORM</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="54.39" y="197.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring ORM<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape9-13" v:mID="9" v:groupContext="shape" transform="translate(12.84,-149.383)">
<title>Box.9</title>
<desc>Spring WEB</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="163.8" cy="206.194" width="327.6" height="61.7143"/>
<rect x="0" y="175.337" width="327.6" height="61.7143" class="st3"/>
<text x="136.57" y="221.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/><v:newlineChar/><v:newlineChar/>Spring WEB</text> </g>
<g id="shape10-16" v:mID="10" v:groupContext="shape" transform="translate(107.34,-188.811)">
<title>Box.10</title>
<desc>Web frontend using Struts or WebWork</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="218.194" width="144.91" height="37.7143"/>
<g id="shadow10-17" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="199.337" width="144.9" height="37.7143" class="st5"/>
</g>
<rect x="0" y="199.337" width="144.9" height="37.7143" class="st6"/>
<text x="33.43" y="215.49" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Web frontend using<v:newlineChar/><tspan
x="34.44" dy="1.2em" class="st8">Struts or WebWork</tspan></text> </g>
<g id="shape12-22" v:mID="12" v:groupContext="shape" transform="translate(12.84,-87.6686)">
<title>Box.12</title>
<desc>Spring AOP</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="81.9" cy="206.194" width="163.8" height="61.7143"/>
<rect x="0" y="175.337" width="163.8" height="61.7143" class="st3"/>
<text x="55.5" y="197.19" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Spring AOP<v:newlineChar/><v:newlineChar/></text> </g>
<g id="shape13-25" v:mID="13" v:groupContext="shape" transform="translate(107.34,-94.5257)">
<title>Box.13</title>
<desc>Transaction management Using Spring decl. trans.</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="223.337" width="144.91" height="27.4286"/>
<g id="shadow13-26" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st6"/>
<text x="21.42" y="220.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Transaction management<v:newlineChar/><tspan
x="23.43" dy="1.2em" class="st8">Using Spring decl</tspan>. trans.</text> </g>
<g id="shape5-31" v:mID="5" v:groupContext="shape" transform="translate(107.34,-67.0971)">
<title>Box</title>
<desc>Hibernate mappings Custom Hibernate DAOs</desc>
<v:userDefs>
<v:ud v:nameU="visVersion" v:val="VT0(11):26"/>
</v:userDefs>
<v:textBlock v:margins="rect(4,4,4,4)"/>
<v:textRect cx="72.45" cy="223.337" width="144.91" height="27.4286"/>
<g id="shadow5-32" v:groupContext="shadow" v:shadowOffsetX="1.8" v:shadowOffsetY="-1.8" v:shadowType="1"
transform="matrix(1,0,0,1,1.8,1.8)" class="st4">
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st5"/>
</g>
<rect x="0" y="209.623" width="144.9" height="27.4286" class="st6"/>
<text x="32.18" y="220.64" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hibernate mappings<v:newlineChar/><tspan
x="22.93" dy="1.2em" class="st8">Custom Hibernate DAOs</tspan></text> </g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1,19 @@
= Spring Framework Reference Documentation
The Spring Framework team and contributors https://github.com/spring-projects/spring-framework/graphs/contributors
:doc-root: https://docs.spring.io
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
<<overview.adoc#spring-introduction,Overview>>
<<core.adoc#spring-core,Core>>
<<testing.adoc#testing,Testing>>
<<data-access.adoc#spring-data-tier,Data Access>>
<<web.adoc#spring-web,Web>>
<<integration.adoc#spring-integration,Integration>>
<<appendix.adoc#spring-appendices,Appendix>>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,865 @@
[[spring-introduction]]
= Overview of Spring Framework
:doc-root: https://docs.spring.io
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
[partintro]
--
The Spring Framework is a lightweight solution and a potential one-stop-shop for
building your enterprise-ready applications. However, Spring is modular, allowing you to
use only those parts that you need, without having to bring in the rest. You can use the
IoC container, with any web framework on top, but you can also use only the
<<orm-hibernate,Hibernate integration code>> or the <<jdbc-introduction,JDBC abstraction
layer>>. The Spring Framework supports declarative transaction management, remote access
to your logic through RMI or web services, and various options for persisting your data.
It offers a full-featured <<mvc-introduction,MVC framework>>, and enables you to
integrate <<aop-introduction,AOP>> transparently into your software.
Spring is designed to be non-intrusive, meaning that your domain logic code generally
has no dependencies on the framework itself. In your integration layer (such as the data
access layer), some dependencies on the data access technology and the Spring libraries
will exist. However, it should be easy to isolate these dependencies from the rest of
your code base.
This document is a reference guide to Spring Framework features. If you have any
requests, comments, or questions on this document, please post them on the
https://groups.google.com/forum/#!forum/spring-framework-contrib[user mailing
list]. Questions on the Framework itself should be asked on StackOverflow
(see https://spring.io/questions[]).
--
[[overview-getting-started-with-spring]]
== Getting Started with Spring
This reference guide provides detailed information about the Spring Framework.
It provides comprehensive documentation for all features, as well as some background
about the underlying concepts (such as __"Dependency Injection"__) that Spring has
embraced.
If you are just getting started with Spring, you may want to begin using the Spring Framework
by creating a http://projects.spring.io/spring-boot/[Spring Boot] based application.
Spring Boot provides a quick (and opinionated) way to create a production-ready Spring based
application. It is based on the Spring Framework, favors convention over configuration, and is
designed to get you up and running as quickly as possible.
You can use http://start.spring.io[start.spring.io] to generate a basic project or follow
one of the https://spring.io/guides["Getting Started" guides] like the
https://spring.io/guides/gs/rest-service/[Getting Started Building a RESTful Web Service]
one. As well as being easier to digest, these guides are very __task focused__, and most of
them are based on Spring Boot. They also cover other projects from the Spring portfolio
that you might want to consider when solving a particular problem.
[[overview]]
== Introduction to the Spring Framework
The Spring Framework is a Java platform that provides comprehensive infrastructure support
for developing Java applications. Spring handles the infrastructure so you can focus on
your application.
Spring enables you to build applications from "plain old Java objects" (POJOs) and to
apply enterprise services non-invasively to POJOs. This capability applies to the Java
SE programming model and to full and partial Java EE.
Examples of how you, as an application developer, can benefit from the Spring platform:
* Make a Java method execute in a database transaction without having to deal with
transaction APIs.
* Make a local Java method a remote procedure without having to deal with remote APIs.
* Make a local Java method a management operation without having to deal with JMX APIs.
* Make a local Java method a message handler without having to deal with JMS APIs.
[[overview-dependency-injection]]
=== Dependency Injection and Inversion of Control
A Java application -- a loose term that runs the gamut from constrained, embedded
applications to n-tier, server-side enterprise applications -- typically consists of
objects that collaborate to form the application proper. Thus the objects in an
application have __dependencies__ on each other.
Although the Java platform provides a wealth of application development functionality,
it lacks the means to organize the basic building blocks into a coherent whole, leaving
that task to architects and developers. Although you can use design patterns such
as __Factory__, __Abstract Factory__, __Builder__, __Decorator__, and __Service Locator__
to compose the various classes and object instances that make up an application,
these patterns are simply that: best practices given a name, with a description
of what the pattern does, where to apply it, the problems it addresses, and so forth.
Patterns are formalized best practices that __you must implement yourself__ in your
application.
The Spring Framework __Inversion of Control__ (IoC) component addresses this concern by
providing a formalized means of composing disparate components into a fully working
application ready for use. The Spring Framework codifies formalized design patterns as
first-class objects that you can integrate into your own application(s). Numerous
organizations and institutions use the Spring Framework in this manner to engineer
robust, __maintainable__ applications.
[[background-ioc]]
.Background
****
"__The question is, what aspect of control are [they] inverting?__" Martin Fowler posed
this question about Inversion of Control (IoC)
http://martinfowler.com/articles/injection.html[on his site] in 2004. Fowler suggested
renaming the principle to make it more self-explanatory and came up with __Dependency
Injection__.
****
[[overview-modules]]
=== Modules
The Spring Framework consists of features organized into about 20 modules. These modules
are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented
Programming), Instrumentation, Messaging, and Test, as shown in the following diagram.
.Overview of the Spring Framework
image::images/spring-overview.png[]
The following sections list the available modules for each feature along with their
artifact names and the topics they cover. Artifact names correlate to _artifact IDs_ used
in <<dependency-management,Dependency Management tools>>.
[[overview-core-container]]
==== Core Container
The <<beans-introduction,__Core Container__>> consists of the `spring-core`,
`spring-beans`, `spring-context`, `spring-context-support`, and `spring-expression`
(Spring Expression Language) modules.
The `spring-core` and `spring-beans` modules <<beans-introduction,provide the fundamental
parts of the framework>>, including the IoC and Dependency Injection features. The
`BeanFactory` is a sophisticated implementation of the factory pattern. It removes the
need for programmatic singletons and allows you to decouple the configuration and
specification of dependencies from your actual program logic.
The <<context-introduction,__Context__>> (`spring-context`) module builds on the solid
base provided by the <<beans-introduction,__Core and Beans__>> modules: it is a means to
access objects in a framework-style manner that is similar to a JNDI registry. The
Context module inherits its features from the Beans module and adds support for
internationalization (using, for example, resource bundles), event propagation, resource
loading, and the transparent creation of contexts by, for example, a Servlet container.
The Context module also supports Java EE features such as EJB, JMX, and basic remoting.
The `ApplicationContext` interface is the focal point of the Context module.
`spring-context-support` provides support for integrating common third-party libraries
into a Spring application context, in particular for caching (EhCache, JCache) and
scheduling (CommonJ, Quartz).
The `spring-expression` module provides a powerful <<expressions,__Expression
Language__>> for querying and manipulating an object graph at runtime. It is an extension
of the unified expression language (unified EL) as specified in the JSP 2.1
specification. The language supports setting and getting property values, property
assignment, method invocation, accessing the content of arrays, collections and indexers,
logical and arithmetic operators, named variables, and retrieval of objects by name from
Spring's IoC container. It also supports list projection and selection as well as common
list aggregations.
[[overview-aop-instrumentation]]
==== AOP and Instrumentation
The `spring-aop` module provides an <<aop-introduction,__AOP__>> Alliance-compliant
aspect-oriented programming implementation allowing you to define, for example,
method interceptors and pointcuts to cleanly decouple code that implements functionality
that should be separated. Using source-level metadata functionality, you can also
incorporate behavioral information into your code, in a manner similar to that of .NET
attributes.
The separate `spring-aspects` module provides integration with AspectJ.
The `spring-instrument` module provides class instrumentation support and classloader
implementations to be used in certain application servers. The `spring-instrument-tomcat`
module contains Spring's instrumentation agent for Tomcat.
[[overview-messaging]]
==== Messaging
Spring Framework 4 includes a `spring-messaging` module with key abstractions from the
_Spring Integration_ project such as `Message`, `MessageChannel`, `MessageHandler`, and
others to serve as a foundation for messaging-based applications. The module also
includes a set of annotations for mapping messages to methods, similar to the Spring MVC
annotation based programming model.
[[overview-data-access]]
==== Data Access/Integration
The __Data Access/Integration__ layer consists of the JDBC, ORM, OXM, JMS, and
Transaction modules.
The `spring-jdbc` module provides a <<jdbc-introduction,JDBC>>-abstraction layer that
removes the need to do tedious JDBC coding and parsing of database-vendor specific error
codes.
The `spring-tx` module supports <<transaction,programmatic and declarative transaction>>
management for classes that implement special interfaces and for __all your POJOs (Plain
Old Java Objects)__.
The `spring-orm` module provides integration layers for popular
<<orm-introduction,object-relational mapping>> APIs, including <<orm-jpa,JPA>> and
<<orm-hibernate,Hibernate>>. Using the `spring-orm` module you can use these
O/R-mapping frameworks in combination with all of the other features Spring offers,
such as the simple declarative transaction management feature mentioned previously.
The `spring-oxm` module provides an abstraction layer that supports <<oxm,Object/XML
mapping>> implementations such as JAXB, Castor, JiBX and XStream.
The `spring-jms` module (<<jms,Java Messaging Service>>) contains features for producing and
consuming messages. Since Spring Framework 4.1, it provides integration with the
`spring-messaging` module.
[[overview-web]]
==== Web
The __Web__ layer consists of the `spring-web`, `spring-webmvc` and `spring-websocket`
modules.
The `spring-web` module provides basic web-oriented integration features such as
multipart file upload functionality and the initialization of the IoC container using
Servlet listeners and a web-oriented application context. It also contains an HTTP client
and the web-related parts of Spring's remoting support.
The `spring-webmvc` module (also known as the __Web-Servlet__ module) contains Spring's
model-view-controller (<<mvc-introduction,__MVC__>>) and REST Web Services implementation
for web applications. Spring's MVC framework provides a clean separation between domain
model code and web forms and integrates with all of the other features of the Spring
Framework.
[[overview-testing]]
==== Test
The `spring-test` module supports the <<unit-testing,unit testing>> and
<<integration-testing,integration testing>> of Spring components with JUnit or TestNG. It
provides consistent <<testcontext-ctx-management,loading>> of Spring
``ApplicationContext``s and <<testcontext-ctx-management-caching,caching>> of those
contexts. It also provides <<mock-objects,mock objects>> that you can use to test your
code in isolation.
[[overview-usagescenarios]]
=== Usage scenarios
The building blocks described previously make Spring a logical choice in many scenarios,
from embedded applications that run on resource-constrained devices to full-fledged
enterprise applications that use Spring's transaction management functionality and web
framework integration.
.Typical full-fledged Spring web application
image::images/overview-full.png[]
Spring's <<transaction-declarative,declarative transaction management features>> make
the web application fully transactional, just as it would be if you used EJB
container-managed transactions. All your custom business logic can be implemented with
simple POJOs and managed by Spring's IoC container. Additional services include support
for sending email and validation that is independent of the web layer, which lets you
choose where to execute validation rules. Spring's ORM support is integrated with JPA
and Hibernate; for example, when using Hibernate, you can continue to use your existing
mapping files and standard Hibernate `SessionFactory` configuration. Form controllers
seamlessly integrate the web-layer with the domain model, removing the need for
`ActionForms` or other classes that transform HTTP parameters to values for your
domain model.
.Spring middle-tier using a third-party web framework
image::images/overview-thirdparty-web.png[]
Sometimes circumstances do not allow you to completely switch to a different framework.
The Spring Framework does __not__ force you to use everything within it; it is not an
__all-or-nothing__ solution. Existing front-ends built with Struts, Tapestry, JSF
or other UI frameworks can be integrated with a Spring-based middle-tier, which allows
you to use Spring transaction features. You simply need to wire up your business logic
using an `ApplicationContext` and use a `WebApplicationContext` to integrate your web
layer.
.Remoting usage scenario
image::images/overview-remoting.png[]
When you need to access existing code through web services, you can use Spring's
`Hessian-`, `Rmi-` or `HttpInvokerProxyFactoryBean` classes. Enabling remote access to
existing applications is not difficult.
.EJBs - Wrapping existing POJOs
image::images/overview-ejb.png[]
The Spring Framework also provides an <<ejb,access and abstraction layer>> for
Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in
stateless session beans for use in scalable, fail-safe web applications that might need
declarative security.
[[dependency-management]]
==== Dependency Management and Naming Conventions
Dependency management and dependency injection are different things. To get those nice
features of Spring into your application (like dependency injection) you need to
assemble all the libraries needed (jar files) and get them onto your classpath at
runtime, and possibly at compile time. These dependencies are not virtual components
that are injected, but physical resources in a file system (typically). The process of
dependency management involves locating those resources, storing them and adding them to
classpaths. Dependencies can be direct (e.g. my application depends on Spring at
runtime), or indirect (e.g. my application depends on `commons-dbcp` which depends on
`commons-pool`). The indirect dependencies are also known as "transitive" and it is
those dependencies that are hardest to identify and manage.
If you are going to use Spring you need to get a copy of the jar libraries that comprise
the pieces of Spring that you need. To make this easier Spring is packaged as a set of
modules that separate the dependencies as much as possible, so for example if you don't
want to write a web application you don't need the spring-web modules. To refer to
Spring library modules in this guide we use a shorthand naming convention `spring-{asterisk}` or
`spring-{asterisk}.jar,` where `{asterisk}` represents the short name for the module
(e.g. `spring-core`, `spring-webmvc`, `spring-jms`, etc.). The actual jar file name that
you use is normally the module name concatenated with the version number
(e.g. __spring-core-{spring-version}.jar__).
Each release of the Spring Framework will publish artifacts to the following places:
* Maven Central, which is the default repository that Maven queries, and does not
require any special configuration to use. Many of the common libraries that Spring
depends on also are available from Maven Central and a large section of the Spring
community uses Maven for dependency management, so this is convenient for them. The
names of the jars here are in the form `spring-*-<version>.jar` and the Maven groupId
is `org.springframework`.
* In a public Maven repository hosted specifically for Spring. In addition to the final
GA releases, this repository also hosts development snapshots and milestones. The jar
file names are in the same form as Maven Central, so this is a useful place to get
development versions of Spring to use with other libraries deployed in Maven Central.
This repository also contains a bundle distribution zip file that contains all Spring
jars bundled together for easy download.
So the first thing you need to decide is how to manage your dependencies: we generally
recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do
it manually by downloading all the jars yourself.
You will find bellow the list of Spring artifacts. For a more complete description of each
modules, see <<overview-modules>>.
.Spring Framework Artifacts
|===
|GroupId |ArtifactId |Description
|org.springframework
|spring-aop
|Proxy-based AOP support
|org.springframework
|spring-aspects
|AspectJ based aspects
|org.springframework
|spring-beans
|Beans support, including Groovy
|org.springframework
|spring-context
|Application context runtime, including scheduling and remoting abstractions
|org.springframework
|spring-context-support
|Support classes for integrating common third-party libraries into a Spring application context
|org.springframework
|spring-core
|Core utilities, used by many other Spring modules
|org.springframework
|spring-expression
|Spring Expression Language (SpEL)
|org.springframework
|spring-instrument
|Instrumentation agent for JVM bootstrapping
|org.springframework
|spring-instrument-tomcat
|Instrumentation agent for Tomcat
|org.springframework
|spring-jdbc
|JDBC support package, including DataSource setup and JDBC access support
|org.springframework
|spring-jms
|JMS support package, including helper classes to send and receive JMS messages
|org.springframework
|spring-messaging
|Support for messaging architectures and protocols
|org.springframework
|spring-orm
|Object/Relational Mapping, including JPA and Hibernate support
|org.springframework
|spring-oxm
|Object/XML Mapping
|org.springframework
|spring-test
|Support for unit testing and integration testing Spring components
|org.springframework
|spring-tx
|Transaction infrastructure, including DAO support and JCA integration
|org.springframework
|spring-web
|Web support packages, including client and web remoting
|org.springframework
|spring-webmvc
|REST Web Services and model-view-controller implementation for web applications
|org.springframework
|spring-websocket
|WebSocket and SockJS implementations, including STOMP support
|===
[[overview-spring-dependencies]]
===== Spring Dependencies and Depending on Spring
Although Spring provides integration and support for a huge range of enterprise and
other external tools, it intentionally keeps its mandatory dependencies to an absolute
minimum: you shouldn't have to locate and download (even automatically) a large number
of jar libraries in order to use Spring for simple use cases. For basic dependency
injection there is only one mandatory external dependency, and that is for logging (see
below for a more detailed description of logging options).
Next we outline the basic steps needed to configure an application that depends on
Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if
anything is unclear, refer to the documentation of your dependency management system, or
look at some sample code - Spring itself uses Gradle to manage dependencies when it is
building, and our samples mostly use Gradle or Maven.
[[overview-maven-dependency-management]]
===== Maven Dependency Management
If you are using http://maven.apache.org/[Maven] for dependency management you don't even
need to supply the logging dependency explicitly. For example, to create an application
context and use dependency injection to configure an application, your Maven dependencies
will look like this:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>{spring-version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
----
That's it. Note the scope can be declared as runtime if you don't need to compile
against Spring APIs, which is typically the case for basic dependency injection use
cases.
The example above works with the Maven Central repository. To use the Spring Maven
repository (e.g. for milestones or developer snapshots), you need to specify the
repository location in your Maven configuration. For full releases:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<repositories>
<repository>
<id>io.spring.repo.maven.release</id>
<url>http://repo.spring.io/release/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
----
For milestones:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<repositories>
<repository>
<id>io.spring.repo.maven.milestone</id>
<url>http://repo.spring.io/milestone/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
----
And for snapshots:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<repositories>
<repository>
<id>io.spring.repo.maven.snapshot</id>
<url>http://repo.spring.io/snapshot/</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
----
[[overview-maven-bom]]
===== Maven "Bill Of Materials" Dependency =====
It is possible to accidentally mix different versions of Spring JARs when using Maven.
For example, you may find that a third-party library, or another Spring project,
pulls in a transitive dependency to an older release. If you forget to explicitly declare
a direct dependency yourself, all sorts of unexpected issues can arise.
To overcome such problems Maven supports the concept of a "bill of materials" (BOM)
dependency. You can import the `spring-framework-bom` in your `dependencyManagement`
section to ensure that all spring dependencies (both direct and transitive) are at
the same version.
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>{spring-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
----
An added benefit of using the BOM is that you no longer need to specify the `<version>`
attribute when depending on Spring Framework artifacts:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
----
[[overview-gradle-dependency-management]]
===== Gradle Dependency Management
To use the Spring repository with the http://www.gradle.org/[Gradle] build system,
include the appropriate URL in the `repositories` section:
[source,groovy,indent=0]
[subs="verbatim,quotes"]
----
repositories {
mavenCentral()
// and optionally...
maven { url "http://repo.spring.io/release" }
}
----
You can change the `repositories` URL from `/release` to `/milestone` or `/snapshot` as
appropriate. Once a repository has been configured, you can declare dependencies in the
usual Gradle way:
[source,groovy,indent=0]
[subs="verbatim,quotes,attributes"]
----
dependencies {
compile("org.springframework:spring-context:{spring-version}")
testCompile("org.springframework:spring-test:{spring-version}")
}
----
[[overview-ivy-dependency-management]]
===== Ivy Dependency Management
If you prefer to use http://ant.apache.org/ivy[Ivy] to manage dependencies then there
are similar configuration options.
To configure Ivy to point to the Spring repository add the following resolver to your
`ivysettings.xml`:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<resolvers>
<ibiblio name="io.spring.repo.maven.release"
m2compatible="true"
root="http://repo.spring.io/release/"/>
</resolvers>
----
You can change the `root` URL from `/release/` to `/milestone/` or `/snapshot/` as
appropriate.
Once configured, you can add dependencies in the usual way. For example (in `ivy.xml`):
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependency org="org.springframework"
name="spring-core" rev="{spring-version}" conf="compile->runtime"/>
----
[[overview-distribution-zip]]
===== Distribution Zip Files
Although using a build system that supports dependency management is the recommended
way to obtain the Spring Framework, it is still possible to download a distribution
zip file.
Distribution zips are published to the Spring Maven Repository (this is just for our
convenience, you don't need Maven or any other build system in order to download them).
To download a distribution zip open a web browser to
http://repo.spring.io/release/org/springframework/spring and select the appropriate
subfolder for the version that you want. Distribution files end `-dist.zip`, for example
+spring-framework-{spring-version}-RELEASE-dist.zip+. Distributions are also published
for http://repo.spring.io/milestone/org/springframework/spring[milestones] and
http://repo.spring.io/snapshot/org/springframework/spring[snapshots].
[[overview-logging]]
==== Logging
Logging is a very important dependency for Spring because __a)__ it is the only mandatory
external dependency, __b)__ everyone likes to see some output from the tools they are
using, and __c)__ Spring integrates with lots of other tools all of which have also made
a choice of logging dependency. One of the goals of an application developer is often to
have unified logging configured in a central place for the whole application, including
all external components. This is more difficult than it might have been since there are so
many choices of logging framework.
The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We
compile against JCL and we also make JCL `Log` objects visible for classes that extend
the Spring Framework. It's important to users that all versions of Spring use the same
logging library: migration is easy because backwards compatibility is preserved even
with applications that extend Spring. The way we do this is to make one of the modules
in Spring depend explicitly on `commons-logging` (the canonical implementation of JCL),
and then make all the other modules depend on that at compile time. If you are using
Maven for example, and wondering where you picked up the dependency on
`commons-logging`, then it is from Spring and specifically from the central module
called `spring-core`.
The nice thing about `commons-logging` is that you don't need anything else to make your
application work. It has a runtime discovery algorithm that looks for other logging
frameworks in well known places on the classpath and uses one that it thinks is
appropriate (or you can tell it which one if you need to). If nothing else is available
you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short).
You should find that your Spring application works and logs happily to the console out
of the box in most situations, and that's important.
[[overview-not-using-commons-logging]]
===== Not Using Commons Logging
Unfortunately, the runtime discovery algorithm in `commons-logging`, while convenient
for the end-user, is problematic. If we could turn back the clock and start Spring now
as a new project it would use a different logging dependency. The first choice would
probably be the Simple Logging Facade for Java ( http://www.slf4j.org[SLF4J]), which is
also used by a lot of other tools that people use with Spring inside their applications.
There are basically two ways to switch off `commons-logging`:
. Exclude the dependency from the `spring-core` module (as it is the only module that
explicitly depends on `commons-logging`)
. Depend on a special `commons-logging` dependency that replaces the library with
an empty jar (more details can be found in the
http://slf4j.org/faq.html#excludingJCL[SLF4J FAQ])
To exclude commons-logging, add the following to your `dependencyManagement` section:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>{spring-version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
----
Now this application is probably broken because there is no implementation of the JCL
API on the classpath, so to fix it a new one has to be provided. In the next section we
show you how to provide an alternative implementation of JCL using SLF4J as an example.
[[overview-logging-slf4j]]
===== Using SLF4J
SLF4J is a cleaner dependency and more efficient at runtime than `commons-logging`
because it uses compile-time bindings instead of runtime discovery of the other logging
frameworks it integrates. This also means that you have to be more explicit about what
you want to happen at runtime, and declare it or configure it accordingly. SLF4J
provides bindings to many common logging frameworks, so you can usually choose one that
you already use, and bind to that for configuration and management.
SLF4J provides bindings to many common logging frameworks, including JCL, and it also
does the reverse: bridges between other logging frameworks and itself. So to use SLF4J
with Spring you need to replace the `commons-logging` dependency with the SLF4J-JCL
bridge. Once you have done that then logging calls from within Spring will be translated
into logging calls to the SLF4J API, so if other libraries in your application use that
API, then you have a single place to configure and manage logging.
A common choice might be to bridge Spring to SLF4J, and then provide explicit binding
from SLF4J to Log4j. You need to supply several dependencies (and exclude the existing
`commons-logging`): the bridge, the SLF4J implementation for Log4j, and the Log4j
implementation itself. In Maven you would do that like this:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>{spring-version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
----
That might seem like a lot of dependencies just to get some logging. Well it is, but it
__is__ optional, and it should behave better than the vanilla `commons-logging` with
respect to classloader issues, notably if you are in a strict container like an OSGi
platform. Allegedly there is also a performance benefit because the bindings are at
compile-time not runtime.
A more common choice amongst SLF4J users, which uses fewer steps and generates fewer
dependencies, is to bind directly to http://logback.qos.ch[Logback]. This removes the
extra binding step because Logback implements SLF4J directly, so you only need to depend
on two libraries not four ( `jcl-over-slf4j` and `logback`). If you do that you might
also need to exclude the slf4j-api dependency from other external dependencies (not
Spring), because you only want one version of that API on the classpath.
[[overview-logging-log4j]]
===== Using Log4j
NOTE: Log4j 1.x is EOL and the following applies to Log4j 2
Many people use http://logging.apache.org/log4j[Log4j] as a logging framework for
configuration and management purposes. It's efficient and well-established, and in fact
it's what we use at runtime when we build and test Spring. Spring also provides some
utilities for configuring and initializing Log4j, so it has an optional compile-time
dependency on Log4j in some modules.
To use Log4j with JCL, all you need to do is put Log4j on the classpath and provide
it with a configuration file (`log4j2.xml`, `log4j2.properties`, or other
http://logging.apache.org/log4j/2.x/manual/configuration.html[supported configuration
formats]). For Maven users, the minimal dependencies needed are:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
----
If you also wish to use SLF4J, the following dependencies are also needed:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
----
Here is an example `log4j2.xml` for logging to the console:
[source,xml,indent=0]
[subs="verbatim,quotes,attributes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.springframework.beans.factory" level="DEBUG"/>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
----
[[overview-native-jcl]]
====== Runtime Containers with Native JCL
Many people run their Spring applications in a container that itself provides an
implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This
often causes problems, and unfortunately there is no silver bullet solution; simply
excluding `commons-logging` from your application is not enough in most situations.
To be clear about this: the problems reported are usually not with JCL per se, or even
with `commons-logging`: rather they are to do with binding `commons-logging` to another
framework (often Log4j). This can fail because `commons-logging` changed the way they do
the runtime discovery in between the older versions (1.0) found in some containers and
the modern versions that most people use now (1.1). Spring does not use any unusual
parts of the JCL API, so nothing breaks there, but as soon as Spring or your application
tries to do any logging you can find that the bindings to Log4j are not working.
In such cases with WAS the easiest thing to do is to invert the class loader hierarchy
(IBM calls it "parent last") so that the application controls the JCL dependency, not
the container. That option isn't always open, but there are plenty of other suggestions
in the public domain for alternative approaches, and your mileage may vary depending on
the exact version and feature set of the container.

View File

@@ -0,0 +1,691 @@
@import url(https://fonts.googleapis.com/css?family=Varela+Round|Montserrat:400,700);
/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
/* ========================================================================== HTML5 display definitions ========================================================================== */
/** Correct `block` display not defined in IE 8/9. */
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
/** Correct `inline-block` display not defined in IE 8/9. */
audio, canvas, video { display: inline-block; }
/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
audio:not([controls]) { display: none; height: 0; }
/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
[hidden], template { display: none; }
script { display: none !important; }
/* ========================================================================== Base ========================================================================== */
/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
/** Remove default margin. */
body { margin: 0; }
/* ========================================================================== Links ========================================================================== */
/** Remove the gray background color from active links in IE 10. */
a { background: transparent; }
/** Address `outline` inconsistency between Chrome and other browsers. */
a:focus { outline: thin dotted; }
/** Improve readability when focused and also mouse hovered in all browsers. */
a:active, a:hover { outline: 0; }
/* ========================================================================== Typography ========================================================================== */
/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
h1 { font-size: 2em; margin: 0.67em 0; }
/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
abbr[title] { border-bottom: 1px dotted; }
/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
b, strong { font-weight: bold; }
/** Address styling not present in Safari 5 and Chrome. */
dfn { font-style: italic; }
/** Address differences between Firefox and other browsers. */
hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
/** Address styling not present in IE 8/9. */
mark { background: #ff0; color: #000; }
/** Correct font family set oddly in Safari 5 and Chrome. */
code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
/** Improve readability of pre-formatted text in all browsers. */
pre { white-space: pre-wrap; }
/** Set consistent quote types. */
q { quotes: "\201C" "\201D" "\2018" "\2019"; }
/** Address inconsistent and variable font size in all browsers. */
small { font-size: 80%; }
/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }
/* ========================================================================== Embedded content ========================================================================== */
/** Remove border when inside `a` element in IE 8/9. */
img { border: 0; }
/** Correct overflow displayed oddly in IE 9. */
svg:not(:root) { overflow: hidden; }
/* ========================================================================== Figures ========================================================================== */
/** Address margin not present in IE 8/9 and Safari 5. */
figure { margin: 0; }
/* ========================================================================== Forms ========================================================================== */
/** Define consistent border, margin, and padding. */
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
button, input { line-height: normal; }
/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
button, select { text-transform: none; }
/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
/** Re-set default cursor for disabled elements. */
button[disabled], html input[disabled] { cursor: default; }
/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
/** Remove inner padding and border in Firefox 4+. */
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
/* ========================================================================== Tables ========================================================================== */
/** Remove most spacing between table cells. */
table { border-collapse: collapse; border-spacing: 0; }
meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
html, body { font-size: 100%; }
body { background: white; color: #34302d; padding: 0; margin: 0; font-family: "Varela Round", sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
a:hover { cursor: pointer; }
img, object, embed { max-width: 100%; height: auto; }
object, embed { height: 100%; }
img { -ms-interpolation-mode: bicubic; }
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
.left { float: left !important; }
.right { float: right !important; }
.text-left { text-align: left !important; }
.text-right { text-align: right !important; }
.text-center { text-align: center !important; }
.text-justify { text-align: justify !important; }
.hide { display: none; }
.antialiased { -webkit-font-smoothing: antialiased; }
img { display: inline-block; vertical-align: middle; }
textarea { height: auto; min-height: 50px; }
select { width: 100%; }
object, svg { display: inline-block; vertical-align: middle; }
.center { margin-left: auto; margin-right: auto; }
.spread { width: 100%; }
p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.45; color: #0b0a0a; font-weight: normal; margin-top: 0; margin-bottom: 0.25em; }
/* Typography resets */
div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
/* Default Link Styles */
a { color: #548e2e; text-decoration: underline; line-height: inherit; }
a:hover, a:focus { color: #487a28; }
a img { border: none; }
/* Default paragraph styles */
p { font-family: inherit; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; text-rendering: optimizeLegibility; }
p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
/* Default header styles */
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Montserrat, sans-serif; font-weight: 400; font-style: normal; color: #34302d; text-rendering: optimizeLegibility; margin-top: 1em; margin-bottom: 0.5em; line-height: 1.0125em; }
h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #867c74; line-height: 0; }
h1 { font-size: 2.125em; }
h2 { font-size: 1.6875em; }
h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
h4 { font-size: 1.125em; }
h5 { font-size: 1.125em; }
h6 { font-size: 1em; }
hr { border: solid #ddddd8; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
/* Helpful Typography Defaults */
em, i { font-style: italic; line-height: inherit; }
strong, b { font-weight: bold; line-height: inherit; }
small { font-size: 60%; line-height: inherit; }
code { font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-weight: normal; color: rgba(0, 0, 0, 0.9); }
/* Lists */
ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; list-style-position: outside; font-family: inherit; }
ul, ol { margin-left: 1.5em; }
ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
/* Unordered Lists */
ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
ul.square { list-style-type: square; }
ul.circle { list-style-type: circle; }
ul.disc { list-style-type: disc; }
ul.no-bullet { list-style: none; }
/* Ordered Lists */
ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
/* Definition Lists */
dl dt { margin-bottom: 0.3125em; font-weight: bold; }
dl dd { margin-bottom: 1.25em; }
/* Abbreviations */
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #34302d; border-bottom: 1px dotted #dddddd; cursor: help; }
abbr { text-transform: none; }
/* Blockquotes */
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
blockquote cite { display: block; font-size: 0.9375em; color: rgba(0, 0, 0, 0.6); }
blockquote cite:before { content: "\2014 \0020"; }
blockquote cite a, blockquote cite a:visited { color: rgba(0, 0, 0, 0.6); }
blockquote, blockquote p { line-height: 1.6; color: rgba(0, 0, 0, 0.85); }
/* Microformats */
.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
.vcard li { margin: 0; display: block; }
.vcard .fn { font-weight: bold; font-size: 0.9375em; }
.vevent .summary { font-weight: bold; }
.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.2; }
h1 { font-size: 2.75em; }
h2 { font-size: 2.3125em; }
h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
h4 { font-size: 1.4375em; } }
/* Tables */
table { background: white; margin-bottom: 1.25em; border: solid 1px #dedede; }
table thead, table tfoot { background: #f7f8f7; font-weight: bold; }
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #34302d; text-align: left; }
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #34302d; }
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f8f8f7; }
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.2; word-spacing: -0.05em; }
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
.clearfix:after, .float-group:after { clear: both; }
*:not(pre) > code { font-size: 0.9375em; font-style: normal !important; letter-spacing: 0; padding: 0.1em 0.5ex; word-spacing: -0.15em; background-color: #f7f7f8; -webkit-border-radius: 4px; border-radius: 4px; line-height: 1.45; text-rendering: optimizeSpeed; word-wrap: break-word; }
*:not(pre) > code.nobreak { word-wrap: normal; }
*:not(pre) > code.nowrap { white-space: nowrap; }
pre, pre > code { line-height: 1.45; color: rgba(0, 0, 0, 0.9); font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-weight: normal; text-rendering: optimizeSpeed; }
em em { font-style: normal; }
strong strong { font-weight: normal; }
.keyseq { color: #6b625c; }
kbd { font-family: Monaco, Menlo, Consolas, "Courier New", monospace; display: inline-block; color: #34302d; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
.keyseq kbd:first-child { margin-left: 0; }
.keyseq kbd:last-child { margin-right: 0; }
.menuseq, .menu { color: #191715; }
b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
b.button:before { content: "["; padding: 0 3px 0 2px; }
b.button:after { content: "]"; padding: 0 2px 0 3px; }
p a > code:hover { color: rgba(0, 0, 0, 0.9); }
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
#content { margin-top: 1.25em; }
#content:before { content: none; }
#header > h1:first-child { color: rgba(0, 0, 0, 0.85); margin-top: 2.25rem; margin-bottom: 0; }
#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #ddddd8; }
#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #ddddd8; padding-bottom: 8px; }
#header .details { border-bottom: 1px solid #ddddd8; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: rgba(0, 0, 0, 0.6); display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
#header .details span:first-child { margin-left: -0.125em; }
#header .details span.email a { color: rgba(0, 0, 0, 0.85); }
#header .details br { display: none; }
#header .details br + span:before { content: "\00a0\2013\00a0"; }
#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: rgba(0, 0, 0, 0.85); }
#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
#header #revnumber { text-transform: capitalize; }
#header #revnumber:after { content: "\00a0"; }
#content > h1:first-child:not([class]) { color: rgba(0, 0, 0, 0.85); border-bottom: 1px solid #ddddd8; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
#toc { border-bottom: 1px solid #efefed; padding-bottom: 0.5em; }
#toc > ul { margin-left: 0.125em; }
#toc ul.sectlevel0 > li > a { font-style: italic; }
#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
#toc ul { font-family: Montserrat, sans-serif; list-style-type: none; }
#toc li { line-height: 1.3334; margin-top: 0.3334em; }
#toc a { text-decoration: none; }
#toc a:active { text-decoration: underline; }
#toctitle { color: #0b0a0a; font-size: 1.2em; }
@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
body.toc2 { padding-left: 15em; padding-right: 0; }
#toc.toc2 { margin-top: 0 !important; background-color: #f1f1f1; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #efefed; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
#toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
#toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
#toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #efefed; left: auto; right: 0; } }
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
#toc.toc2 { width: 20em; }
#toc.toc2 #toctitle { font-size: 1.375em; }
#toc.toc2 > ul { font-size: 0.95em; }
#toc.toc2 ul ul { padding-left: 1.25em; }
body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
#content #toc { border-style: solid; border-width: 1px; border-color: #d7d7d7; margin-bottom: 1.25em; padding: 1.25em; background: #f1f1f1; -webkit-border-radius: 4px; border-radius: 4px; }
#content #toc > :first-child { margin-top: 0; }
#content #toc > :last-child { margin-bottom: 0; }
#footer { max-width: 100%; background-color: #34302d; padding: 1.25em; }
#footer-text { color: #cbcfd2; line-height: 1.44; }
.sect1 { padding-bottom: 0.625em; }
@media only screen and (min-width: 768px) { .sect1 { padding-bottom: 1.25em; } }
.sect1 + .sect1 { border-top: 1px solid #efefed; }
#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #34302d; text-decoration: none; }
#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #262321; }
.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; font-family: "Varela Round", sans-serif; font-size: 1rem; font-style: italic; }
table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: rgba(0, 0, 0, 0.85); }
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
.admonitionblock > table td.icon { text-align: center; width: 80px; }
.admonitionblock > table td.icon img { max-width: initial; }
.admonitionblock > table td.icon .title { font-weight: bold; font-family: Montserrat, sans-serif; text-transform: uppercase; }
.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #ddddd8; color: rgba(0, 0, 0, 0.6); }
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
.exampleblock > .content > :first-child { margin-top: 0; }
.exampleblock > .content > :last-child { margin-bottom: 0; }
.sidebarblock { border-style: solid; border-width: 1px; border-color: #d7d7d7; margin-bottom: 1.25em; padding: 1.25em; background: #f1f1f1; -webkit-border-radius: 4px; border-radius: 4px; }
.sidebarblock > :first-child { margin-top: 0; }
.sidebarblock > :last-child { margin-bottom: 0; }
.sidebarblock > .content > .title { color: #0b0a0a; margin-top: 0; text-align: center; }
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: whitesmoke; }
.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px solid #dddddd; -webkit-border-radius: 4px; border-radius: 4px; word-wrap: break-word; padding: 1em; font-size: 0.8125em; }
.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
.literalblock.output pre { color: whitesmoke; background-color: rgba(0, 0, 0, 0.9); }
.listingblock pre.highlightjs { padding: 0; }
.listingblock pre.highlightjs > code { padding: 1em; -webkit-border-radius: 4px; border-radius: 4px; }
.listingblock > .content { position: relative; }
.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
.listingblock:hover code[data-lang]:before { display: block; }
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.45; }
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #ddddd8; }
pre.pygments .lineno { display: inline-block; margin-right: .25em; }
table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
.quoteblock { margin: 0 1em 1.25em 1.5em; display: table; }
.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
.quoteblock blockquote, .quoteblock blockquote p { color: rgba(0, 0, 0, 0.85); font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: #0b0a0a; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid rgba(0, 0, 0, 0.6); }
.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
.quoteblock .quoteblock blockquote:before { display: none; }
.verseblock { margin: 0 1em 1.25em 1em; }
.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: rgba(0, 0, 0, 0.85); font-weight: 300; text-rendering: optimizeLegibility; }
.verseblock pre strong { font-weight: 400; }
.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
.quoteblock .attribution, .verseblock .attribution { font-size: 0.9375em; line-height: 1.45; font-style: italic; }
.quoteblock .attribution br, .verseblock .attribution br { display: none; }
.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: rgba(0, 0, 0, 0.6); }
.quoteblock.abstract { margin: 0 0 1.25em 0; display: block; }
.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
table.tableblock { max-width: 100%; border-collapse: separate; }
table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
table.tableblock, th.tableblock, td.tableblock { border: 0 solid #dedede; }
table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; }
table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; }
table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; }
table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; }
table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; }
table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; }
table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; }
table.frame-all { border-width: 1px; }
table.frame-sides { border-width: 0 1px; }
table.frame-topbot { border-width: 1px 0; }
th.halign-left, td.halign-left { text-align: left; }
th.halign-right, td.halign-right { text-align: right; }
th.halign-center, td.halign-center { text-align: center; }
th.valign-top, td.valign-top { vertical-align: top; }
th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
th.valign-middle, td.valign-middle { vertical-align: middle; }
table thead th, table tfoot th { font-weight: bold; }
tbody tr th { display: table-cell; line-height: 1.6; background: #f7f8f7; }
tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #34302d; font-weight: bold; }
p.tableblock > code:only-child { background: none; padding: 0; }
p.tableblock { font-size: 1em; }
td > div.verse { white-space: pre; }
ol { margin-left: 1.75em; }
ul li ol { margin-left: 1.5em; }
dl dd { margin-left: 1.125em; }
dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.625em; }
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1em; font-size: 0.85em; }
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { width: 1em; position: relative; top: 1px; }
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
ul.inline > li > * { display: block; }
.unstyled dl dt { font-weight: normal; font-style: normal; }
ol.arabic { list-style-type: decimal; }
ol.decimal { list-style-type: decimal-leading-zero; }
ol.loweralpha { list-style-type: lower-alpha; }
ol.upperalpha { list-style-type: upper-alpha; }
ol.lowerroman { list-style-type: lower-roman; }
ol.upperroman { list-style-type: upper-roman; }
ol.lowergreek { list-style-type: lower-greek; }
.hdlist > table, .colist > table { border: 0; background: none; }
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
td.hdlist1 { font-weight: bold; padding-bottom: 1.25em; }
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
.colist > table tr > td:first-of-type { padding: 0 0.75em; line-height: 1; }
.colist > table tr > td:first-of-type img { max-width: initial; }
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
.imageblock > .title { margin-bottom: 0; }
.imageblock.thumb, .imageblock.th { border-width: 6px; }
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
.image.left { margin-right: 0.625em; }
.image.right { margin-left: 0.625em; }
a.image { text-decoration: none; display: inline-block; }
a.image object { pointer-events: none; }
sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
sup.footnote a, sup.footnoteref a { text-decoration: none; }
sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.05em; margin-bottom: 0.2em; }
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
#footnotes .footnote:last-of-type { margin-bottom: 0; }
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
.gist .file-data > table td.line-data { width: 99%; }
div.unbreakable { page-break-inside: avoid; }
.big { font-size: larger; }
.small { font-size: smaller; }
.underline { text-decoration: underline; }
.overline { text-decoration: overline; }
.line-through { text-decoration: line-through; }
.aqua { color: #00bfbf; }
.aqua-background { background-color: #00fafa; }
.black { color: black; }
.black-background { background-color: black; }
.blue { color: #0000bf; }
.blue-background { background-color: #0000fa; }
.fuchsia { color: #bf00bf; }
.fuchsia-background { background-color: #fa00fa; }
.gray { color: #606060; }
.gray-background { background-color: #7d7d7d; }
.green { color: #006000; }
.green-background { background-color: #007d00; }
.lime { color: #00bf00; }
.lime-background { background-color: #00fa00; }
.maroon { color: #600000; }
.maroon-background { background-color: #7d0000; }
.navy { color: #000060; }
.navy-background { background-color: #00007d; }
.olive { color: #606000; }
.olive-background { background-color: #7d7d00; }
.purple { color: #600060; }
.purple-background { background-color: #7d007d; }
.red { color: #bf0000; }
.red-background { background-color: #fa0000; }
.silver { color: #909090; }
.silver-background { background-color: #bcbcbc; }
.teal { color: #006060; }
.teal-background { background-color: #007d7d; }
.white { color: #bfbfbf; }
.white-background { background-color: #fafafa; }
.yellow { color: #bfbf00; }
.yellow-background { background-color: #fafa00; }
span.icon > .fa { cursor: default; }
.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #3f6a22; }
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
.conum[data-value] { display: inline-block; color: #fff !important; background-color: #34302d; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
.conum[data-value] * { color: #fff !important; }
.conum[data-value] + b { display: none; }
.conum[data-value]:after { content: attr(data-value); }
pre .conum[data-value] { position: relative; top: -0.125em; }
b.conum * { color: inherit !important; }
.conum:not([data-value]):empty { display: none; }
.admonitionblock { border-left: 4px solid #6db33f; background-color: #ebf1e7; padding: 1.2em 0; margin: 30px 0; width: auto; }
#toc a:hover { text-decoration: underline; }
.admonitionblock > table td.content { border-left: none; }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
[[spring-web]]
= The Web
:doc-root: https://docs.spring.io
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
[partintro]
--
This part of the reference documentation covers Spring Framework's support for the
presentation tier (and specifically web-based presentation tiers) including support
for WebSocket-style messaging in web applications.
Spring Framework's own web framework, <<mvc,Spring Web MVC>>, is covered in the
first couple of chapters. Subsequent chapters are concerned with Spring Framework's
integration with other web technologies, such as <<jsf,JSF>>.
The section then concludes with comprehensive coverage of the Spring Framework
<<websocket>> (including <<websocket-stomp>>).
* <<mvc>>
* <<view>>
* <<web-integration>>
* <<websocket>>
--
include::web/web-mvc.adoc[leveloffset=+1]
include::web/web-view.adoc[leveloffset=+1]
include::web/web-cors.adoc[leveloffset=+1]
include::web/web-integration.adoc[leveloffset=+1]
include::web/web-websocket.adoc[leveloffset=+1]
include::web/web-flux.adoc[leveloffset=+1]

View File

@@ -0,0 +1,244 @@
[[cors]]
= CORS Support
== Introduction
For security reasons, browsers prohibit AJAX calls to resources residing outside the
current origin. For example, as you're checking your bank account in one tab, you
could have the evil.com website open in another tab. The scripts from evil.com should not
be able to make AJAX requests to your bank API (e.g., withdrawing money from your account!)
using your credentials.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-origin resource sharing]
(CORS) is a http://www.w3.org/TR/cors/[W3C specification] implemented by
http://caniuse.com/#feat=cors[most browsers] that allows you to specify in a flexible
way what kind of cross domain requests are authorized, instead of using some less secured
and less powerful hacks like IFRAME or JSONP.
As of Spring Framework 4.2, CORS is supported out of the box. CORS requests
(https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L906[including preflight ones with an `OPTIONS` method])
are automatically dispatched to the various registered ``HandlerMapping``s. They handle
CORS preflight requests and intercept CORS simple and actual requests thanks to a
{api-spring-framework}/web/cors/CorsProcessor.html[CorsProcessor]
implementation (https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java[DefaultCorsProcessor]
by default) in order to add the relevant CORS response headers (like `Access-Control-Allow-Origin`)
based on the CORS configuration you have provided.
[NOTE]
====
Since CORS requests are automatically dispatched, you *do not need* to change the
`DispatcherServlet` `dispatchOptionsRequest` init parameter value; using its default value
(`false`) is the recommended approach.
====
== Controller method CORS configuration
You can add an
{api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`]
annotation to your `@RequestMapping` annotated handler method in order to enable CORS on
it. By default `@CrossOrigin` allows all origins and the HTTP methods specified in the
`@RequestMapping` annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
It is also possible to enable CORS for the whole controller:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
In the above example CORS support is enabled for both the `retrieve()` and the `remove()`
handler methods, and you can also see how you can customize the CORS configuration using
`@CrossOrigin` attributes.
You can even use both controller-level and method-level CORS configurations; Spring will
then combine attributes from both annotations to create merged CORS configuration.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
== Global CORS configuration
In addition to fine-grained, annotation-based configuration you'll probably want to
define some global CORS configuration as well. This is similar to using filters but can
be declared within Spring MVC and combined with fine-grained `@CrossOrigin` configuration.
By default all origins and `GET`, `HEAD`, and `POST` methods are allowed.
=== JavaConfig
Enabling CORS for the whole application is as simple as:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
----
You can easily change any properties, as well as only apply this CORS configuration to a
specific path pattern:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
----
=== XML namespace
The following minimal XML configuration enables CORS for the `/**` path pattern with
the same default properties as with the aforementioned JavaConfig examples:
[source,xml,indent=0]
[subs="verbatim"]
----
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
----
It is also possible to declare several CORS mappings with customized properties:
[source,xml,indent=0]
[subs="verbatim"]
----
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />
<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />
</mvc:cors>
----
== Advanced Customization
{api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
allows you to specify how the CORS requests should be processed: allowed origins, headers, methods, etc.
It can be provided in various ways:
* {api-spring-framework}/web/servlet/handler/AbstractHandlerMapping.html#setCorsConfiguration-java.util.Map-[`AbstractHandlerMapping#setCorsConfiguration()`]
allows to specify a `Map` with several {api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
instances mapped to path patterns like `/api/**`.
* Subclasses can provide their own `CorsConfiguration` by overriding the
`AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)` method.
* Handlers can implement the {api-spring-framework}/web/cors/CorsConfigurationSource.html[`CorsConfigurationSource`]
interface (like https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java[`ResourceHttpRequestHandler`]
now does) in order to provide a {api-spring-framework}/web/cors/CorsConfiguration.html[CorsConfiguration]
instance for each request.
== Filter based CORS support
In order to support CORS with filter-based security frameworks like
http://projects.spring.io/spring-security/[Spring Security], or
with other libraries that do not support natively CORS, Spring Framework also
provides a http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/filter/CorsFilter.html[`CorsFilter`].
Instead of using `@CrossOrigin` or `WebMvcConfigurer#addCorsMappings(CorsRegistry)`, you
need to register a custom filter defined like bellow:
[source,java,indent=0]
----
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
public class MyCorsFilter extends CorsFilter {
public MyCorsFilter() {
super(configurationSource());
}
private static UrlBasedCorsConfigurationSource configurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
----
You need to ensure that `CorsFilter` is ordered before the other filters, see
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework#filter-based-cors-support[this blog post]
about how to configure Spring Boot accordingly.

View File

@@ -0,0 +1,244 @@
==== Functional Programming Model
NOTE: This section is to be merged into `web-flux.adoc`.
===== HandlerFunctions
Incoming HTTP requests are handled by a **`HandlerFunction`**, which is essentially a function that
takes a `ServerRequest` and returns a `Mono<ServerResponse>`. The annotation counterpart to a
handler function would be a method with `@RequestMapping`.
`ServerRequest` and `ServerResponse` are immutable interfaces that offer JDK-8 friendly access
to the underlying HTTP messages. Both are fully reactive by
building on top of Reactor: the request expose the body as `Flux` or `Mono`; the response accepts
any http://www.reactive-streams.org[Reactive Streams] `Publisher` as body.
`ServerRequest` gives access to various HTTP request elements:
the method, URI, query parameters, and -- through the separate `ServerRequest.Headers` interface
-- the headers. Access to the body is provided through the `body` methods. For instance, this is
how to extract the request body into a `Mono<String>`:
Mono<String> string = request.bodyToMono(String.class);
And here is how to extract the body into a `Flux`, where `Person` is a class that can be
deserialised from the contents of the body (i.e. `Person` is supported by Jackson if the body
contains JSON, or JAXB if XML).
Flux<Person> people = request.bodyToFlux(Person.class);
The two methods above (`bodyToMono` and `bodyToFlux`) are, in fact, convenience methods that use the
generic `ServerRequest.body(BodyExtractor)` method. `BodyExtractor` is
a functional strategy interface that allows you to write your own extraction logic, but common
`BodyExtractor` instances can be found in the `BodyExtractors` utility class. So, the above
examples can be replaced with:
Mono<String> string = request.body(BodyExtractors.toMono(String.class);
Flux<Person> people = request.body(BodyExtractors.toFlux(Person.class);
Similarly, `ServerResponse` provides access to the HTTP response. Since it is immutable, you create
a `ServerResponse` with a builder. The builder allows you to set the response status, add response
headers, and provide a body. For instance, this is how to create a response with a 200 OK status,
a JSON content-type, and a body:
Mono<Person> person = ...
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person);
And here is how to build a response with a 201 Created status, Location header, and empty body:
URI location = ...
ServerResponse.created(location).build();
Putting these together allows us to create a `HandlerFunction`. For instance, here is an example
of a simple "Hello World" handler lambda, that returns a response with a 200 status and a body
based on a String:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
HandlerFunction<ServerResponse> helloWorld =
request -> ServerResponse.ok().body(fromObject("Hello World"));
----
Writing handler functions as lambda's, as we do above, is convenient, but perhaps lacks in
readability and becomes less maintainable when dealing with multiple functions. Therefore, it is
recommended to group related handler functions into a handler or controller class. For example,
here is a class that exposes a reactive `Person` repository:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
public class PersonHandler {
private final PersonRepository repository;
public PersonHandler(PersonRepository repository) {
this.repository = repository;
}
public Mono<ServerResponse> listPeople(ServerRequest request) { // <1>
Flux<Person> people = repository.allPeople();
return ServerResponse.ok().contentType(APPLICATION_JSON).body(people, Person.class);
}
public Mono<ServerResponse> createPerson(ServerRequest request) { // <2>
Mono<Person> person = request.bodyToMono(Person.class);
return ServerResponse.ok().build(repository.savePerson(person));
}
public Mono<ServerResponse> getPerson(ServerRequest request) { // <3>
int personId = Integer.valueOf(request.pathVariable("id"));
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
Mono<Person> personMono = this.repository.getPerson(personId);
return personMono
.then(person -> ServerResponse.ok().contentType(APPLICATION_JSON).body(fromObject(person)))
.otherwiseIfEmpty(notFound);
}
}
----
<1> `listPeople` is a handler function that returns all `Person` objects found in the repository as
JSON.
<2> `createPerson` is a handler function that stores a new `Person` contained in the request body.
Note that `PersonRepository.savePerson(Person)` returns `Mono<Void>`: an empty Mono that emits
a completion signal when the person has been read from the request and stored. So we use the
`build(Publisher<Void>)` method to send a response when that completion signal is received, i.e.
when the `Person` has been saved.
<3> `getPerson` is a handler function that returns a single person, identified via the path
variable `id`. We retrieve that `Person` via the repository, and create a JSON response if it is
found. If it is not found, we use `otherwiseIfEmpty(Mono<T>)` to return a 404 Not Found response.
===== RouterFunctions
Incoming requests are routed to handler functions with a **`RouterFunction`**, which is a function
that takes a `ServerRequest`, and returns a `Mono<HandlerFunction>`. If a request matches a
particular route, a handler function is returned; otherwise it returns an empty `Mono`. The
`RouterFunction` has a similar purpose as the `@RequestMapping` annotation in `@Controller` classes.
Typically, you do not write router functions yourself, but rather use
`RouterFunctions.route(RequestPredicate, HandlerFunction)` to
create one using a request predicate and handler function. If the predicate applies, the request is
routed to the given handler function; otherwise no routing is performed, resulting in a
404 Not Found response.
Though you can write your own `RequestPredicate`, you do not have to: the `RequestPredicates`
utility class offers commonly used predicates, such matching based on path, HTTP method,
content-type, etc.
Using `route`, we can route to our "Hello World" handler function:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
RouterFunction<ServerResponse> helloWorldRoute =
RouterFunctions.route(RequestPredicates.path("/hello-world"),
request -> Response.ok().body(fromObject("Hello World")));
----
Two router functions can be composed into a new router function that routes to either handler
function: if the predicate of the first route does not match, the second is evaluated.
Composed router functions are evaluated in order, so it makes sense to put specific functions
before generic ones.
You can compose two router functions by calling `RouterFunction.and(RouterFunction)`, or by calling
`RouterFunction.andRoute(RequestPredicate, HandlerFunction)`, which is a convenient combination
of `RouterFunction.and()` with `RouterFunctions.route()`.
Given the `PersonHandler` we showed above, we can now define a router function that routes to the
respective handler functions.
We use https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html[method-references]
to refer to the handler functions:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
PersonRepository repository = ...
PersonHandler handler = new PersonHandler(repository);
RouterFunction<ServerResponse> personRoute =
route(GET("/person/{id}").and(accept(APPLICATION_JSON)), handler::getPerson)
.andRoute(GET("/person").and(accept(APPLICATION_JSON)), handler::listPeople)
.andRoute(POST("/person").and(contentType(APPLICATION_JSON)), handler::createPerson);
----
Besides router functions, you can also compose request predicates, by calling
`RequestPredicate.and(RequestPredicate)` or `RequestPredicate.or(RequestPredicate)`.
These work as expected: for `and` the resulting predicate matches if *both* given predicates match;
`or` matches if *either* predicate does.
Most of the predicates found in `RequestPredicates` are compositions.
For instance, `RequestPredicates.GET(String)` is a composition of
`RequestPredicates.method(HttpMethod)` and `RequestPredicates.path(String)`.
====== Running a Server
Now there is just one piece of the puzzle missing: running a router function in an HTTP server.
You can convert a router function into a `HttpHandler` by using
`RouterFunctions.toHttpHandler(RouterFunction)`.
The `HttpHandler` allows you to run on a wide variety of reactive runtimes: Reactor Netty,
RxNetty, Servlet 3.1+, and Undertow.
Here is how we run a router function in Reactor Netty, for instance:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
----
For Tomcat it looks like this:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
RouterFunction<ServerResponse> route = ...
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("", System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();
----
TODO: DispatcherHandler
===== HandlerFilterFunction
Routes mapped by a router function can be filtered by calling
`RouterFunction.filter(HandlerFilterFunction)`, where `HandlerFilterFunction` is essentially a
function that takes a `ServerRequest` and `HandlerFunction`, and returns a `ServerResponse`.
The handler function parameter represents the next element in the chain: this is typically the
`HandlerFunction` that is routed to, but can also be another `FilterFunction` if multiple filters
are applied.
With annotations, similar functionality can be achieved using `@ControllerAdvice` and/or a `ServletFilter`.
Let's add a simple security filter to our route, assuming that we have a `SecurityManager` that
can determine whether a particular path is allowed:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
SecurityManager securityManager = ...
RouterFunction<ServerResponse> route = ...
RouterFunction<ServerResponse> filteredRoute =
route.filter(request, next) -> {
if (securityManager.allowAccessTo(request.path())) {
return next.handle(request);
}
else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});
----
You can see in this example that invoking the `next.handle(ServerRequest)` is optional: we only
allow the handler function to be executed when access is allowed.

View File

@@ -0,0 +1,393 @@
[[web-reactive]]
= WebFlux framework
This section provides basic information on the reactive programming
support for Web applications in Spring Framework 5.
[[web-reactive-intro]]
== Introduction
[[web-reactive-programming]]
=== What is Reactive Programming?
In plain terms reactive programming is about non-blocking applications that are asynchronous
and event-driven and require a small number of threads to scale vertically (i.e. within the
JVM) rather than horizontally (i.e. through clustering).
A key aspect of reactive applications is the concept of backpressure which is
a mechanism to ensure producers don't overwhelm consumers. For example in a pipeline
of reactive components extending from the database to the HTTP response when the
HTTP connection is too slow the data repository can also slow down or stop completely
until network capacity frees up.
Reactive programming also leads to a major shift from imperative to declarative async
composition of logic. It is comparable to writing blocking code vs using the
`CompletableFuture` from Java 8 to compose follow-up actions via lambda expressions.
For a longer introduction check the blog series
https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape["Notes on Reactive Programming"]
by Dave Syer.
[[web-reactive-api]]
=== Reactive API and Building Blocks
Spring Framework 5 embraces
https://github.com/reactive-streams/reactive-streams-jvm#reactive-streams[Reactive Streams]
as the contract for communicating backpressure across async components and
libraries. Reactive Streams is a specification created through industry collaboration that
has also been adopted in Java 9 as `java.util.concurrent.Flow`.
The Spring Framework uses https://projectreactor.io/[Reactor] internally for its own
reactive support. Reactor is a Reactive Streams implementation that further extends the
basic Reactive Streams `Publisher` contract with the `Flux` and `Mono` composable API
types to provide declarative operations on data sequences of `0..N` and `0..1`.
The Spring Framework exposes `Flux` and `Mono` in many of its own reactive APIs.
At the application level however, as always, Spring provides choice and fully supports
the use of RxJava. For more on reactive types check the post
https://spring.io/blog/2016/04/19/understanding-reactive-types["Understanding Reactive Types"]
by Sebastien Deleuze.
[[web-reactive-feature-overview]]
== Spring WebFlux Module
Spring Framework 5 includes a new `spring-webflux` module. The module contains support
for reactive HTTP and WebSocket clients as well as for reactive server web applications
including REST, HTML browser, and WebSocket style interactions.
[[web-reactive-server]]
=== Server Side
On the server-side WebFlux supports 2 distinct programming models:
* Annotation-based with `@Controller` and the other annotations supported also with Spring MVC
* Functional, Java 8 lambda style routing and handling
Both programming models are executed on the same reactive foundation that adapts
non-blocking HTTP runtimes to the Reactive Streams API. The diagram
below shows the server-side stack including traditional, Servlet-based
Spring MVC on the left from the `spring-webmvc` module and also the
reactive stack on the right from the `spring-webflux` module.
image::images/webflux-overview.png[width=720]
WebFlux can run on Servlet containers with support for the
Servlet 3.1 Non-Blocking IO API as well as on other async runtimes such as
Netty and Undertow. Each runtime is adapted to a reactive
`ServerHttpRequest` and `ServerHttpResponse` exposing the body of the
request and response as `Flux<DataBuffer>`, rather than
`InputStream` and `OutputStream`, with reactive backpressure.
REST-style JSON and XML serialization and deserialization is supported on top
as a `Flux<Object>`, and so is HTML view rendering and Server-Sent Events.
[[web-reactive-server-annotation]]
==== Annotation-based Programming Model
The same `@Controller` programming model and the same annotations used in Spring MVC
are also supported in WebFlux. The main difference is that the underlying core,
framework contracts -- i.e. `HandlerMapping`, `HandlerAdapter`, are
non-blocking and operate on the reactive `ServerHttpRequest` and `ServerHttpResponse`
rather than on the `HttpServletRequest` and `HttpServletResponse`.
Below is an example with a reactive controller:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RestController
public class PersonController {
private final PersonRepository repository;
public PersonController(PersonRepository repository) {
this.repository = repository;
}
@PostMapping("/person")
Mono<Void> create(@RequestBody Publisher<Person> personStream) {
return this.repository.save(personStream).then();
}
@GetMapping("/person")
Flux<Person> list() {
return this.repository.findAll();
}
@GetMapping("/person/{id}")
Mono<Person> findById(@PathVariable String id) {
return this.repository.findOne(id);
}
}
----
[[web-reactive-server-functional]]
==== Functional Programming Model
include::web-flux-functional.adoc[leveloffset=+1]
[[web-reactive-client]]
=== Client Side
WebFlux includes a functional, reactive `WebClient` that offers a fully
non-blocking and reactive alternative to the `RestTemplate`. It exposes network
input and output as a reactive `ClientHttpRequest` and `ClientHttpResponse` where
the body of the request and response is a `Flux<DataBuffer>` rather than an
`InputStream` and `OutputStream`. In addition it supports the same reactive JSON, XML,
and SSE serialization mechanism as on the server side so you can work with typed objects.
Below is an example of using the `WebClient` which requires a `ClientHttpConnector`
implementation to plug in a specific HTTP client such as Reactor Netty:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
WebClient client = WebClient.create("http://example.com");
Mono<Account> account = client.get()
.url("/accounts/{id}", 1L)
.accept(APPLICATION_JSON)
.exchange(request)
.then(response -> response.bodyToMono(Account.class));
----
[NOTE]
====
The `AsyncRestTemplate` also supports non-blocking interactions. The main difference
is it can't support non-blocking streaming, like for example
https://dev.twitter.com/streaming/overview[Twitter one], because fundamentally it's
still based and relies on `InputStream` and `OutputStream`.
====
[[web-reactive-http-body]]
=== Request and Response Body Conversion
The `spring-core` module provides reactive `Encoder` and `Decoder` contracts
that enable the serialization of a `Flux` of bytes to and from typed objects.
The `spring-web` module adds JSON (Jackson) and XML (JAXB) implementations for use in
web applications as well as others for SSE streaming and zero-copy file transfer.
The following Reactive APIs are supported:
* Reactor 3.x is supported out of the box
* RxJava 2.x is supported when `io.reactivex.rxjava2:rxjava` dependency is on the classpath
* RxJava 1.x is supported when both `io.reactivex:rxjava` and `io.reactivex:rxjava-reactive-streams` (https://github.com/ReactiveX/RxJavaReactiveStreams[adapter between RxJava and Reactive Streams]) dependencies are on the classpath
For example the request body can be one of the following way and it will be decoded
automatically in both the annotation and the functional programming models:
* `Account account` -- the account is deserialized without blocking before the controller is invoked.
* `Mono<Account> account` -- the controller can use the `Mono` to declare logic to be executed after the account is deserialized.
* `Single<Account> account` -- same as with `Mono` but using RxJava
* `Flux<Account> accounts` -- input streaming scenario.
* `Observable<Account> accounts` -- input streaming with RxJava.
The response body can be one of the following:
* `Mono<Account>` -- serialize without blocking the given Account when the `Mono` completes.
* `Single<Account>` -- same but using RxJava.
* `Flux<Account>` -- streaming scenario, possibly SSE depending on the requested content type.
* `Observable<Account>` -- same but using RxJava `Observable` type.
* `Flowable<Account>` -- same but using RxJava 2 `Flowable` type.
* `Publisher<Account>` or `Flow.Publisher<Account>` -- any type implementing Reactive Streams `Publisher` is supported.
* `Flux<ServerSentEvent>` -- SSE streaming.
* `Mono<Void>` -- request handling completes when the `Mono` completes.
* `Account` -- serialize without blocking the given Account; implies a synchronous, non-blocking controller method.
* `void` -- specific to the annotation-based programming model, request handling completes
when the method returns; implies a synchronous, non-blocking controller method.
When using stream types like `Flux` or `Observable`, the media type specified in the
request/response or at mapping/routing level is used to determine how the data should be serialized
and flushed. For example a REST endpoint that returns a `Flux<Account>` will be serialized by
default as following:
* `application/json`: a `Flux<Account>` is handled as an asynchronous collection and
serialized as a JSON array with an explicit flush when the `complete` event is emitted.
* `application/stream+json`: a `Flux<Account>` will be handled as a stream of `Account` elements
serialized as individual JSON object separated by new lines and explicitly flushed after
each element. The `WebClient` supports JSON stream decoding so this is a good use case
for server to server use case.
* `text/event-stream`: a `Flux<Account>` or `Flux<ServerSentEvent<Account>>` will be handled as
a stream of `Account` or `ServerSentEvent` elements serialized as individual SSE elements
using by default JSON for data encoding and explicit flush after each element. This
is well suited for exposing a stream to browser clients. `WebClient` supports
reading SSE streams as well.
[[web-reactive-websocket-support]]
=== Reactive WebSocket Support
WebFlux includes reactive WebSocket client and server support.
Both client and server are supported on the Java WebSocket API
(JSR-356), Jetty, Undertow, Reactor Netty, and RxNetty.
On the server side, declare a `WebSocketHandlerAdapter` and then simply add
mappings to `WebSocketHandler`-based endpoints:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/foo", new FooWebSocketHandler());
map.put("/bar", new BarWebSocketHandler());
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setUrlMap(map);
return mapping;
}
@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
----
On the client side create a `WebSocketClient` for one of the supported libraries
listed above:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute("ws://localhost:8080/echo"), session -> {... }).blockMillis(5000);
----
[[web-reactive-tests]]
=== Testing
The `spring-test` module includes a `WebTestClient` that can be used to test
WebFlux server endpoints with or without a running server.
Tests without a running server are comparable to `MockMvc` from Spring MVC
where mock request and response are used instead of connecting over the network
using a socket. The `WebTestClient` however can also perform tests against a
running server.
For more see
https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples[sample tests]
in the framework.
[[web-reactive-getting-started]]
== Getting Started
[[web-reactive-getting-started-boot]]
=== Spring Boot Starter
The
https://github.com/bclozel/spring-boot-web-reactive#spring-boot-web-reactive-starter[Spring Boot Web Reactive starter]
available via http://start.spring.io is the fastest way to get started.
It does all that's necessary so you to start writing `@Controller` classes
just like with Spring MVC. Simply go to http://start.spring.io, choose
version 2.0.0.BUILD-SNAPSHOT, and type reactive in the dependencies box.
By default the starter runs with Tomcat but the dependencies can be changed as usual with Spring Boot to switch to a different runtime.
See the
https://github.com/bclozel/spring-boot-web-reactive#spring-boot-web-reactive-starter[starter]
page for more details and instruction
This starter also supports the functional web API and will detect automatically `RouterFunction`
beans. Your Spring Boot WebFlux application should use the `RouterFunction` *or* the
`RequestMapping` approach, it is currently not possible to mix them in the same application.
[[web-reactive-getting-started-manual]]
=== Manual Bootstrapping
This section outlines the steps to get up and running manually.
For dependencies start with `spring-webflux` and `spring-context`.
Then add `jackson-databind` and `io.netty:netty-buffer`
(temporarily see https://jira.spring.io/browse/SPR-14528[SPR-14528]) for JSON support.
Lastly add the dependencies for one of the supported runtimes:
* Tomcat -- `org.apache.tomcat.embed:tomcat-embed-core`
* Jetty -- `org.eclipse.jetty:jetty-server` and `org.eclipse.jetty:jetty-servlet`
* Reactor Netty -- `io.projectreactor.ipc:reactor-netty`
* RxNetty -- `io.reactivex:rxnetty-common` and `io.reactivex:rxnetty-http`
* Undertow -- `io.undertow:undertow-core`
For the **annotation-based programming model** bootstrap with:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext context = new AnnotationConfigApplicationContext(DelegatingWebFluxConfiguration.class); // (1)
HttpHandler handler = DispatcherHandler.toHttpHandler(context); // (2)
----
The above loads default Spring Web framework configuration (1), then creates a
`DispatcherHandler`, the main class driving request processing (2), and adapts
it to `HttpHandler` -- the lowest level Spring abstraction for reactive HTTP request handling.
For the **functional programming model** bootstrap as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext context = new AnnotationConfigApplicationContext(); // (1)
context.registerBean(FooBean.class, () -> new FooBeanImpl()); // (2)
context.registerBean(BarBean.class); // (3)
HttpHandler handler = WebHttpHandlerBuilder
.webHandler(RouterFunctions.toHttpHandler(...))
.applicationContext(context)
.build(); // (4)
----
The above creates an `AnnotationConfigApplicationContext` instance (1) that can take advantage
of the new functional bean registration API (2) to register beans using a Java 8 `Supplier`
or just by specifying its class (3). The `HttpHandler` is created using `WebHttpHandlerBuilder` (4).
The `HttpHandler` can then be installed in one of the supported runtimes:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
// Tomcat and Jetty (also see notes below)
HttpServlet servlet = new ServletHttpHandlerAdapter(handler);
...
// Reactor Netty
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create(host, port).newHandler(adapter).block();
// RxNetty
RxNettyHttpHandlerAdapter adapter = new RxNettyHttpHandlerAdapter(handler);
HttpServer server = HttpServer.newServer(new InetSocketAddress(host, port));
server.startAndAwait(adapter);
// Undertow
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();
----
[NOTE]
====
For Servlet containers especially with WAR deployment you can use the
`AbstractAnnotationConfigDispatcherHandlerInitializer` which as a
`WebApplicationInitializer` and is auto-detected by Servlet containers.
It takes care of registering the `ServletHttpHandlerAdapter` as shown above.
You will need to implement one abstract method in order to point to your
Spring configuration.
====
[[web-reactive-getting-started-examples]]
=== Examples
You will find code examples useful to build reactive Web application in the following projects:
* https://github.com/bclozel/spring-boot-web-reactive[Spring Boot Web Reactive Starter]: sources of the reactive starter available at http://start.spring.io
* https://github.com/poutsma/web-function-sample[Functional programming model sample]
* https://github.com/sdeleuze/spring-reactive-playground[Spring Reactive Playground]: playground for most Spring Web reactive features
* https://github.com/reactor/projectreactor.io/tree/spring-functional[Reactor website]: the `spring-functional` branch is a Spring 5 functional, Java 8 lambda-style application
* https://github.com/bclozel/spring-reactive-university[Spring Reactive University session]: live-coded project from https://www.youtube.com/watch?v=Cj4foJzPF80[this Devoxx BE 2106 university talk]
* https://github.com/thymeleaf/thymeleafsandbox-biglist-reactive[Reactive Thymeleaf Sandbox]
* https://github.com/mix-it/mixit/[Mix-it 2017 website]: Kotlin + Reactive + Functional web and bean registration API application
* https://github.com/simonbasle/reactor-by-example[Reactor by example]: code snippets coming from this https://www.infoq.com/articles/reactor-by-example[InfoQ article]
* https://github.com/spring-projects/spring-framework/tree/master/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation[Spring integration tests]: various features tested with Reactor https://projectreactor.io/docs/test/release/api/index.html?reactor/test/StepVerifier.html[`StepVerifier`]

View File

@@ -0,0 +1,249 @@
[[web-integration]]
= Integrating with other web frameworks
[[intro]]
== Introduction
.Spring Web Flow
****
Spring Web Flow (SWF) aims to be the best solution for the management of web application
page flow.
SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and
Portlet environments. If you have a business process (or processes) that would benefit
from a conversational model as opposed to a purely request model, then SWF may be the
solution.
SWF allows you to capture logical page flows as self-contained modules that are reusable
in different situations, and as such is ideal for building web application modules that
guide the user through controlled navigations that drive business processes.
For more information about SWF, consult the
http://projects.spring.io/spring-webflow/[Spring Web Flow website].
****
This chapter details Spring's integration with third party web frameworks, such as
http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF].
One of the core value propositions of the Spring Framework is that of enabling
__choice__. In a general sense, Spring does not force one to use or buy into any
particular architecture, technology, or methodology (although it certainly recommends
some over others). This freedom to pick and choose the architecture, technology, or
methodology that is most relevant to a developer and their development team is
arguably most evident in the web area, where Spring provides its own web framework
(<<mvc,Spring MVC>>), while at the same time providing integration with a number of
popular third party web frameworks. This allows one to continue to leverage any and all
of the skills one may have acquired in a particular web framework such as JSF, while
at the same time being able to enjoy the benefits afforded by Spring in other areas such
as data access, declarative transaction management, and flexible configuration and
application assembly.
Having dispensed with the woolly sales patter (c.f. the previous paragraph), the
remainder of this chapter will concentrate upon the meaty details of integrating your
favorite web framework with Spring. One thing that is often commented upon by developers
coming to Java from other languages is the seeming super-abundance of web frameworks
available in Java. There are indeed a great number of web frameworks in the Java space;
in fact there are far too many to cover with any semblance of detail in a single
chapter. This chapter thus picks four of the more popular web frameworks in Java,
starting with the Spring configuration that is common to all of the supported web
frameworks, and then detailing the specific integration options for each supported web
framework.
[NOTE]
====
Please note that this chapter does not attempt to explain how to use any of the
supported web frameworks. For example, if you want to use JSF for the presentation
layer of your web application, the assumption is that you are already familiar with
JSF itself. If you need further details about any of the supported web frameworks
themselves, please do consult <<web-integration-resources>> at the end of this chapter.
====
[[web-integration-common]]
== Common configuration
Before diving into the integration specifics of each supported web framework, let us
first take a look at the Spring configuration that is __not__ specific to any one web
framework. (This section is equally applicable to Spring's own web framework, Spring
MVC.)
One of the concepts (for want of a better word) espoused by (Spring's) lightweight
application model is that of a layered architecture. Remember that in a 'classic'
layered architecture, the web layer is but one of many layers; it serves as one of the
entry points into a server side application and it delegates to service objects
(facades) defined in a service layer to satisfy business specific (and
presentation-technology agnostic) use cases. In Spring, these service objects, any other
business-specific objects, data access objects, etc. exist in a distinct 'business
context', which contains __no__ web or presentation layer objects (presentation objects
such as Spring MVC controllers are typically configured in a distinct 'presentation
context'). This section details how one configures a Spring container (a
`WebApplicationContext`) that contains all of the 'business beans' in one's application.
On to specifics: all that one need do is to declare a
{api-spring-framework}/web/context/ContextLoaderListener.html[`ContextLoaderListener`]
in the standard Java EE servlet `web.xml` file of one's web application, and add a
`contextConfigLocation`<context-param/> section (in the same file) that defines which
set of Spring XML configuration files to load.
Find below the <listener/> configuration:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
----
Find below the <context-param/> configuration:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
----
If you don't specify the `contextConfigLocation` context parameter, the
`ContextLoaderListener` will look for a file called `/WEB-INF/applicationContext.xml` to
load. Once the context files are loaded, Spring creates a
{api-spring-framework}/web/context/WebApplicationContext.html[`WebApplicationContext`]
object based on the bean definitions and stores it in the `ServletContext` of the web
application.
All Java web frameworks are built on top of the Servlet API, and so one can use the
following code snippet to get access to this 'business context' `ApplicationContext`
created by the `ContextLoaderListener`.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
----
The
{api-spring-framework}/web/context/support/WebApplicationContextUtils.html[`WebApplicationContextUtils`]
class is for convenience, so you don't have to remember the name of the `ServletContext`
attribute. Its __getWebApplicationContext()__ method will return `null` if an object
doesn't exist under the `WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE`
key. Rather than risk getting `NullPointerExceptions` in your application, it's better
to use the `getRequiredWebApplicationContext()` method. This method throws an exception
when the `ApplicationContext` is missing.
Once you have a reference to the `WebApplicationContext`, you can retrieve beans by
their name or type. Most developers retrieve beans by name and then cast them to one of
their implemented interfaces.
Fortunately, most of the frameworks in this section have simpler ways of looking up
beans. Not only do they make it easy to get beans from a Spring container, but they also
allow you to use dependency injection on their controllers. Each web framework section
has more detail on its specific integration strategies.
[[jsf]]
== JavaServer Faces 1.2
JavaServer Faces (JSF) is the JCP's standard component-based, event-driven web user
interface framework. As of Java EE 5, it is an official part of the Java EE umbrella.
For a popular JSF runtime as well as for popular JSF component libraries, check out the
http://myfaces.apache.org/[Apache MyFaces project]. The MyFaces project also provides
common JSF extensions such as http://myfaces.apache.org/orchestra/[MyFaces Orchestra]:
a Spring-based JSF extension that provides rich conversation scope support.
[NOTE]
====
Spring Web Flow 2.0 provides rich JSF support through its newly established Spring Faces
module, both for JSF-centric usage (as described in this section) and for Spring-centric
usage (using JSF views within a Spring MVC dispatcher). Check out the
http://projects.spring.io/spring-webflow[Spring Web Flow website] for details!
====
The key element in Spring's JSF integration is the JSF `ELResolver` mechanism.
[[jsf-springbeanfaceselresolver]]
=== SpringBeanFacesELResolver (JSF 1.2+)
`SpringBeanFacesELResolver` is a JSF 1.2 compliant `ELResolver` implementation,
integrating with the standard Unified EL as used by JSF 1.2 and JSP 2.1. Like
`SpringBeanVariableResolver`, it delegates to the Spring's 'business context'
`WebApplicationContext` __first__, then to the default resolver of the underlying JSF
implementation.
Configuration-wise, simply define `SpringBeanFacesELResolver` in your JSF 1.2
__faces-context.xml__ file:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<faces-config>
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
...
</application>
</faces-config>
----
[[jsf-facescontextutils]]
=== FacesContextUtils
A custom `VariableResolver` works well when mapping one's properties to beans
in __faces-config.xml__, but at times one may need to grab a bean explicitly. The
{api-spring-framework}/web/jsf/FacesContextUtils.html[`FacesContextUtils`]
class makes this easy. It is similar to `WebApplicationContextUtils`, except that it
takes a `FacesContext` parameter rather than a `ServletContext` parameter.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
----
[[struts]]
== Apache Struts 2.x
Invented by Craig McClanahan, http://struts.apache.org[Struts] is an open source project
hosted by the Apache Software Foundation. At the time, it greatly simplified the
JSP/Servlet programming paradigm and won over many developers who were using proprietary
frameworks. It simplified the programming model, it was open source (and thus free as in
beer), and it had a large community, which allowed the project to grow and become popular
among Java web developers.
Check out the Struts
https://struts.apache.org/release/2.3.x/docs/spring-plugin.html[Spring Plugin] for the
built-in Spring integration shipped with Struts.
[[tapestry]]
== Tapestry 5.x
From the http://tapestry.apache.org/[Tapestry homepage]:
Tapestry is a "__Component oriented framework for creating dynamic, robust,
highly scalable web applications in Java.__"
While Spring has its own <<mvc,powerful web layer>>, there are a number of unique
advantages to building an enterprise Java application using a combination of Tapestry
for the web user interface and the Spring container for the lower layers.
For more information, check out Tapestry's dedicated
https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for
Spring].
[[web-integration-resources]]
== Further Resources
Find below links to further resources about the various web frameworks described in this
chapter.
* The http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF] homepage
* The http://struts.apache.org/[Struts] homepage
* The http://tapestry.apache.org/[Tapestry] homepage

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

279
src/docs/dist/license.txt vendored Normal file
View File

@@ -0,0 +1,279 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=======================================================================
SPRING FRAMEWORK ${version} SUBCOMPONENTS:
Spring Framework ${version} includes a number of subcomponents
with separate copyright notices and license terms. The product that
includes this file does not necessarily use all the open source
subcomponents referred to below. Your use of the source
code for these subcomponents is subject to the terms and
conditions of the following licenses.
>>> ASM 4.0 (org.ow2.asm:asm:4.0, org.ow2.asm:asm-commons:4.0):
Copyright (c) 2000-2011 INRIA, France Telecom
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 1999-2009, OW2 Consortium <http://www.ow2.org/>
>>> CGLIB 3.0 (cglib:cglib:3.0):
Per the LICENSE file in the CGLIB JAR distribution downloaded from
http://sourceforge.net/projects/cglib/files/cglib3/3.0/cglib-3.0.jar/download,
CGLIB 3.0 is licensed under the Apache License, version 2.0, the text of which
is included above.
=======================================================================
To the extent any open source subcomponents are licensed under the EPL and/or
other similar licenses that require the source code and/or modifications to
source code to be made available (as would be noted above), you may obtain a
copy of the source code corresponding to the binaries for such open source
components and modifications thereto, if any, (the "Source Files"), by
downloading the Source Files from http://www.springsource.org/download, or by
sending a request, with your name and address to:
Pivotal, Inc., 875 Howard St,
San Francisco, CA 94103
United States of America
or email info@pivotal.io. All such requests should clearly specify:
OPEN SOURCE FILES REQUEST
Attention General Counsel
Pivotal shall mail a copy of the Source Files to you on a CD or equivalent
physical medium. This offer to obtain a copy of the Source Files is valid for
three years from the date you acquired this Software product.

11
src/docs/dist/notice.txt vendored Normal file
View File

@@ -0,0 +1,11 @@
Spring Framework ${version}
Copyright (c) 2002-${copyright} Pivotal, Inc.
This product is licensed to you under the Apache License, Version 2.0
(the "License"). You may not use this product except in compliance with
the License.
This product may include a number of subcomponents with separate
copyright notices and license terms. Your use of the source code for
these subcomponents is subject to the terms and conditions of the
subcomponent's license, as noted in the license.txt file.

14
src/docs/dist/readme.txt vendored Normal file
View File

@@ -0,0 +1,14 @@
Spring Framework version ${version}
=====================================================================================
To find out what has changed since earlier releases, see the 'Change Log' section at
https://jira.spring.io/browse/SPR
Please consult the documentation located within the 'docs/spring-framework-reference'
directory of this release and also visit the official Spring Framework home at
http://projects.spring.io/spring-framework/
There you will find links to the forum, issue tracker, and other resources.
See https://github.com/spring-projects/spring-framework#readme for additional
information including instructions on building from source.