61阅读

Spring MVC-spring mvc EL ModelAndView的 Model 值 在jsp中不显示

发布时间:2017-11-16 所属栏目:modelandview

一 : spring mvc EL ModelAndView的 Model 值 在jsp中不显示

问题:
spring mvc开发过程中, 经常会给model addAttribute, 然后通过EL在jsp中显示,比如 ${msg},
但是有时候会出现jsp最后显示的还是${msg},而不是msg赋值过的。

Spring Controller


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class ABCController extends AbstractController{

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {

ModelAndView model = new ModelAndView("HelloWorldPage");
model.addObject("msg", "hello world");

return model;
}

}
JSP page


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


${msg}


解决方法:
原因在于老的JSP 1.2 声明.


1. JSP 1.2
如果你用的jsp1.2版本的DTD
web.xml

"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">


//...

EL是默认关闭的。。。必须手动打开。<%@ page isELIgnored="false" %>


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<%@ page isELIgnored="false" %>


${msg}




2. JSP 2.0
JSP2.0默认是打开支持EL的,所以声明jsp2.0就可以直接用了。
web.xml

xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
//...

二 : Spring MVC简介

1.Spring MVC简介

Spring MVC框架是有一个MVC框架,通过实现Model-View-Controller模式来很好地将数据、业务与展现进行分离。(www.61k.com)从这样一个角度来说,Spring MVC和Struts、Struts2非常类似。Spring MVC的设计是围绕DispatcherServlet展开的,DispatcherServlet负责将请求派发到特定的handler。通过可配置的handler mappings、view resolution、locale以及theme resolution来处理请求并且转到对应的视图。Spring MVC请求处理的整体流程如图:

springmvc Spring MVC简介

Spring3.x中定义一个控制器类,必须以@Controller注解标记。当控制器类接收到一个请求时,它会在自己内部寻找一个合适的处理方法来处理请求。使用@RequestMapping注解将方法映射到一些请求上,以便让该方法处理那些请求。这种方法就像一般的类中的方法,方法名参数列表和返回值并不像Struts2之类的框架有很强的限制。方法参数列表具体以及返回值具体都有哪些,这里先不细说。这篇博客的目的在于简单介绍如何快速上手使用Spring MVC框架。

控制器在选择好适合处理请求的方法时,传入收到的请求(根据方法参数类型,可能以不同的类型传入),并且调用该方法中的逻辑来进行处理(也可以是调用Service来真正处理)。方法逻辑可能也会在参数中添加或者删除数据。处理方法处理完之后,会委派给一个视图,由该视图来处理方法的返回值。处理程序的返回值并不代表视图的具体实现,可以只是String类型,代表视图名,甚至是void(这时候Spring MVC可以根据方法名或者控制器名找默认视图)。也不需要担心返回值只是视图名称的话,视图拿不到要显示的数据。因为方法参数对于视图来说也是可以拿到的。比如说,如果处理方法以Map为参数,那么这个Map对于视图也是可以拿到的。

返回的视图名称会返回给DispatcherServlet,它会根据一个视图解析器将视图名称解析为一个具体的视图实现。这里说到的视图解析器是一个实现了ViewResolver借口的Bean,它的任务就是返回一个视图的具体实现(HTML、JSP、PDF等等).

2.Spring MVC版本的helloworld

接下来我们用Spring MVC开发一个最最简单的Web应用。首先创建一个Dynamic Web Project。为了方便起见,我们将Spring dist目录下的所有jar包放到WEB-INF/lib目录下。这里我是用的是Spring3.1.x版本。此外还需要添加commons-logging包。

接下来在web.xml文件中配置DispatcherServlet,在web.xml文件中添加如下片段:

<servlet> 	<servlet-name>hello</servlet-name> 	<servlet-class>  org.springframework.web.servlet.DispatcherServlet 	</servlet-class> 	<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> 	<servlet-name>hello</servlet-name> 	<url-pattern>/</url-pattern> </servlet-mapping>

这里我们将DispatcherServlet命名为hello,并且让它在web项目一启动就加载。接下来我们需要在WEB-INF目录下创建一个hello-servlet.xml的Spring配置文件。Spring官方文档上推荐的默认的文件名是[servlet-name]-servlet.xml文件,这里servlet-name叫hello,因此,这个文件也就是叫hello-servlet.xml。在这个文件中可以定义各种各样的Spring MVC需要使用的Bean。需要说明的是,对于整个Web项目中的Spring配置文件中定义的Bean在这个配置文件中是可以继承的,反过来不成立。上面我们将所有的请求都交给DispatcherServlet。

现在我们定义一个控制器类HelloController:

package springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HelloController {  @RequestMapping(value="/hello",method=RequestMethod.GET) 	public String sayHello(Model model) {  model.addAttribute("msg", "Hello, World!");  return "hello"; 	} }

首先通过@Controller注解标示这个类是一个控制器,接下来通过@RequestMapping注解为制定方法sayHello处理哪些请求,在这个例子中,sayHello方法仅仅处理GET类型的/hello请求。

sayHello方法接收一个org.springframework.ui.Model类型的参数model,SpringMVC会自动将请求参数封装进model中,我们可以简单的把model理解为一个Map。我们在方法中从model中取出参数person的值并且打印出来,接下来往model中添加一个属性msg,值为"Hello,World!",然后返回视图名称hello。

接下来我们需要在Spring MVC配置文件中配置一个视图解析器,我们看看hello-servlet.xml的内容:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 	xmlns:context="http://www.springframework.org/schema/context" 	xmlns:mvc="http://www.springframework.org/schema/mvc" 	xsi:schemaLocation=" 	http://www.springframework.org/schema/beans 	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 	http://www.springframework.org/schema/context 	http://www.springframework.org/schema/context/spring-context-3.0.xsd 	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 	<!-- 默认的注解映射的支持 --> 	<mvc:annotation-driven /> 	<!--启用自动扫描 --> 	<context:component-scan base-package="springmvc.controller" /> 	<bean>  <property name="prefix" value="/WEB-INF/jsp/" />  <property name="suffix" value=".jsp" /> 	</bean> </beans>

扩展:springmvc / springmvc框架简介 / springmvc介绍

前面没什么好说的,但是注意添加了mvc名称空间,接下来启用了spring的自动扫描,并且设置了默认的注解映射支持。这里需要重点解释的是配置文件中的那个bean。它的类型是是Spring MVC中最常用的一种视图解析器,当然还有很多其他的类型,由于这篇博客的重点在于简单的介绍Spring MVC,因此不重点介绍,后续博文会补充。prefix属性是指视图前缀,suffix是视图后缀,这里配置的是.jsp,我们在控制器的方法sayHello中返回的是hello,再结合这里的配置,对应的完整的视图是:/WEB-INF/jsp/hello.jsp。接下来我们完成这个视图,我们只是简单的取出我们放的信息msg:

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>hello.jsp</title> </head> <body> 	${msg} </body> </html>

接下来部署应用,我们访问http://localhost:8080/springmvc/hello,会显示视图的内容,并且取出了msg的内容:

springmvc Spring MVC简介

就这样一个简单的Spring MVC的Web应用就ok了。

扩展:springmvc / springmvc框架简介 / springmvc介绍

三 : Spring MVC数据绑定的扩展

Spring MVC经过三个版本,功能已经改进和完善了很多。尤其是2.5以来采用的Annotation的参数绑定,极大的方便了开发,3.0对其进行更进一步的完善。对于一些特殊的前台框架,传到后台的不是普通的request中的参数,而是request流中的xml格式,这时就不能采用SpringMVC自带的参数绑定方法。这时候考虑是否能扩展一下。

SpringMVC默认使用的是AnnotationMethodHandlerAdapter.java,可以修改这个类来实现扩展。关键位置在如下方法中:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

ServletHandlerMethodResolver methodResolver= getMethodResolver(handler);

Method handlerMethod = methodResolver.resolveHandlerMethod(request);

ServletHandlerMethodInvoker methodInvoker=new ServletHandlerMethodInvoker(methodResolver);

ServletWebRequest webRequest = new ServletWebRequest(request, response);

ExtendedModelMap implicitModel = new BindingAwareModelMap();

Object result=methodInvoker.invokeHandlerMethod(handlerMethod,handler,webRequest, implicitModel);

ModelAndView mav=methodInvoker.getModelAndView(handlerMethod,handler.getClass(),result, implicitModel, webRequest); methodInvoker.updateModelAttributes(handler,(mav!=null?mav.getModel():null),implicitModel,webRequest);

return mav;

}

ServletHandlerMethodInvoker.java是内部类,继承自HandlerMethodInvoker.java,invokeHandlerMethod方法需要扩展,继续跟踪这个方法,发现是HandlerMethodInvoker.java这个类的方法,这个方法中的关键方法是resolveHandlerArguments(),关键部分如下

if (RequestParam.class.isInstance(paramAnn)) {

RequestParam requestParam = (RequestParam) paramAnn;

paramName = requestParam.value();

required = requestParam.required();

defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());

annotationsFound++;

}

else if (RequestHeader.class.isInstance(paramAnn)) {

RequestHeader requestHeader = (RequestHeader) paramAnn;

headerName = requestHeader.value();

required = requestHeader.required();

defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());

annotationsFound++;

}

到此扩展的话需要添加自己的类型,如RequestParamExt,添加在后面,模仿如下:

else if (RequestParamExt.class.isInstance(paramAnn)) {

RequestParamExtrequestParam = (RequestParamExt) paramAnn;

paramName = requestParam.value();

defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());

miType = requestParam.type();

annotationsFound++;

}

else if (paramName != null) {

args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);

}

这个方法上面添加扩展逻辑:

if(!RequestParamExt.TYPE_NONE.equals(miType)){

if(null == platformRequest){

HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

platformRequest = new PlatformRequest((HttpServletRequest)request, "utf-8");

platformRequest.receiveData();

}

if(RequestParamExt.TYPE_PLATFORMREQUEST.equals(miType)){

args[i] = platformRequest;

}

else if(RequestParamExt.TYPE_STR.equals(miType)){

args[i] = resolveRequestStrParamExt(platformRequest, methodParam);

}else{

args[i] = resolveRequestParamExt(miType,platformRequest,paramName, defaultValue, methodParam, webRequest, handler);

}

}

两个resolveRequest*Ext方法如下:

protected Object resolveRequestStrParamExt(PlatformRequest platformRequest, MethodParameter methodParam){

VariableList inVl = platformRequest.getVariableList();

String paraName = methodParam.getParameterName();

return inVl.getValueAsObject(paraName);

}

protected Object resolveRequestParamExt(String miType,PlatformRequest platformRequest, String paramName,

String defaultValue,MethodParameter methodParam,NativeWebRequest webRequest, Object handler)throws Exception{

if(StringUtils.isBlank(paramName)){

paramName = defaultValue;

}

Class<?> paramType = methodParam.getParameterType();

DatasetList inDl = platformRequest.getDatasetList();

VariableList inVl = platformRequest.getVariableList();

if(RequestParamExt.TYPE_DS.equals(miType)){//绑定的关键过程

Dataset ds = inDl.getDataset(paramName);

Object vo = paramType.newInstance();

MiPDataBinder dataBinder = new MiPDataBinder(vo, false);

dataBinder.bind(inVl);

return dataBinder.getTarget();

}

}

同时还需要一个annotation的定义:示例如下:

package com.company.springext.web.bind.annotation;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

@Documented

扩展:spring mvc 数据绑定 / springmvc4 数据绑定 / springmvc的数据绑定

public @interface RequestParamExt {

public static final String TYPE_NONE = "none";

public static final String TYPE_DS = "ds";

public static final String TYPE_VL = "vl";

public static final String TYPE_STR = "string";

String type() default TYPE_NONE;

String value() default "";

String defaultValue() default "ds";

}

最后是修改Spring配置:

<bean class="com.company.springext.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterExt">

</bean>

到此就实现了自定义格式的数据绑定。

对于特定格式的输出,如果需要自定义的话,同样需要修改AnnotationMethodHandlerAdapterExt.java这个类,关键位置在getModelAndView()方法。在如下位置:

} else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {

handleResponseBody(returnValue, webRequest);

return null;

}

添加自己的扩展方法:

else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBodyExt.class) != null) {

ResponseBodyExt bodyMi = AnnotationUtils.findAnnotation(handlerMethod, ResponseBodyExt.class);

handleResponseBodyExt(returnValue, webRequest, bodyMi);

return null;

}

定义handleResponseBodyExt方法:

private void handleResponseBodyExt(Object returnValue, ServletWebRequest webRequest, ResponseBodyMI bodyMi) throws Exception {

HttpServletResponse servletResponse = (HttpServletResponse) webRequest.getNativeResponse();

writeWithExtConverters(returnValue, servletResponse, bodyMi);

}

writeWithExtConverters()方法如下:

private void writeWithExtConverters(Object returnValue, HttpServletResponse response, ResponseBodyMI bodyMi) throws Exception {

convertToXML(...);

};

使用方式如下:

@RequestMapping(value="/getContractList")

@ResponseBodyExt(isCheck=true, resultType="sql", sqlColumns="ID,TUREID")

public Page<Contract> getContractList(@RequestParamExt(value = "ds_search", type = "ds") Contract cp) throws Exception {

Page<Contract> page = method1();

return page;

}
作者“菜园子”

扩展:spring mvc 数据绑定 / springmvc4 数据绑定 / springmvc的数据绑定

四 : spring mvc经典自学教程

spring mvc学习教程(一)-入门实例

引言

1.MVC:Model-View-Control

框架性质的C层要完成的主要工作:封装web请求为一个数据对象、调用业务逻辑层来处理数据对象、

返回处理数据结果及相应的视图给用户。[www.61k.com]

2.简要概述springmvc

Spring C 层框架的核心是 DispatcherServlet,它的作用是将请求分发给不同的后端处理器,也即 使用

了一种被称为Front Controller 的模式(后面对此模式有简要说明)。 Spring 的C 层框架使用了后端控

制器来、映射处理器和视图解析器来共同完成C 层框架的主要工作。并且spring 的C 层框架还真正地把

业务层处理的数据结果和相应的视图拼成一个对象,即我们后面会经常用到的

ModelAndView 对象。

一、入门实例

1. 搭建环境

在spring的官方API文档中,给出所有包的作用概述,现列举常用的包及相关作用: org.springframework.aop-3.0.5.RELEASE.jar:与Aop编程相关的包

org.springframework.beans-3.0.5.RELEASE.jar:提供了简捷操作bean的接口

org.springframework.context-3.0.5.RELEASE.jar:构建在beans包基础上,用来处理资源文件及国际

化。

org.springframework.core-3.0.5.RELEASE.jar:spring核心包

org.springframework.web-3.0.5.RELEASE.jar:web核心包,提供了web层接口

org.springframework.web.servlet-3.0.5.RELEASE.jar:web 层的一个具体实现包, DispatcherServlet也位于此包中。

后文全部在spring3.0 版本中进行,为了方便,建议在搭建环境中导入spring3.0 的所有jar 包(所

有jar 包位于dist 目录下)。

2.编写HelloWorld实例

步骤一、建立名为springMVC_01_helloword,并导入上面列出的jar 包。

步骤二、编写web.xml配置文件,代码如下:

1. <?xml version="1.0" encoding="UTF-8"?>

2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"

3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

6. <servlet>

7. <servlet-name>spring</servlet-name>

spring mvc spring mvc经典自学教程

8. <servlet-class>org.springframework.web.servlet.Dispatche

rServlet</servlet-class>

9. <load-on-startup>1</load-on-startup>

10. </servlet>

11. <servlet-mapping>

12. <servlet-name>spring</servlet-name>

13. <url-pattern>*.do</url-pattern>

14. </servlet-mapping>

15. </web-app>

16.

17. <!-- 所有请求都要由DispatcherServlet来处理,因此映射到"/"上面(包括静态页面),

<load-on-startup>不加经测试也未见出错,而且如果要修改spring-servlet.xml的配

置位置或名字,

18. 可以加 <init-param> <param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring-servlet.xml</param-value>

19. </init-param> 但一定要放到<load-on-startup>前面,否则xml校验出错(经

测试)。[www.61k.com)

20.

21. 简要说明:DispatcherServlet就是一个Servlet,也是对请求进行转发的核

心Servlet。在这里即所

22. 有.do 的请求将首先被DispatcherServlet处理,而DispatcherServlet它要作的工作

就是对请求进行分

23. 发(也即是说把请求转发给具体的Controller)。可以简单地认为,它就是一个总控处理

器,但事实上

24. 它除了具备总控处理理器对请求进行分发的能力外,还与spring的IOC 容器完全集成在

一起,从而可以

25. 更好地使用spring的其它功能。在这里还需留意

<servlet-name>spring</servlet-name>,下面

26. 步骤三会用到。

27. -->

复制代码

步骤三、建立spring-servlet.xml文件,它的命名规则:servlet-name-servlet.xml。它的主要代码如下:

spring mvc spring mvc经典自学教程

1. <?xml version="1.0" encoding="UTF-8"?>

2.

3. <beans xmlns="http://www.springframework.org/schema/beans"

4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

5. xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:context="http://www.springframework.org/schema/context"

6. xmlns:util="http://www.springframework.org/schema/util"

7. xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

8. http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

9. http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

10. http://www.springframework.org/schema/util

http://www.springframework.org/schema/util/spring-util-3.0.xsd">

11.

12. <bean id="simpleUrlHandlerMapping"

13. class="org.springframework.web.servlet.handler.SimpleUrl

61阅读提醒您本文地址:

HandlerMapping">

14. <property name="mappings">

15. <props>

16. <prop

key="/hello.do">helloControl</prop><!-- 说明:hello.do的请求将给名为helloControl的bean进行处理。[www.61k.com) -->

17. </props>

18. </property>

19. </bean>

20. <bean id="helloControl" class="controller.HelloWord"></bean>

21. </beans>

22.

复制代码

spring mvc spring mvc经典自学教程

步骤四、完成HelloWord.java的编写,代码如下:

1. package controller;

2.

3. import javax.servlet.http.HttpServletRequest;

4. import javax.servlet.http.HttpServletResponse;

5.

6. import org.springframework.web.servlet.ModelAndView;

7. import org.springframework.web.servlet.mvc.Controller;

8.

9. public class HelloWord implements Controller {

10. public ModelAndView handleRequest(HttpServletRequest request,

HttpServletResponse response)

11. throws Exception {

12. ModelAndView mav = new ModelAndView("hello.jsp");

13. mav.addObject("message", "Hello World!");

14. return mav;

15. }

16. }

17. /*

18. * 说明:ModelAndView对象是包含视图和业务数据的混合对象,即是说通过此对象,我们

可以知道所

19. 返回的相应页面(比如这里返回hello.jsp页面),也可以在相应的页面中获取此对象所

包含的业务数据

20. (比如这里message-hello worrld)。(www.61k.com)*/

21.

复制代码

步骤五、在当前项目web根目录下编写hello.jsp,主要代码如下:

1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

2. <%

3. String path = request.getContextPath();

4. String basePath =

request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

spring mvc spring mvc经典自学教程

5. %>

6.

7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

8. <html>

9. <head>

10. <base href="<%=basePath%>">

11.

12. <title>My JSP 'hello.jsp' starting page</title>

13.

14. <meta http-equiv="pragma" content="no-cache">

15. <meta http-equiv="cache-control" content="no-cache">

16. <meta http-equiv="expires" content="0">

17. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

18. <meta http-equiv="description" content="This is my page">

19. <!--

20. <link rel="stylesheet" type="text/css" href="styles.css">

21. -->

22.

23. </head>

24.

25. <body>

26. 获取值:${message}

27. </body>

28. </html>

29.

复制代码

步骤六:输入.../hello.do 进行测试。[www.61k.com]

如http://localhost/springmvc/hello.do

运行的结果是:获取值:Hello World!

4.简析spring mvc工作原理

(1)启动服务器,根据web.xml的配置加载前端控制器(也称总控制器)DispatcherServlet。在加载

时、会完成一系列的初始化动作。

(2)根据servlet的映射请求(上面的helloWorld实例中针对.do 请求),并参照“控制器

spring mvc spring mvc经典自学教程

配置文

件”(即spring-servlet.xml这样的配置)文件,把具体的请求分发给特定的后端控制器进行处理(比

如上例会分发给HelloWorld控制器进行处理)

(3)后端控制器调用相应的逻辑层代码,完成处理并返回视图对象(ModelAndView)给前端处理器。(www.61k.com]

(4)前端控制器根据后端控制器返回的ModelAndView对象,并结合一些配置(后面有说明),返回一

个相应的页面给客户端。

小结:这种Front Controller模式常应用在主流的web框架中,比如典型的struts1.x框架.Front

Controller模式:所有请求先交给一个前端处理器(总控处理器)处理,然后前端处理器会参照一些配

置文件再把具体的请求交给相应的后端处理器。后端处理器调用逻辑层代码,并根据逻辑返回相应的视

图对象给前端控制器。然后前端控制器再根据视图对象返回具体的页面给客户端(提示:和spring mvc

一样,在struts1.x中前端控制器是Servlet,而在struts2中前端控制器是Filter)。概述Front Controller模式:前端控制器预处理并分发请求给后端控制器,后端控制器进行真正的逻辑处理并返回

视图对象,前端控器器根据视图对象返回具体页面给客户端。

5.初识spring mvc的视图

在前面的HelloWorld实例中,在HelloWorld.java中返回ModelAndView mav

=newModelAndView(

"hello.jsp") 参数为hello.jsp,它会对应于当前项目根目录下的hello.jsp页面。但spring mvc为我们提供了

一个特别的视图定位方式,下面改进前面的HelloWord实例:

改进一:在spring-servlet.xml中增加如下代码:

1. <bean id="viewResolver"

61阅读提醒您本文地址:

class="org.springframework.web.servlet.view.InternalResourceViewResolve

r">

2. <property name="prefix" value="/WEB-INF/page/" />

3. <property name="suffix" value=".jsp" />

4. </bean>

复制代码

改进二:在HelloWorld.java重新定义返回的ModelAndView对象,即把ModelAndView mav =new

ModelAndView("hello.jsp") 改为ModelAndView mav =newModelAndView("hello") 改进三:在/WEB-INF/page目录下建立hello.jsp页面

进行上面三个改进操作后,重新访问hello.do会访问到WEB-INF/page/hello.jsp页面。 简析视图定位:当返回ModelAndView对象名称为hello时,会给hello加上前后缀变成 /WEB-INF/page/hello.jsp。因此在给前后缀赋值时,应特别注意它和返回的ModelAndView

spring mvc spring mvc经典自学教程

对象能否

组成一个正确的文件全路径。[www.61k.com)在前面的“简析spring mvc工作原理(4)”点中提到在根

据ModelAndView对象返回页面时,会结合一些配置。这里就是结合了视图定位方式,给viewName

加上前后缀进行定位

spring mvc学习教程(二)-后端控制器(上)

1.概述SpringMVC后端控制器

为了方便开发人员快捷地建立适合特定应用的后端控制器,springMVC实现Controller接口,自定义了许多特定控制器。这些控制器的层次关系如下:

-AbstractController

-AbstractUrlViewController

-UrlFilenameViewController

-BaseCommandController

-AbstractCommandController

-AbstractFormController

-AbstractWizardFormController

-SimpleFormController

-CancellableFormController

-MultiActionController

-ParameterizableViewController

-ServletForwardingController

-ServletWrappingController

下面重点分析两个特色控制器:

2.SimpleFormController控制器

在正式开发前,请先熟悉上前面的HelloWord实例。在保证熟悉前一个实例后,我们建立名为springMVC_02_controllerweb项目,并导入相关的jar包。

步骤一:建立后端控制器RegControl.java代码如下:

1. package controller;

2.

3. import javax.servlet.http.HttpServletRequest;

4. import javax.servlet.http.HttpServletResponse;

5.

6. import org.springframework.validation.BindException;

7. import org.springframework.web.servlet.ModelAndView;

8. import org.springframework.web.servlet.mvc.SimpleFormController;

9.

10. public class RegControl extends SimpleFormController{

spring mvc spring mvc经典自学教程

11. @SuppressWarnings("deprecation")

12. public RegControl() {

13. setCommandClass(User.class);

14. }

15.

16. protected ModelAndView processFormSubmission(HttpServletRequest arg0,

HttpServletResponse arg1,

17. Object formbean, BindException arg3) throws Exception {

18. User user = (User) formbean;

19. ModelAndView mav = new ModelAndView("hello");

20. mav.addObject("message", "Hello World!");

21. mav.addObject("user", user);

22. return mav;

23. }

24.

25. protected ModelAndView showForm(HttpServletRequest arg0,

HttpServletResponse arg1, BindException arg2)

26. throws Exception {

27. return null;

28. }

29. }

复制代码

User.java,代码如下:

1. package controller;

2.

3. public class User {

4. private String username;

5. private int age;

6. public String getUsername() {

7. return username;

8. }

9. public void setUsername(String username) {

spring mvc spring mvc经典自学教程

10. this.username = username;

11. }

12. public int getAge() {

13. return age;

14. }

15. public void setAge(int age) {

16. this.age = age;

17. }

18.

19. }

复制代码

简要说明:如果熟悉struts1.x相信很容易理解Object formbean参数,其实它就是和表单属性打交道的一个对象,也即是说表单参数会依据一定的规则填充给formbean对象。(www.61k.com)在struts1.x中,如果像把这种与formbean转换成User对象,必须要求User继承自ActionForm类,这样才能把一个表单参数转换成一个具体的formbean对象(所谓具体实质是指参数formbean对象已经能成功地赋值给User对象)并与相应的Action绑定。但springmvc并不要求这种User一定要继承某个类,既然springmvc对这种User没有要求,那表单参数是怎样与User进行完美匹配的,注意在RegControl构造方法中有如下一句代码:

setCommandClass(User.class); 这句代码就指明了此控制器绑定User类来和表单进行匹配。如果想验证此句代码的作用,可以注释掉这句代码并查看异常。后面将会分析这种控制器的一个执行过程(包括表单填充及验证过程)

概述此步要点:(1)继承SimpleFormController类(2)构造器中调用setCommandClass方法绑定定命令对象(这里为User类)(3)转换formbean为User类进行业务逻辑操作 步骤二:配置web.xml(和前面HelloWorld实例一样,在此省略)

步骤三:配置spring-servlet.xml文件,代码如下:

1. <?xml version="1.0" encoding="UTF-8"?>

61阅读提醒您本文地址:

2.

3. <beans xmlns="http://www.springframework.org/schema/beans"

4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

5. xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:context="http://www.springframework.org/schema/context"

6. xmlns:util="http://www.springframework.org/schema/util"

7. xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

spring mvc spring mvc经典自学教程

8. http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd

9. http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

10. http://www.springframework.org/schema/util

http://www.springframework.org/schema/util/spring-util-3.0.xsd"> 11.

12.

13.

14. <bean

id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

15. <property name="prefix" value="/WEB-INF/page/" />

16. <property name="suffix" value=".jsp" />

17. </bean>

18.

19. <bean

id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

20. <property name="mappings">

21. <props>

22. <prop key="/reg.do">regControl</prop>

23. </props>

24. </property>

25. </bean>

26. <bean id="regControl" class="controller.RegControl"></bean> 27.

28. </beans>

29.

复制代码

步骤四:根据配置文件完善相应页面

在index.jsp设定表单填写页面,主要代码如下:

1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

spring mvc spring mvc经典自学教程

2. <%

3. String path = request.getContextPath();

4. String basePath =

request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

5. %>

6.

7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

8. <html>

9. <head>

10. <base href="<%=basePath%>">

11.

12. <title>My JSP 'index.jsp' starting page</title>

13. <meta http-equiv="pragma" content="no-cache">

14. <meta http-equiv="cache-control" content="no-cache">

15. <meta http-equiv="expires" content="0">

16. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

17. <meta http-equiv="description" content="This is my page">

18. <!--

19. <link rel="stylesheet" type="text/css" href="styles.css">

20. -->

21. </head>

22.

23. <body>

24. <form action="<%=request.getContextPath()%>/reg.do" method="post">

25. 用户名:<input type="text" name="username"><br/>

26. 年龄:<input type="text" name="age"><br/>

27. <input type="submit">

28. </form>

29. </body>

30. </html>

31.

spring mvc spring mvc经典自学教程

复制代码

/page/hello.jsp,主要代码如下:

1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

2. <%

3. String path = request.getContextPath();

4. String basePath =

request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

5. %>

6.

7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

8. <html>

9. <head>

10. <base href="<%=basePath%>">

11.

12. <title>My JSP 'hello.jsp' starting page</title>

13.

14. <meta http-equiv="pragma" content="no-cache">

15. <meta http-equiv="cache-control" content="no-cache">

16. <meta http-equiv="expires" content="0">

17. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

18. <meta http-equiv="description" content="This is my page">

19. <!--

20. <link rel="stylesheet" type="text/css" href="styles.css">

21. -->

22.

23. </head>

24.

25. <body>

26. 世界,你好!(WEB-INF/page)

27. 用户名:${user.username }

61阅读提醒您本文地址:

28. 年龄:${user.age }

spring mvc spring mvc经典自学教程

29. </body>

30. </html>

31.

复制代码

步骤五:启动服务器,访问到首页,填写表单完成测试。(www.61k.com)

spring mvc学习教程(三)-后端控制器(下)

3.细研SimpleController控制器

在RegControl.java中增加如下代码:

1. protected Object formBackingObject(HttpServletRequest request) throws

Exception {

2. System.out.println("formBackingObject方法执行-->01");

3. setCommandClass(User.class); //也可在此处调用

setCommandClass方法

4. return super.formBackingObject(request);

5. }

6.

7. protected void initBinder(HttpServletRequest request,

ServletRequestDataBinder binder) throws Exception {

8. System.out.println("initBinder方法执行-->02");

9. super.initBinder(request, binder);

10. }

11.

12. protected void onBind(HttpServletRequest request, Object command)

throws Exception {

13. System.out.println("onBind方法执行-->03");

14. super.onBind(request, command);

15. }

16.

17. protected void onBindAndValidate(HttpServletRequest request,

Object command, BindException errors)

spring mvc spring mvc经典自学教程

18. throws Exception {

19. System.out.println("onBindAndValidate方法执行-->04");

20. super.onBindAndValidate(request, command, errors);

21. }

22.

复制代码

下面简要分析执行过程:

(1).当前端控制器把请求转交给此此控制器后,会首先调用formBackingObject方法,此方法的作用就是根据绑定的Command Class来创建一个Command对象,因此除了可以在构造方法中调用setCommandClass方法,也可以在此处调用setCommandClass方法。[www.61k.com]其实创建这个Command对象很简单,spring通过如下代码完成:

BeanUtils.instantiateClass(this.commandClass);

由于在此处必须根据commandClass来完成Command对象的创建,因此在此方法调用前应保证commandClass设置完成,所以我们可以在formBackingObject方法和构造方法中完成commandClass的设置。

(2).调用initBinder方法,初始化Command对象,即把表单参数与Command字段按名称进行匹配赋值。

(3).调用onBind方法,把Command对象和后端控制器绑定。

(4).调用onBindAndValidate方法,验证用户输入的数据是否合法。如果验证失败,我们可以通过修改errors参数,即新的errors对象将会绑定到ModelAndView上并重新回到表单填写页面。

(5).执行processFormSubmission方法,主要操作就是把绑定的Command对象转换成一个User这样的表单对象,并调用业务逻辑方法操作User对象,根据不同的逻辑返回不同的ModelAndView对象。

4.MultiActionController控制器

此控制器来将多个请求处理方法合并在一个控制器里,这样可以把相关功能组合在一起(它和struts1.x中的DispatchAction极为相似)。下面通过实例演示此控制器的使用。 步骤一:在springMVC_02_controllerweb项目下,建立后端控制器

UserManagerController.java,代码如下:

1. package com.asm;

2. //...省略导入的相关类

3. public class UserManagerController extends MultiActionController {

4. public ModelAndView list(HttpServletRequest request,

HttpServletResponse response) {

5. ModelAndView mav = new ModelAndView("list");

6. return mav;

7. }

8.

spring mvc spring mvc经典自学教程

9. public ModelAndView add(HttpServletRequest request,

HttpServletResponse response) {

10. ModelAndView mav = new ModelAndView("add");

11. return mav;

12. }

13.

14. public ModelAndView edit(HttpServletRequest request,

HttpServletResponse response) {

15. ModelAndView mav = new

ModelAndView("edit");

16. return mav;

17. }

18.

19. }

20.

复制代码

步骤二:配置web.xml(参前面实例),并在spring-servlet.xml中增加如下配置:

1. <bean

id="springMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">

2. <property name="mappings">

3. <props>

4. <prop key="/list.do">list</prop>

5. <prop key="/add.do">add</prop>

6. <prop key="/edit.do">edit</prop>

7. </props>

8. </property>

9. </bean>

10.

11. <bean

id="userManagerController" class="com.asm.UserManagerController">

12. <property name="methodNameResolver"

61阅读提醒您本文地址:

spring mvc spring mvc经典自学教程

13. ref="springMethodNameResolver">

14. </property>

15. </bean>

16.

复制代码

说明:methodNameResolver负责从请求中解析出需要调用的方法名称。(www.61k.com)Spring本身已经提供了一系列 MethodNameResolver的实现,当然也可以编写自己的实现。在这里我们使用了Pro方式来解析,具体表现如下:

<prop key="/list.do">list</prop> 请求list.do时调用list方法

<prop key="/add.do">add</prop> 请求为add.do时调用add方法

<prop key="/edit.do">edit</prop> 请求为edit.do时调用edit方法

然后通过把springMethodNameResolver解析器注入给UserManagerController的methodNameResolver,这样配置后才完成了一个真正的具有请求转发能力的

MultiActionController控制器对象——UserManagerController 强调:此步骤实质完成了一个工作:就是为UserManagerController控制器配置一个方法解析器。

步骤三:配置请求转发的访问路径,在spring-servlet.xml中添加如下代码

1. <bean

id="simpleUrlHandlerMapping" class="org.springframework.w

eb.servlet.handler.SimpleUrlHandlerMapping">

2. <property name="mappings">

3. <props>

4. <prop

key="/list.do">userManagerController</prop>

5. <prop

key="/add.do">userManagerController</prop>

6. <prop

key="/edit.do">userManagerController</prop>

7. </props>

8. </property>

9. </bean>

10.

复制代码

步骤四:根据配置文件,完善jsp页面编写。

page/list.jsp,代码如下:

<body>

用户列表页面

</body>

spring mvc spring mvc经典自学教程

page/add.jsp,代码如下:

<body>

用户添加页面

</body>

page/edi.jsp,代码如下:

<body>

用户修改页面

</body>

步骤五:启动服务器,访问…/list.do将调用到list方法并转向到list.jsp页面。(www.61k.com)

补充:细说MethodNameResolver解析器

InternalPathMethodNameResolver:默认MethodNameResolver解析器,从请求路径中获取文件名作为方法名。比如,…/list.do的请求会调用

list(HttpServletRequest,HttpServletResponse)方法。

ParameterMethodNameResolver:解析请求参数,并将它作为方法名。比如,对应…/userManager.do?method=add的请求,会调用 add(HttpServletRequest,

HttpServletResponse)方法。使用paramName属性定义要使用的请求参数名称。

PropertiesMethodNameResolver :使用用户自定义的属性(Properties)对象,将请求的URL映射到方法名,具体可以参见实例。

使用ParameterMethodNameResolver作为MethodNameResolver的解析器时,主要配置代码如下:

1. <bean

id="simpleUrlHandlerMapping" class="org.springframework.w

eb.servlet.handler.SimpleUrlHandlerMapping">

2. <property name="mappings">

3. <props>

4. <prop

key="/user.do">userManagerController</prop>

5. </props>

6. </property>

7. </bean>

8.

9. <bean

id="ParameterMethodNameResolver" class="org.springframewo

rk.web.servlet.mvc.multiaction.ParameterMethodNameResolver">

10. <property name="paramName" value="crud"></property>

11. </bean>

12.

spring mvc spring mvc经典自学教程

13. <bean id="userManagerController"

14. class="com.asm.UserManagerController">

15. <property name="methodNameResolver"

16. ref="ParameterMethodNameResolver">

17. </property>

18. </bean>

19.

复制代码

访问路径为…/user.do?crud=list(add|edit)

spring mvc学习教程(四)-映射处理器(上)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

Message:${message}

</body>

步骤五:启动服务器,输入…/message.do访问测试。(www.61k.com]

61阅读提醒您本文地址:

简析执行过程

(1)启动服务器后,当我们向服务器发送message.do请求时,首先被在web.xml中配置的前端控制器DispatcherServlet拦截到。

(2)前端控制器把此请求转交给后端控制器,下面分析转交过程:当在

spmvc-servlet.xml中查找能执行message.do请求的映射处理器时,发现没有能处理此请求的映射处理器,这时便使用默认的映射处理器

BeanNameUrlHandlerMapping:This is the default implementation used by theDispatcherServlet, along

with DefaultAnnotationHandlerMapping (on Java 5 and higher). 我们还需注意:这种后端控制器的bean Name必须以“/”开头,并且要结合

DispatcherServlet的映射配置。同时beanName支持通配符配置。比如如果配置:<bean name="/m*.do" class="com.asm.MessageController" /> 时,当访问

messasge.do时也可以成功访问到MessageController类。

(3)BeanNameUrlHandlerMapping处理器,会查找在spring容器中是否在名为“message.do”的bean实例。当查找到此实例后,则把此bean作为处理此请求的后端控制器。同时把自身加到映射处理器链上,并向处理器链传递此请求。

spring mvc spring mvc经典自学教程

4)后端控制器进行处理,并返回视图

spring mvc spring mvc经典自学教程

spring mvc学习教程(五)-映射处理器(下)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc学习教程(六)- 视图与视图解析器(上)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

步骤五:启动服务器,输入…/getExcel.do,将访问到excel文件。(www.61k.com]

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

简析执行过程:当后端控制器接受到前端控制派发的请求时,后端控制器会首先准备Model,这里即Map对象,然后返回exl视图。[www.61k.com]在返回视图前,会查找spmvc-servlet.xml配置文件,当查找名为exl的视图是由

ResourceBundleViewResolver视图解析器进行解析时,这时根据此视图解析的解析规则,会对每个待解析的视图,ResourceBundle里(这时即view.properties文件)的[视图名].class所对应的值就是实现该视图的类。 同样,[视图名].url所对应的值是该视图所对应的URL。当视图类成功完成视图的预处理工作后,会把此视图返回给客户端。

spring mvc学习教程(七)- 视图与视图解析器(下)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

61阅读提醒您本文地址:

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc学习教程(八)- 使用注解(上)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

SimpleAnnotationControl类纳入spring容器管理。[www.61k.com]关于spring自动扫描管理bean可以参它的相关文档。

步骤四:在WEB-INF/page目录下编写anno.jsp页面,主要代码如下:

<body>

欢迎来到注解页面<br/>

${message}

</body>

步骤五:启动服务器,访问…/anno.do完成测试。

简析注解:在本实例中,我们使用了两个注解,一是Controller注解,此注解的作用是把控制器SimpleAnnotationControl纳入spring容器管理;二是@RequestMapping注解。下面我们重点分析此注解:在本例中,我们使用 @RequestMapping("/anno.do")这种简写形式,实际它的完整形式应为:@RequestMapping(value = "/anno.do")。value属性指明了它的映射路径,比如这里的映射路径为anno.do。此注解除了value属性外,还有如下属性:method、headers、params。

@RequestMapping(value = "/anno.do", method = RequestMethod.GET)

此配置说明只有GET请求才能访问

spring mvc学习教程(九)- 使用注解(下)

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

spring mvc spring mvc经典自学教程

</body>

步骤四、输入相关信息进行测试。(www.61k.com) reg.do,

spring mvc spring mvc经典自学教程

对应于addUI()方法的访问:我们输入..../reg.do,可以看到页面显示如下内容:

“在此处填写用户名”,这几个字是由于我们在reg.jsp中使用了${user.usernam},并且在initUser方法中我们通过ModelAttribute注解初始化了一个模型数据,这样我们便可以在此类对应的任何方法映射的视图中访问到此模型数据,这也即是前面提到这种模型数据在类中全局有效。然后填写相关数据,提交表单给sava.do,即是提交给给save方法,在save方法中我们同样使用了ModelAttribute注解,此注解在save方法中实现了web请求参数和方法参数的绑定的功能,也即是说把web中username、password和ModelAttribute指示的user中的username、password进行绑定,这种绑定和struts2中的模型驱动ModerDriven极为相似。

步骤五、访问登录页面,在login方法中我们对登录进行了简单的校验,如果用户名是admin则允许后台进行管理操作,如果不是则提示用户没有权力进行此操作。在前面我们对save方法进行了简要分析,这里的login方法也是类似得。另在此方法中如果是admin登录我们重定向到管理页面,如果不是admin登录,我们使用forward进行转发。访问login.do的jsp页面代码如下:

<form action="<%=request.getContextPath() %>/login.do" method="post">

<input type="text" name="username">

<input type="submit" value="登入管理后台">

</form>

<!--[endif]-->

Java学习论坛 Java软件开发学习群 94897353

61阅读提醒您本文地址:

本文标题:Spring MVC-spring mvc EL ModelAndView的 Model 值 在jsp中不显示
本文地址: http://www.61k.com/1101111.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1