spring(6) 渲染web视图

【0】README
1)本文部分文字描述转自:“Spring In Action(中/英文版)”,旨在review  “spring(6) 渲染web视图” 的相关知识;
 
【1】 理解视图解析
【1.1】视图解析的基础知识以及spring 提供的其他视图解析器
1)spring mvc 定义了一个名为 ViewResolver的接口,如下
public interface ViewResolver {View resolveViewName(String viewName, Locale locale)throws Exception;
} 
2)当给 resolveViewName()方法传入一个视图名和Locale对象时,它会返回一个View实例。View是另外一个接口:
public interface View {
String getContentType();void render(Map<String, ?> model,HttpServletRequest request,HttpServletResponse response) throws Exception;
} 
代码分析:View接口的任务就是接受模型以及 servlet的request 和 response对象,并将输出结果渲染到 response;
3)spring自带了13个视图解析器

对上表的分析(Analysis):
A1)InternalResourceViewResolver: 用于 JSP, TilesViewResolver用于Apache Tiles 视图, FreeMarkerViewResolver and VelocityViewResolver 分别用于 FreeMaker 和 Velocity模板视图;
A2)Thymeleaf: 是一种用来替代JSP 的新兴技术,spring提供了与 Thymeleaf 的原生模板协作的视图解析器;这种模板之所以得到这样的称呼是因为它更像最终产生的HTML,而不是驱动它们的java 代码;

 
【2】创建JSP视图
1)spring提供了两种支持 JSP 的视图(type)
type1)InternalResourceViewResolver 会将视图名解析为 jsp 文件;如果在jsp页面中使用了 JSP 标准标签库(java server page standard tag library)的话,InternalResourceViewResolver 能够将视图名解析为 JstlView 形式的jsp 文件,从而将JSTL 本地化和资源 bundle变量暴露给 JSTL 的格式化和信息标签;
type2)spring提供了两个JSP 标签库: 一个用于表单到模型的绑定,另一个提供了通用的工具类特性;
【2.1】配置适用于JSP的视图解析器
1)看个荔枝:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages={"com.spring.chapter5.spittr.web","com.spring.chapter5.spittr.data"})
public class WebConfig extends WebMvcConfigurerAdapter {@Beanpublic ViewResolver viewResolver() { // highlight line.InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");resolver.setExposeContextBeansAsAttributes(true);return resolver;}@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
} 
【2.1.1】解析JSTL 视图(jsp standard tag lib-java标准库标签)
1)intro: InternalResourceViewResolver 最终会将逻辑视图名解析为 InternalResourceView 实例,这个实例会引用jsp文件;
2)如果想让InternalResourceViewResolver  将视图解析为 JstlView,而不是 InternalResourceView 实例的话,只需要设置它的 viewClass属性即可:
@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);return resolver;}
3)同样,在xml中的配置为:
<bean id="viewResolver"class="org.springframework.web.servlet.view. InternalResourceViewResolver" p:prefix="/WEB-INF/views/"p:suffix=".jsp"p:viewClass="org.springframework.web.servlet.view.JstlView" /> <span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);"> </span>

【2.2】使用 spring 的 jsp库
1)标签库的作用: 能够避免在脚本块中直接编写 java 代码;(干货——标签库的作用)
2)spring提供了两个JSP 标签库:一个用于表单到模型的绑定,另一个提供了通用的工具类特性;
 
【2.2.1】将表单绑定到模型上
1)intro:spring 的表单绑定jsp 标签库包含了14个标签,他们中的大多数都用用来渲染HTML 中的表单标签;
2)为了使用表单标签库,需要在jsp 页面上对其声明;
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>


 3)在注册JSP 中使用这些标签后,会得到如下程序:<sf:form method="POST" commandName="spitter">

  First Name: <sf:input path="firstName" /><br />Last Name: <sf:input path="lastName" /><br />Email: <sf:input path="email" /><br />Username: <sf:input path="username" /><br />Password: <sf:password path="password" /><br /><input type="submit" value="Register" /></sf:form> 

代码分析(Analysis): <sf:form>标签 会渲染为一个 HTML<form> 标签,通过 commandName 属性构建针对某个模型对象的上下文信息;这就需要我们必须要有一个key==spitter的对象;

 
4)我们可以指定email 域:
Email: <sf:input path="email" type="email" /><br/> 
4.1)得到的 HTML 如下所示:
Email:  <input id="email" name="email" type="email" value="jack"/><br/> 

5)为了矫正用户输入错误,需要使用 标签 <sf:errors>
 
【2.2.2】展现错误
1)将 <sf:errors> 用到 registerForm.jsp 中的代码片段中;
<sf:form method="POST" commandName="spitter">First Name: <sf:input path="firstName" /><sf:errors path="firstName" /><br/>...
</sf:form> 
代码分析(Analysis): 这里path 属性设置为 firstName,即指定了要显示 Spitter 模型对象中哪个属性的的错误;
 
看个荔枝)如果用户提交字母”J“的话,那么如下的HTML 片段就是针对 firstName 输入域所显示的内容:
First Name: <input id="firstName"name="firstName" type="text" value="J"/>
<span id="firstName.errors">size must be between 2 and 30</span> 
2)进一步修改错误的样式,使其更加突出显示;设置 cssClass属性:
<sf:form method="POST" commandName="spitter">First Name: <sf:input path="firstName" /><sf:errors path="firstName" cssClass="error" /><br />
...
</sf:form>
2.1)再定义一个css样式:
span.error {color: red;
} 

3)problem+solution:
3.1)problem:在输入域的旁边展现错误信息是一种很好的方式,但是会带来布局问题;
3.2)solution:将所有的错误信息都 在同一个地方进行显示;我们可以移除每个输入域上的 <sf:errors> 元素,并将其放到表单的顶部,如下所示:
<sf:form method="POST" commandName="spitter" ><sf:errors path="*" element="div" cssClass="errors" />...
</sf:form> 
对以上代码分析(Analysis):这里的paht被设置为了 “*”,这是一个通配符选择器;会告诉 <sf: errors> 展现所有属性的所有错误;

4)通过为每个输入域设置 cssErrorClass 属性,显示需要修正的输入域;
<sf:form method="POST" commandName="spitter"><sf:label path="firstName" cssErrorClass="error">First Name</sf:label>:<sf:input path="firstName" cssErrorClass="error" /><br />...
</sf:form> 
对以上代码的分析(Analysis):
A1)<sf:label> 标签:使用path 来指定它属于模型对象中的 哪个属性;在本例中,将其设置为 firstName,它会绑定 spitter对象的 firstName属性;
A2)如果校验错误的话,渲染得到 的<label>元素中,class属性将会被设置为 error:
<label for="firstName" class="error">First Name</label> 
A3)还可以设置一些css 属性 
label.error {color: red;
}
input.error {} 

5)如何让错误信息更加易读。可以在校验注解上设置 message属性,使其引用对用户更为友好的信息,这些信息定义在属性文件中;并将该属性文件放在根目录下;
// ValidationMessages.properties 文件内容如下(放置在根类路径下,即 project/src/ 目录下):
firstName.size=First name must be between {min} and {max} characters long.
lastName.size=Last name must be between {min} and {max} characters long.
username.size=Username must be between {min} and {max} characters long.
password.size=Password must be between {min} and {max} characters long.
email.valid=The email address must be valid. 

【2.2.3】spring 通用的标签库
1)要使用spring通用的标签库,在页面上对其进行声明;
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %> 
2)spring的jsp 标签库提供了多个便利的标签;
 

【2.2.4】展现国际化消息
1)考虑首页info:
<h1>Welcome to Spittr!</h1>  
1.1)考虑将其国际化,<s:message>标签就是一个很好地方案;
<h1><s:message code="spittr.welcome" /></h1> 
对以上代码的分析(Analysis):该标签将会工具  key=spittr.welcome 的信息源来渲染文本;
1.2)spring有多个信息源类,都实现了 MessageSource接口,最为常见的是ResourceBundleMessageSource.
1.3)intro to ResourceBundleMessageSource:它会从属性文件中加载信息,该属性文件的名称根据基础名称(base name)衍生而来的。如下的 @Bean 方法配置了 ResourceBundleMessageSource:
@Beanpublic MessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasename("messages"); // 核心在于设置basename属性值.return messageSource;} 
对以上代码的分析(Analysis):将basename属性值设置为 messages后,SourceBundleMessageSource就会视图在根路径的属性文件中解析信息,这些属性文件的名称是根据这个基础名称衍生得到的;

1.4)还可以使用ReloadableResourceBundleMessageSource,它能够重新加载信息属性,而不必重新编译或重启应用,其配置如下:
@Beanpublic MessageSource messageSource() {ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();messageSource.setBasename("file:///etc/spittr/messages");messageSource.setCacheSeconds(10);return messageSource;} 
对以上代码的分析(Analysis):
A1)关键区别在于 basename 属性设置为在应用的外部查找(而不是像 ResourceBundleMessageSource 在类路径下查找);
A2)basename的属性可以设置在类路径下,文件系统中或web 应用的根路径下查找属性;

2)创建属性文件
2.1)创建默认的属性文件,名为 messages.properties:它要么位于根路径下(使用ResourceBundleMessageSource),要么位于pathname属性指定的路径下 (使用ReloadableResourceBundleMessageSource);
2.2)对于 spittr.welcome 信息来讲,需要如下条目:
spittr.welcome=Welcome to Spittr!
2.3)problem+solution:
2.3.1)problem:如果你不再创建其他信息文件的话,我们所做的事情就是将jsp中硬编码的信息抽取到了属性文件中,仍然是硬编码;
2.3.2)solution:如果想要设置西班牙语的话,需要创建另外一个 名为 message_es.properties 的属性文件
spittr.welcome=Bienvenidos a Spittr!
 

【2.2.5】创建URL
1)intro:<s:url>的主要任务就是创建 URL,然后将其赋值给一个变量或渲染到相应中, 它是 JSTL 中 <c:url> 标签的替代者;(干货——<s:url> 是 JSTL 中 <c:url> 标签的替代者)
2)看几个荔枝:
2.1)<a href="<s:url href="/spitter/register" />">Register</a>,如果应用的servlet上下文名为 spittr,则 <s:url> 将会渲染为:
<a href="/spittr/spitter/register">Register</a> 
2.2)将<s:url> 进行赋值,并使用: 
<s:url href="/spitter/register" var="registerUrl" />
<a href="${registerUrl}">Register</a> 

2.3)default case, URL是在页面作用域内创建的。但通过设置scope 属性,可以让 <s:url> 在应用作用域内,会话作用域内或请求作用域内创建URL:(干货——default case,URL是在页面作用域内创建的)
<s:url href="/spitter/register" var="registerUrl" scope="request" /> 
2.4)如果希望添加参数的话,使用 <s:param>标签;
<s:url href="/spittles" var="spittlesUrl"><s:param name="max" value="60" /><s:param name="count" value="20" />
</s:url> 
3)各种需求组团袭来
3.1)假设我们要为特定用户的基本信息页面创建一个URL,<s:param> 标签可以承担此任; (干货——这里用到了占位符{username})
<s:url href="/spitter/{username}" var="spitterUrl"><s:param name="username" value="jbauer" />
</s:url> 
3.2)解决URL 的转义需求:希望将渲染得到的URL 内容展现在 web 页面上(而不是作为超链接),这就要求 <s:url> 进行HTML 转义,将 htmlEscape属性设置为 true;
<s:url value="/spittles" htmlEscape="true"><s:param name="max" value="60" /><s:param name="count" value="20" />
</s:url>
所渲染得到的结果为:
/spitter/spittles?max=60&count=20 
3.3)解决在 javascript中使用URL的话,应该将 javascriptEscape 属性设置为 true;
<s:url value="/spittles" var="spittlesJSUrl" javaScriptEscape="true"><s:param name="max" value="60" /><s:param name="count" value="20" />
</s:url>
<script>var spittlesUrl = "${spittlesJSUrl}"
</script>渲染得到的结果为:
<script>var spittlesUrl = "\/spitter\/spittles?max=60&count=20"
</script> 
【2.2.6】转义内容(<s:escapeBody> 标签)
1)intro:<s:escapeBody> 标签是一个转义标签;
2)任务来啦:
2.1)任务一:需要将  "<" and ">" 字符替换为 &lt, &gt;<s:escapeBody> 可以做到这一点;
<s:escapeBody htmlEscape="true"><h1>Hello</h1>
</s:escapeBody>
所渲染得到的结果为:
&lt;h1&gt;Hello&lt;/h1&gt; 

2.2)通过设置 javaScriptEscape属性,<s:escapeBody> 标签还支持 JavaScript 转义:
<s:escapeBody javaScriptEscape="true"><h1>Hello</h1>
</s:escapeBody> 
【3】使用 Apache Tiles视图定义布局
1)intro:为了更好的定义视图布局,引入了布局引擎,如Apache Tiles;(干货——引入了布局引擎);
【3.1】配置 Tiles 视图解析器
1)intro:为了在spring 中使用 Tiles,需要配置几个 bean
1.1)需要一个 TilesConfigurer bean:负责定位和加载 Tile 定义并协调生成 Tiles;
1.2)还需要TilesViewResolver bean: 将逻辑视图名称解析为 Tile定义;
2)设置的具体操作:
2.1)需要一个 TilesConfigurer bean:负责定位和加载 Tile 定义并协调生成 Tiles;
@Beanpublic TilesConfigurer tilesConfigurer() {TilesConfigurer tiles = new TilesConfigurer();tiles.setDefinitions(new String[] {"/WEB-INF/layout/tiles.xml"});tiles.setCheckRefresh(true);return tiles;}
对以上代码的分析(Analysis):
A1)所要设置的最重要的属性是 definitions:这个属性接收一个 string 类型的 数组,其中每个条目都指定一个 Tile定义的 xml 文件;
A2)我们可以在数组中指定多个文件,并使用通配符;
tiles.setDefinitions(new String[] {"/WEB-INF/**/tiles.xml"
}); 
对以上代码的分析(Analysis): 
A1)我们要求 TilesConfigurer  加载 /WEB-INF/ 目录下的所有名字为 tiles.xml 的文件;
A2)上述代码使用了 Ant 风格的通配符(**); 

2.2)还需要TilesViewResolver bean: 将逻辑视图名称解析为 Tile定义;
@Bean
public ViewResolver viewResolver() {return new TilesViewResolver();
} 
通过XML 配置的代码如下:
<bean id="tilesConfigurer"class="org.springframework.web.servlet.view.tiles3.TilesConfigurer"><property name="definitions"><list><value>/WEB-INF/layout/tiles.xml.xml</value><value>/WEB-INF/views/**/tiles.xml</value></list></property>
</bean>
<bean id="viewResolver"class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" /> 
Conclusion)
C1)TilesConfigurer 会加载 Tile定义并与 Apache Tiles协作;
C2)而 TilesViewResolver 会将逻辑视图名称解析为引用 Tile 定义的视图。它是通过查找与 逻辑视图名称相匹配的Tile 定义实现该功能的;
 
【3.1.1】 定义Tiles
1)intro:Apache Tiles 提供了一个文档类型定义(document type definition, DTD),用来在 XML文件中指定Tile的定义。每个定义中需要包含一个 <definition> 元素,这个元素会有一个或多个 <put-attribute>元素;
2)看个荔枝:如下的xml 文档为 Spittr 应用定义了几个 Tile:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN""http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions><definition name="base" template="/WEB-INF/layout/page.jsp"><put-attribute name="header" value="/WEB-INF/layout/header.jsp" /><put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" /></definition><definition name="home" extends="base">  // hightlight line: 这里用到了继承,碉堡了.<put-attribute name="body" value="/WEB-INF/views/home.jsp" /></definition><definition name="registerForm" extends="base"><put-attribute name="body" value="/WEB-INF/views/registerForm.jsp" /></definition><definition name="profile" extends="base"><put-attribute name="body" value="/WEB-INF/views/profile.jsp" /></definition><definition name="spittles" extends="base"><put-attribute name="body" value="/WEB-INF/views/spittles.jsp" /></definition><definition name="spittle" extends="base"><put-attribute name="body" value="/WEB-INF/views/spittle.jsp" /></definition></tiles-definitions> 
对以上代码的分析(Analysis):
A1)每个 <definition> 元素都定义了一个 Tile,它最终引用的是一个 JSP 模板;
A2)某个 Tile 可能还引用其他的JSP模板,对于base Tile 来讲,引用的是一个头部 jsp 模板 和 一个底部 jsp 模板;
 
3)base Tile 所引用的page.jap 模板如下面程序清单所示:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %><%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<%@ page session="false" %>
<html><head><title>Spittr</title><link rel="stylesheet" type="text/css" href="<s:url value="/resources/style.css" />" ></head><body><div id="header"><t:insertAttribute name="header" /></div><div id="content"><t:insertAttribute name="body" /></div><div id="footer"><t:insertAttribute name="footer" /></div></body>
</html> 
对以上代码的分析(Analysis):重点在于 使用 Tile标签库中的 <t:insertAttribute> jsp 标签来插入其他的模板;插入了 header, body,  footer 的模板;
 

【4】 使用Thymeleaf 模板
1)problem+solution:
1.1)problem:jsp最明显的问题:在于它看起来像 HTML 或 XML,但它其实并不是。大多数的jsp 模板都采用了HTML 的形式,但 又掺杂了各种jsp 标签库的标签,使其变得很是混乱;
1.2)solution:Thymelead模板:能在接收原始HTML 的地方进行编辑和渲染。因为它没有和 servlet规范耦合,因此 Thymeleaf 模板能够进入jsp 所无法涉足的领域;
 
【4.1】配置 Thymeleaf 视图解析器
1)intro:为了要在spring中 使用 Thymeleaf,我们要配置三个启用 Thymeleaf 与 spring集成的bean;
1.1)ThymeleafViewResolver:将逻辑视图名解析为 Thymeleaf 模板视图;
1.2)SpringTemplateEngine:处理模板并渲染结果;
1.3)TemplateResolver: 加载 Thymeleaf模板;

2)如下是声明这些bean 的 java配置;
@Beanpublic ViewResolver viewResolver(SpringTemplateEngine templateEngine) {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setTemplateEngine(templateEngine);return viewResolver;}@Beanpublic TemplateEngine templateEngine(TemplateResolver templateResolver) {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver);return templateEngine;}@Beanpublic TemplateResolver templateResolver() {TemplateResolver templateResolver = new ServletContextTemplateResolver();templateResolver.setPrefix("/WEB-INF/templates/");templateResolver.setSuffix(".html");templateResolver.setTemplateMode("HTML5");return templateResolver;} 
2.1)通过XML 声明这些bean 的java配置
<bean id="viewResolver" class="org.thymeleaf.spring3.view.ThymeleafViewResolver"p:templateEngine-ref="templateEngine" />
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine"p:templateResolver-ref="templateResolver" />
<bean id="templateResolver"class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"p:prefix="/WEB-INF/templates/" p:suffix=".html" p:templateMode="HTML5" />
Conclusion)不管采用何种配置,Thymeleaf都可以将响应中的模板渲染到 spring mvc 控制器所处理的请求中;
 
3)ThymeleafViewResolver
3.1)intro:ThymeleafViewResolver 是 spring mvc 中 ViewResolver的一个实现类;
3.2)需要注意的是:ThymeleafViewResolver bean 中注入了一个对  SpringTemplateEngine bean 的引用;
3.2)SpringTemplateEngine 会在spring中启用 Thymeleaf引擎,用来解析模板,并基于这些模板渲染结果;
3.4)TemplateResolver会最终定位和查找模板,它也使用了prefix 和 suffix 属性。前缀和后缀将会与 逻辑视图名组合使用,进而定位 Thymeleaf 引擎,它的templateMode属性被设置为 HTML5,这表明我们预期要解析的模板会渲染成 HTML5 输出;
 
【4.2】定义 Thymeleaf 模板
1)intro: Thymeleaf之所以能够发挥作用,是因为它通过自定义的命名空间,为标准的HTML 标签集合添加 Thymeleaf属性;
2)使用 Thymeleaf模板的 home.html源码
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head><title>Spittr</title><link rel="stylesheet" type="text/css" th:href="@{/resources/style.css}"></link>
</head>
<body><h1>Welcome to Spittr</h1><a th:href="@{/spittles}">Spittles</a> |<a th:href="@{/spitter/register}">Register</a>
</body>
</html> 
 

【4.2.1】借助Thymeleaf实现表单绑定
1)review 表单绑定
1.1) 下面展现了在 registration.jsp 中的firname 输入域:
<sf:label path="firstName"cssErrorClass="error">First Name</sf:label>:
<sf:input path="firstName" cssErrorClass="error" /><br/>

2)考虑如下的 Thymeleaf模板片段,它会渲染first name输入域:

<label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>:
<input type="text" th:field="*{firstName}"th:class="${#fields.hasErrors('firstName')}? 'error'" /><br/>

对以上代码分析(Analysis):

A1)不再使用jsp 标签中的 cssClassName 属性,而是在标准的HTML 标签中上使用 th:class 属性;th:class 属性会渲染成为一个 class属性;
A2)<input> 标签使用了 th:field 属性,用来引用后端对象的 firstname域;
3)以下代码暂时了完整的注册表单模板
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="POST" th:object="${spitter}"><div class="errors" th:if="${#fields.hasErrors('*')}">
<ul>
<li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input
is incorrect</li>
</ul>
Listing 6.7 Registration page, using Thymeleaf to bind a form to a
command object Display errors 192 CHAPTER 6 Rendering web views
</div>
<label th:class="${#fields.hasErrors('firstName')}? 'error'">
First Name</label>: <input type="text" th:field="*{firstName}"
th:class="${#fields.hasErrors('firstName')}? 'error'" /><br /> <label
th:class="${#fields.hasErrors('lastName')}? 'error'"> Last
Name</label>: <input type="text" th:field="*{lastName}"
th:class="${#fields.hasErrors('lastName')}? 'error'" /><br /> <label
th:class="${#fields.hasErrors('email')}? 'error'"> Email</label>: <input
type="text" th:field="*{email}"
th:class="${#fields.hasErrors('email')}? 'error'" /><br /> <label
th:class="${#fields.hasErrors('username')}? 'error'">
Username</label>: <input type="text" th:field="*{username}"
th:class="${#fields.hasErrors('username')}? 'error'" /><br /> <label
th:class="${#fields.hasErrors('password')}? 'error'">
Password</label>: <input type="password" th:field="*{password}"
th:class="${#fields.hasErrors('password')}? 'error'" /><br /> <input
type="submit" value="Register" />
</form>
</body>
</html>

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring思维导图,让Spring不再难懂(aop篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;aop篇&#xff09; 什么是aop AOP&#xff08;Aspect-OrientedProgramming&#xff0c;面向方面编程&#xff09;&#xff0c;可以说是OOP&#xff08;Object-Oriented Programing&#xff0c;面向对象编程&…

tomcatSupplement(1)tomcat启动脚本分析(以Windows平台为例)

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“深入剖析tomcat”&#xff0c;旨在学习“tomcat启动脚本分析” 的相关知识&#xff1b;2&#xff09;for tomcat4 startup files&#xff0c; please visit https://github.com/pacosonTang/HowTomcatWorks/tree/ma…

Spring思维导图,让spring不再难懂(一)

转载自 Spring思维导图&#xff0c;让spring不再难懂&#xff08;一&#xff09; 摘要: Spring是一个开源框架&#xff0c;是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构&#xff0c;分层架构允许您选择使用哪一个组件&#xff0c;同时为 J2EE …

spring(7)spring mvc 的高级技术

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(7)spring mvc 的高级技术” 的相关知识&#xff1b;2&#xff09;本文将会看到如何编写控制器来处理文件上传&#xff0c;如…

Ubuntu下MySQL、Redis以及MongoDB三个数据库的启动、重启以及停止命令

一、MySQL #启动 /etc/init.d/mysql start #停止 /etc/init.d/mysql stop #重启 /etc/init.d/mysql restart 二、Redis #启动 redis-server #停止 pkill redis-server三、MongoDB #启动服务 sudo service mongod start #重启 sudo service mongod restart #终止 sudo serv…

Spring思维导图,让Spring不再难懂(mvc篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;mvc篇&#xff09;spring mvc简介与运行原理Spring的模型-视图-控制器&#xff08;MVC&#xff09;框架是围绕一个DispatcherServlet来设计的&#xff0c;这个Servlet会把请求分发给各个处理器&#xff0c;并支持…

spring(10)通过spring 和 JDBC征服数据库

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(10)通过spring 和 JDBC征服数据库” 的相关知识&#xff1b;【1】 spring 的数据访问哲学1&#xff09;intro&#xff1a;s…

Ubuntu下apt-get方式Git的安装、配置和更新

一、首先命令行下载Git sudo apt-get update sudo apt-get install git 通过此种方式安装的git可能不是官方的最新版本&#xff0c;通过 git --version 查看版本信息&#xff0c;然后与git官网比对官网下载地址 二、然后配置git的帐号信息 git config --global user.name &q…

Spring思维导图,让Spring不再难懂(cache篇)

转载自 Spring思维导图&#xff0c;让Spring不再难懂&#xff08;cache篇&#xff09; 关于缓存 缓存是实际工作中非常常用的一种提高性能的方法。而在java中&#xff0c;所谓缓存&#xff0c;就是将程序或系统经常要调用的对象存在内存中&#xff0c;再次调用时可以快速从内存…

intro to JNDI

【0】README 1&#xff09;本文转自 http://sishuok.com/forum/blogPost/list/1186.html 【1】原文如下 1&#xff09;JNDI 是什么&#xff1f; JNDI是 Java 命名与目录接口&#xff08;Java Naming and Directory Interface&#xff09;&#xff0c;在J2EE规范中是重要的规范之…

Mybatis3配置方法

一.准备 1.三个Jar包&#xff0c; 1.mybatis-3.2.1.jar 2.mysql-connector-java-5.1.12-bin.jar 3.log4j-1.2.17.jar 2.vo类对象 public class SysUser {private Long id;private String name;private String loginName;private String password;private String avatar;/** ge…

小白学数据:教你用Python实现简单监督学习算法

转载自 小白学数据&#xff1a;教你用Python实现简单监督学习算法今天&#xff0c;文摘菌想谈谈监督学习。监督学习作为运用最广泛的机器学习方法&#xff0c;一直以来都是从数据挖掘信息的重要手段。即便是在无监督学习兴起的近日&#xff0c;监督学习也依旧是入门机器学习的钥…

Spring_01_IoC初级总结

1.IoC简介 (转载) (原文&#xff1a;http://jinnianshilongnian.iteye.com/blog/1413846) via:jinnianshilongnian 1.1、IoC是什么 Ioc—Inversion of Control&#xff0c;即“控制反转”&#xff0c;不是什么技术&#xff0c;而是一种设计思想。在Java开发中&#xff0c;Io…

深度学习工具caffe详细安装指南

转载自 深度学习工具caffe详细安装指南前言&#xff1a; 在一台系统环境较好的linux机器上可以很容易的安装caffe&#xff0c;但是如果系统本身很旧&#xff0c;又没有GPU的话&#xff0c;安装就太麻烦了&#xff0c;所有都得从头做起&#xff0c;本文档旨在尽可能覆盖安装所要…

Spring_02_AOP初级总结

1.AOP简介 是对OOP编程方式的一种补充。翻译过来为“面向切面编程”。 可以理解为一个拦截器框架&#xff0c;但是这个拦截器会非常武断&#xff0c;如果它拦截一个类&#xff0c;那么它就会拦截这个类中的所有方法。如对一个目标列的代理&#xff0c;增强了目标类的所有方法…

spring(11)使用对象-关系映射持久化数据

【0】README1&#xff09;本文部分文字描述转自&#xff1a;“Spring In Action&#xff08;中/英文版&#xff09;”&#xff0c;旨在review “spring(11)使用对象-关系映射持久化数据” 的相关知识&#xff1b;【2】spring 与 java 持久化API1&#xff09;intro&#xff1a;…

漫画:什么是数据仓库

转载自 玻璃猫 算法与数据结构一个故事 在很久很久以前&#xff0c;世界上生活着许多种族&#xff0c;有人类&#xff0c;有矮人&#xff0c;有精灵......他们有着不同的信仰&#xff0c;不同的文化&#xff0c;彼此相安无事。可是&#xff0c;有一个猥琐男却偏偏想要统治整个世…

SpringMVC_初级总结

1.SpringMVC的工作原理 浏览器发出一个http请求给服务器&#xff0c;如果匹配DispatcherServlet的请求映射路径&#xff08;在web.xml中指定&#xff09;&#xff0c;服务器将请求转交给DispatcherServlet.DipatcherServlet接收到这个请求之后&#xff0c;根据请求的路径&#…

tomcat中配置jndi数据源以便spring获取

【0】README0&#xff09;intro to jndi&#xff0c; plase visit intro to jndi&#xff1b;1&#xff09;本文译自 Configuring Spring MVC JdbcTemplate with JNDI Data Source in Tomcat&#xff1b;2&#xff09;本文旨在分析如何通过springmvc 获取 JNDI 数据源 以连接到…

Machine Learning:十大机器学习算法

转载自 Machine Learning&#xff1a;十大机器学习算法摘要: - 机器学习算法分类&#xff1a;监督学习、无监督学习、强化学习 - 基本的机器学习算法&#xff1a;线性回归、支持向量机(SVM)、最近邻居(KNN)、逻辑回归、决策树、k平均、随机森林、朴素贝叶斯、降维、梯度增强 机…