在Spring框架体系下,可以说规约最少,最不受限制的就是表现层技术了。不像Struts,改定了好多的标签,而且有些功能还和标签绑定了。Sping也定义了一些标签,但这些标签只是给使用者提供了一些方便,并不会提供额外的功能或效果。
Sping Tag比较少,不超过十个,这里只介绍最常用的一个<sping:bind>,也叫作Spring绑定。
下面以一个登陆事例为例,controller使用的是SimpleFormController。
web.xml就不说了,先看/WEB-INF/mvc-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--InternalResourceViewResolver-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!--SimpleUrlHandlerMapping-->
<bean id="urlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index.htm">indexController</prop>
<prop key="/login.htm">loginController</prop>
</props>
</property>
</bean>
<!--ParameterizableViewController-->
<bean id="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName">
<value>login</value>
</property>
</bean>
<!--SimpleFormController-->
<bean id="loginController"
class="com.yangsq.controller.LoginController">
<property name="formView">
<value>login</value>
</property>
<property name="successView">
<value>success</value>
</property>
<property name="commandClass">
<value>com.yangsq.domain.LoginForm</value>
</property>
<property name="sessionForm">
<value>true</value>
</property>
<property name="commandName">
<value>loginForm</value>
</property>
</bean>
</beans>
indexController作用只是把页面转到/WEB-INF/login.jsp,起到逻辑控制的是loginController。其中红色标记的部分就是在页面中绑定是使用的名称,即用loginForm代表这个表单类(使用更多的是command作为commandName的值,但这只是一个代替符号问题)。但是不要认为loginForm仅仅代表这个表单类,实际上它更像一个model,除了表单类,它还包括了其他一些信息,例如错误信息(BinException对象)。
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import com.yangsq.domain.LoginForm;
public class LoginController extends SimpleFormController {
protected ModelAndView onSubmit(Object command, BindException errs) throws Exception {
LoginForm loginForm = (LoginForm) command;
if ("yangsq".equals(loginForm.getUsername()) && "123".equals(loginForm.getPassword())) {
return new ModelAndView(this.getSuccessView(), "username", loginForm.getUsername());
} else {
errs.reject("errCode","用户名或密码错误");
return new ModelAndView(this.getFormView(), errs.getModel());
}
}
}
这是一个逻辑很简单的一个Controller。其中红颜色标记的字体下面会说明。
看登陆页面/WEB-INF/jsp/login.jsp:
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="/WEB-INF/tags/c.tld"%>
<%@ taglib prefix="spring" uri="/WEB-INF/tags/spring.tld" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="cn-zh" />
<title>main</title>
</head>
<BODY>
<FORM action="login.htm" method="post">
<TABLE>
<TBODY>
<TR>
<TD>
<spring:bind path="loginForm.username">
用户名:<INPUT name="${status.expression}" type="text" value="${status.value}"/>
</spring:bind>
</TD>
</TR>
<TR>
<TD>
<spring:bind path="loginForm.password">
密码:<INPUT name="${status.expression}" type="password" value="${status.value}"/>
</spring:bind>
</TD>
</TR>
<TR>
<TD>
<spring:bind path="loginForm.*">
<font color="red"><c:out value="${status.errorMessage}" /></font>
</spring:bind>
</TD>
</TR>
<TR>
<TD align="center">
<INPUT type="submit" value="提交" />
</TD>
</TR>
</TBODY>
</TABLE>
</FORM>
</BODY>
</html>
<sping:bind>的<span style="color:#ff0000;">path属性制定了与表单中的那个属性绑定,这样,${status.expression}就代表了那个属性的名称,${status.expression}代表那个属性的值。如果path属性为“XXX.*”则与那个表单的所有属性绑定。</span>
上面的例子表单有两个属性username和password。实际上绑定方式有两种,第一种就像上面的那样,第二种如下:
......
<spring:bind path="loginForm">
用户名:<INPUT name="username" type="text" value="${loginForm.username}"/><br>
密码:<INPUT name="password" type="password" value="${loginForm.password}"/>
</spring:bind>
......
这种情况input的name属性就不能用${status.expression}代表了。
使用<sping:bind>标签,在初次进入表单页面时并不会有什么作用,而是当表单提交后,如果有BindException错误时再返回这个页面时,可以把先前的输入显示在input里。
好了,现在该来看看对错误(BindException)的处理了。可以看到LoginController中用红色标出的代码。它调用了BindException的reject方法,这样,再调用BindException的getModel()方法,就把错误连同表单等信息一并返回到表单页面用以显示。
reject方法的第一个参数是错误码,如果设定了国际化资源,则显示资源文件中该错误码对应的错误条目,如果没有设定了国际化资源,则显示reject方法的第二个参数。
reject方法的不足之处是在表现层不能区分错误消息属于那个字段,即不能说明是username不对呢还是password不对。解决这种情况可以使用rejectValue方法,这也是更一般使用的方法。rejectValue方法定义如下:
rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage)
第一个参数指定表单的域,即username或password,这样就可以分辨到底是那块出了问题;第二个参数和reject方法的第一个参数一样,制定错误码;第三个参选数制定了资源文件中的占位符;第四个参数和和reject方法的第二个参数一样。rejectValue方法还有一个简化的定义:
rejectValue(String field, String errorCode, String defaultMessage)
上面是在Controller里使用的方法,使用上述方法后,若果出现BindException错误,返回表单页面时就会显示错误信息,那么如何在页面里显示错误信息呢?
上面/WEB-INF/jsp/login.jsp里由于在controller里使用的是reject方法,所以只能那么显示,如果我们使用rejectValue方法,例如改动LoginController:
......
rejectValue("username", "nameErr", null, "用户名错误");
......
rejectValue("password", "passErr", null, "密码错误");
......
这样,就可以把页面改为如下:
......
<spring:bind path="loginForm.username">
用户名:<INPUT name="${status.expression}" type="text" value="${status.value}"/>
<font color="red"><c:out value="${status.errorMessage}" /></font>
</spring:bind>
......
<spring:bind path="loginForm.password">
密码:<INPUT name="${status.expression}" type="password" value="${status.value}"/>
<font color="red"><c:out value="${status.errorMessage}" /></font>
</spring:bind>
这样错误的消息就绑定到相应的字段了。当然也可以不制定某个字段,一股脑都输出
......
<spring:bind path="loginForm.*"><font color="red">错误如下:
<c:forEach items="${status.errorMessages}" var="err">
<c:out value="${err}" />
</c:forEach>
</font>
</spring:bind>
SpringMVC学习笔记--Spring Tag
最新推荐文章于 2021-04-29 09:31:31 发布