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
7
src/docs/api/overview.html
Normal 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
@@ -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;
|
||||
}
|
||||
|
||||
19
src/docs/asciidoc/Guardfile
Normal 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
|
||||
3969
src/docs/asciidoc/appendix.adoc
Normal file
2050
src/docs/asciidoc/appendix/appx-spring-form-tld.adoc
Normal file
496
src/docs/asciidoc/appendix/appx-spring-tld.adoc
Normal 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.
|
||||
|===
|
||||
44
src/docs/asciidoc/core.adoc
Normal 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]
|
||||
|
||||
1750
src/docs/asciidoc/core/core-aop-api.adoc
Normal file
3561
src/docs/asciidoc/core/core-aop.adoc
Normal file
8788
src/docs/asciidoc/core/core-beans.adoc
Normal file
1487
src/docs/asciidoc/core/core-expressions.adoc
Normal file
666
src/docs/asciidoc/core/core-resources.adoc
Normal 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");
|
||||
----
|
||||
|
||||
1639
src/docs/asciidoc/core/core-validation.adoc
Normal file
6686
src/docs/asciidoc/data-access.adoc
Normal file
BIN
src/docs/asciidoc/images/DataAccessException.gif
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
src/docs/asciidoc/images/aop-proxy-call.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/docs/asciidoc/images/aop-proxy-plain-pojo-call.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
src/docs/asciidoc/images/aop-uml.gif
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
src/docs/asciidoc/images/bean-lifecycle-overview.gif
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/docs/asciidoc/images/bind1.jpg
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/docs/asciidoc/images/bind2.jpg
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/docs/asciidoc/images/container-magic.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
src/docs/asciidoc/images/eclipse-setup-1.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
src/docs/asciidoc/images/eclipse-setup-2.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
src/docs/asciidoc/images/eclipse-setup-3.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
src/docs/asciidoc/images/ejb.gif
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/docs/asciidoc/images/ejb.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
95
src/docs/asciidoc/images/ejb.svg
Normal 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 |
BIN
src/docs/asciidoc/images/full.gif
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
src/docs/asciidoc/images/full.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
253
src/docs/asciidoc/images/full.svg
Normal 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 |
BIN
src/docs/asciidoc/images/idea-setup-1.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
src/docs/asciidoc/images/idea-setup-2.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
src/docs/asciidoc/images/idea-setup-3.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
src/docs/asciidoc/images/idea-setup-4.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
src/docs/asciidoc/images/idea-setup-5.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
src/docs/asciidoc/images/idea-setup-6.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
src/docs/asciidoc/images/message-flow-broker-relay.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
src/docs/asciidoc/images/message-flow-simple-broker.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
src/docs/asciidoc/images/mvc-context-hierarchy.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
612
src/docs/asciidoc/images/mvc-context-hierarchy.svg
Normal 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 |
BIN
src/docs/asciidoc/images/mvc-root-context.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
328
src/docs/asciidoc/images/mvc-root-context.svg
Normal 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 |
BIN
src/docs/asciidoc/images/mvc.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
3559
src/docs/asciidoc/images/overview-ejb.graffle
Normal file
BIN
src/docs/asciidoc/images/overview-ejb.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
4884
src/docs/asciidoc/images/overview-full.graffle
Normal file
BIN
src/docs/asciidoc/images/overview-full.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
4410
src/docs/asciidoc/images/overview-remoting.graffle
Normal file
BIN
src/docs/asciidoc/images/overview-remoting.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
5410
src/docs/asciidoc/images/overview-thirdparty-web.graffle
Normal file
BIN
src/docs/asciidoc/images/overview-thirdparty-web.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
1619
src/docs/asciidoc/images/oxm-exceptions.graffle
Normal file
BIN
src/docs/asciidoc/images/oxm-exceptions.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
src/docs/asciidoc/images/prototype.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
src/docs/asciidoc/images/remoting.gif
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/docs/asciidoc/images/remoting.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
129
src/docs/asciidoc/images/remoting.svg
Normal 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 |
BIN
src/docs/asciidoc/images/singleton.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
src/docs/asciidoc/images/spring-overview.gif
Normal file
|
After Width: | Height: | Size: 19 KiB |
4787
src/docs/asciidoc/images/spring-overview.graffle
Normal file
BIN
src/docs/asciidoc/images/spring-overview.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
196
src/docs/asciidoc/images/spring-overview.svg
Normal 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 |
BIN
src/docs/asciidoc/images/spring-overview.vsd
Normal file
BIN
src/docs/asciidoc/images/spring.sxd
Normal file
BIN
src/docs/asciidoc/images/thirdparty-web.gif
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/docs/asciidoc/images/thirdparty-web.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
131
src/docs/asciidoc/images/thirdparty-web.svg
Normal 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 |
BIN
src/docs/asciidoc/images/tx.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
src/docs/asciidoc/images/tx_prop_required.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
src/docs/asciidoc/images/tx_prop_requires_new.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
src/docs/asciidoc/images/webflux-overview.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
19
src/docs/asciidoc/index.adoc
Normal 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>>
|
||||
9104
src/docs/asciidoc/integration.adoc
Normal file
865
src/docs/asciidoc/overview.adoc
Normal 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.
|
||||
|
||||
|
||||
691
src/docs/asciidoc/stylesheets/spring.css
Normal 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; }
|
||||
5249
src/docs/asciidoc/testing.adoc
Normal file
35
src/docs/asciidoc/web.adoc
Normal 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]
|
||||
244
src/docs/asciidoc/web/web-cors.adoc
Normal 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.
|
||||
244
src/docs/asciidoc/web/web-flux-functional.adoc
Normal 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.
|
||||
393
src/docs/asciidoc/web/web-flux.adoc
Normal 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`]
|
||||
249
src/docs/asciidoc/web/web-integration.adoc
Normal 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
|
||||
|
||||
5762
src/docs/asciidoc/web/web-mvc.adoc
Normal file
2139
src/docs/asciidoc/web/web-view.adoc
Normal file
2424
src/docs/asciidoc/web/web-websocket.adoc
Normal file
279
src/docs/dist/license.txt
vendored
Normal 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
@@ -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
@@ -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.
|
||||