SpringMVC入门



目录(?)[+]

1.               Spring web mvc介绍

 

Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:

 

2.               Web mvc

1、  用户发起request请求至控制器

2、  控制器通过模型准备数据

3、  控制器将模型数据在视图中展示

4、  控制器将视图响应给用户

3.               Sping web mvc 架构

1、  用户发送请求至前端控制器DispatcherServlet

2、  DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、  处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、  DispatcherServlet调用HandlerAdapter处理器适配器

5、  HandlerAdapter经过适配(通过反射)调用具体的处理器(Controller,也叫后端控制器)。

6、  Controller执行完成返回ModelAndView

7、  HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

8、  DispatcherServlet将ModelAndView传给ViewReslover视图解析器

9、  ViewReslover解析后返回具体View

10、             DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中,数据为map类型通用性强)。

11、             DispatcherServlet响应用户

 

重点:

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

 

4.               开发环境准备

本教程使用Eclipse+tomcat7开发

5.               第一个springmvc工程

 

第一步:建立一个Web项目

在eclipse下创建动态web工程springmvc_01。

 

第二步:导入sping3.1.4的jar包

 

第三步:前端控制器配置

在WEB-INF\web.xml中配置前端控制器,

 

<servlet>

    <servlet-name>springmvc</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>classpath:springmvc-servlet.xml</param-value>

    </init-param>

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

  </servlet>

  <servlet-mapping>

    <servlet-name>springmvc</servlet-name>

    <url-pattern>*.action</url-pattern>

  </servlet-mapping>

 

 

load-on-startup:表示servlet随服务启动;

url-pattern:*.action的请交给DispatcherServlet处理。

contextConfigLocation:指定springmvc配置的加载位置,如果不指定则默认加

载WEB-INF/[DispatcherServlet的Servlet 名字]-servlet.xml。

 

第四步:配置处理器映射器

 

在springmvc-servlet.xml文件配置如下:

<?xmlversion="1.0"encoding="UTF-8"?>

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

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"

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

   xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"

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

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

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

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

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

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

       http://www.springframework.org/schema/aop

       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

       http://www.springframework.org/schema/tx

       http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

<!-- HandlerMapping -->

<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

BeanNameUrlHandlerMapping:表示将定义的Bean名字作为请求的url,需要将编写的controller在spring容器中进行配置,且指定bean的name为请求的url,且必须以.action结尾。

 

第五步:配置处理器适配器

 

在springmvc-servlet.xml文件配置如下:

 

<!-- HandlerAdapter -->

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

 

SimpleControllerHandlerAdapter:即简单控制器处理适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean作为

Springmvc的后端控制器。

第六步:配置视图解析器

在springmvc-servlet.xml文件配置如下:

 

<!-- ViewResolver -->

<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

 

InternalResourceViewResolver:支持JSP视图解析

viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar 包;

prefix 和suffix:查找视图页面的前缀和后缀,最终视图的址为:

前缀+逻辑视图名+后缀,逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,则最终返回的jsp视图地址 “WEB-INF/jsp/hello.jsp”

 

第七步:后端控制器开发

后端控制器即controller,也有称为action。

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

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

public class HelloWorldControllerimplements Controller {

@Override

public ModelAndView handleRequest(HttpServletRequest req,HttpServletResponse resp)throws

Exception {

ModelAndView mv = new ModelAndView();

//添加模型数据

mv.addObject("message""Hello World!");

//设置逻辑视图名,最终视图地址=前缀+逻辑视图名+后缀

mv.setViewName("hello");

return mv;

}

}

 

org.springframework.web.servlet.mvc.Controller:处理器必须实现Controller 接口。

ModelAndView:包含了模型数据及逻辑视图名

第八步:后端控制器配置

在springmvc-servlet.xml文件配置如下:

 

<!-- 处理器-->

 <beanname="/hello.action"

class="springmvc.action.HelloWorldController"/>

 

name="/hello.action"前边配置的BeanNameUrlHandlerMapping,表示如过请求的URL 为“上下文/hello.action”,则将会

交给该Bean进行处理。

 

第九步:视图开发

创建 /WEB-INF/jsp/hello.jsp视图页面:

 

<%@ pagelanguage="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>

<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">

<title>Hello World</title>

</head>

<body>

${message}

</body>

</html>

 

${message}表示显示由HelloWorldController处理器传过来的模型数据。

第十步:部署在tomcat测试

通过请求:http://localhost:8080/springmvc_01/hello.action,如果页面输出“Hello World! ”就表明我们成功了!

 

总结:

主要进行如下操作:

1、前端控制器DispatcherServlet配置

2、HandlerMapping配置

3、HandlerAdapter配置

4、ViewResolver配置

5、后端控制器编写

6、后端控制器配置

7、视图编写

 

从上边的步骤可以看出,通常情况下我们只需要编写后端控制器和视图。

 

 

 

6.   HandlerMapping处理器映射器

HandlerMapping 给前端控制器返回一个HandlerExecutionChain对象(包含一个Handler (后端控制器)对象、多个HandlerInterceptor 拦截器)对象。

 

BeanNameUrlHandlerMapping

beanName Url映射器

 

<!—beanName Url映射器 -->

<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

将后端控制器的bean name作为请求的url。

SimpleUrlHandlerMapping

 

<!—简单url映射 -->

    <beanclass="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

       <propertyname="mappings">

           <props>

              <propkey="/hello1.action">hello_controller</prop>

              <propkey="/hello2.action">hello_controller</prop>

           </props>

       </property>

    </bean>

 

可定义多个url映射至一个后端控制器。

 

7.   HandlerAdapter处理器适配器

HandlerAdapter会把后端控制器包装为一个适配器,支持多种类型的控制器开发,这里使用了适配器设计模式。

SimpleControllerHandlerAdapter

简单控制器处理器适配器

所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean作为

Springmvc的后端控制器。

适配器配置如下:

<beanclass="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

 

HttpRequestHandlerAdapter

HTTP请求处理器适配器

HTTP请求处理器适配器将http请求封装成HttpServletResquest 和HttpServletResponse对象,和servlet接口类似。

适配器配置如下:

<beanclass="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

 

Controller实现如下:

public class HelloWorldController2 implements HttpRequestHandler {

 

    @Override

    public void handleRequest(HttpServletRequest request,

           HttpServletResponse response) throws ServletException,IOException {

       request.setAttribute("message","HelloWorld!");

       request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request, response);

    }

 

 

}

 

从上边可以看出此适配器器的controller方法没有返回ModelAndView,可通过response修改定义响应内容。

 

8.   Controller控制器

ParameterizableViewController(参数控制器)

 

参数化视图控制器,不进行功能处理(即静态视图),根据参数的逻辑视图名直接选择需要展示的视图。

 

<beanname="/success.action"

class="org.springframework.web.servlet.mvc.ParameterizableViewController">

<propertyname="viewName"value="success"/>

</bean>

 

AbstractCommandController(命令控制器)

 

该控制器能把请求参数封装到一个命令对象(模型对象)中。

 

public class MyCommandController extendsAbstractCommandController{

 

    /**

     * 通过构造函数设置命令对象

     */

    public MyCommandController(){

       this.setCommandClass(Student.class);

       this.setCommandName("student");//不是必须设置

    }

   

    @Override

    protected ModelAndView handle(HttpServletRequest request,

           HttpServletResponse response, Object command,BindException errors)

           throws Exception {

 

       Student student = (Student)command;

       System.out.println(student);

       return null;

    }

 

    /**

     * 字符串转换为日期属性编辑器

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinderbinder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

}

 

 

public class Student {

   

    public Student() {

    }

    public Student(String name) {

       this.name = name;

    }

    private Stringname;//姓名

    private Integerage;//年龄

    private Datebirthday;//生日

    private Stringaddress;//地址

 

….get/set方法省略

 

Controller配置;

 

<beanid="command_controller" name="/command.action"

class="springmvc.action.MyCommandController"/>

 

SimpleFormController(表单控制器)

表单控制器可以实现通用的表单显示及表单提交操作。

 

public class MyFormController extendsSimpleFormController{

   

    public MyFormController(){

       this.setCommandClass(Student.class);

       this.setCommandName("student");

    }

 

   

    /**

     * 注册属性编辑器(字符串转日期)

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

 

    /**

     * 表单显示

     */

    @Override

    protected ModelAndView showForm(HttpServletRequest request,

           HttpServletResponse response, BindException errors, MapcontrolModel)

           throws Exception {

       // TODO Auto-generatedmethod stub

       return super.showForm(request, response, errors, controlModel);

    }

 

    /**

     * 表单提交

     */

    @Override

    protected void doSubmitAction(Object command) throws Exception {

       System.out.println(command);

       super.doSubmitAction(command);

    }

 

}

 

Controller配置:

 

<beanid="from_controller"name="/form.action"class="springmvc.action.MyFormController">

        <!-- 表单视图 -->

       <propertyname="formView"value="student"/><!--逻辑视图名 -->

       <!-- 成功视图 -->

       <propertyname="successView"value="success"/><!--逻辑视图名 -->

    </bean>

 

 

 

问题解决

日期格式化

在controller注册属性编辑器:

/**

     * 注册属性编辑器(字符串转换为日期)

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

Post时中文乱码

在web.xml中加入:

<filter>

    <filter-name>CharacterEncodingFilter</filter-name>

    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <init-param>

      <param-name>encoding</param-name>

      <param-value>utf-8</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>CharacterEncodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

 

 

9.   注解开发

第一个例子

创建工程的步骤同第一个springmvc工程,注解开发需要修改handlermapper和handlMapperAdapter,如下:

 

在springmvc-servlet.xml中配置:

 

<!-- 注解映射器 -->   

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

 

 

注意:

Spring3.1 之前版本,开启注解式处理器为:DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。

 

Spring3.1 之后的版本,开启注解式处理器为:RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

 

 

 

HelloWorldController编写:

 

@Controller

public class HelloWorldController {

 

    @RequestMapping(value="/hello")

    public String hello(Model model)throws Exception{

       model.addAttribute("message","HelloWorld!");

       return"hello";

    }

}

 

 

注解描述:

 

@Controller用于标识是处理器类

 

@RequestMapping请求到处理器功能方法的映射规则

 

 

Controller配置

在springmvc-servlet.xml中配置定义的controller:

<!-- controller -->

<bean class="springmvc.action.HelloWorldController"/>

 

 

组件扫描

 

<context:component-scanbase-package="springmvc.action" />

 

扫描@component、@controller、@service、@repository的注解

 

注意:如果使用组件扫描则controller不需要在springmvc-servlet.xml中配置

 

@Controller

 

标识该类为控制器类,@controller、@service、@repository分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口。

 

@RequestMapping

URL路径映射

@RequestMapping(value="/user")或@RequestMapping("/user")

根路径+子路径

根路径:

@RequestMapping放在类名上边,如下:

@Controller

@RequestMapping("/user")

子路径:

@RequestMapping放在方法名上边,如下:

@RequestMapping("/useradd")

public String useradd(….

 

URI 模板模式映射

@RequestMapping(value="/useredit/{userId}"):{×××}占位符, 请求的URL可以是“/useredit/001”或“/useredit/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

 

@RequestMapping("/useredit/{userid}")

    public String useredit(@PathVariable String userid,Modelmodel)throws Exception{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

 

多个占位符:

 

@RequestMapping("/useredit/{groupid}/{userid}")

public String useredit(@PathVariable Stringgroupid,@PathVariable Stringuserid,Model model)throwsException{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("groupid",groupid);

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

正则表达式url映射

 

限制只允许输入数字:

RequestMapping(value="/useredit/{userid:\\d+}")

限制只允许输入数字、英文字符:

RequestMapping(value="/useredit/{userid:[A-Za-z0-9]+}")

 

 

请求方法限定
限定GET方法

@RequestMapping(method = RequestMethod.GET)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'POST' notsupported

 

例如:

@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)

限定POST方法

 

@RequestMapping(method = RequestMethod.POST)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'GET' notsupported

 

GET和POST都可以

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

 

 

 

请求数据绑定

默认支持的参数类型
HttpServletRequest

通过request对象获取请求信息

HttpServletResponse

通过response处理响应信息

HttpSession

通过session对象得到session中存放的对象

Model、Map、ModelMap

通过model、map及modelMap向页面传递数据,如下:

 

modelMap.put("user1"new User("张三"));

model.addAttribute("user2"new User("李四"));

map.put("user3",new User("王五"));

 

命令/表单对象

自动将请求参数绑定到功能处理方法的命令/表单对象上。

 

Java基本数据类型
布尔型:

页面如下:

 

<tr>

<td>是否好学生:</td>

<td>

<inputtype="radio"name="isgood"value="true"/>

<inputtype="radio"name="isgood"value="false"/></td>

</tr>

<tr>

日期型需要添加属性编辑器:

@InitBinder

    public void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

Pojo对象
页面上以pojo对象中属性名称命名:

将pojo对象中的属性名于传递进来的属性名对应,对应上的将值设置在pojo对象中

 

页面定义如下;

 

<inputtype="text" name="age"/>

<inputtype="text" name="birthday"/>

 

页面上以pojo对象名点 属性名命名:

需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。

包装对象定义如下:

public class UserVo {

  private Useruser;

 

public User getUser() {

    return user;

}

 

public void setUser(User user) {

    this.user = user;

}

}

 

页面定义:

 

<inputtype="text" name="user.height" />

 

字符串数组

页面传递逗号分隔的字符串,springmvc中以String[]接收。

 

List

List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。

 

List中对象:

成绩对象

public classStudentScore {

   private Stringcoursename;//课程名称

   private Floatscore;//成绩

   public String getCoursename(){

      return coursename;

   }

   public void setCoursename(Stringcoursename) {

      this.coursename = coursename;

   }

   public Float getScore() {

      return score;

   }

   public void setScore(Float score) {

      this.score = score;

   }

}

 

包装类中定义List对象,并添加get/set方法如下:

 

private List<StudentScore> scores;//成绩

 

页面:

 

<tr>

<td>兴趣课程:</td>

<td>

课程名:<inputtype="text"name="scores[0].coursename"/>成绩:<inputtype="text"name="scores[0].score"/><br/>

课程名:<inputtype="text"name="scores[1].coursename"/>成绩:<inputtype="text"name="scores[1].score"/><br/>

课程名:<inputtype="text"name="scores[2].coursename"/>成绩:<inputtype="text"name="scores[2].score"/><br/>

</td>

</tr>

 

Map

在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。

包装类中定义Map对象如下:

private Map<String, Object>userinfo = new HashMap<String, Object>();

 

 

页面定义如下:

 

<tr>

<td>学生详细信息:</td>

<td>

地址:<inputtype="text"name="userinfo['address']"/>

朋友:<inputtype="text"name="userinfo['firend']"/>

</td>

</tr>

 

 

@RequestParam绑定单个请求参数

 

value参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;

required是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;

defaultValue默认值,表示如果请求中没有同名参数时的默认值

 

 

 

@PathVariable 绑定URI 模板变量值

 

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上

 

@RequestMapping(value="/useredit/{groupid}/{userid}",method={RequestMethod.GET,RequestMethod.POST})

    public String useredit(@PathVariable String groupid,@PathVariable Stringuserid,Model model)throwsException{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("groupid", groupid);

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

如请求的 URL 为“控制器URL/useredit/1/admin.action”,则自动将URL 中模板变量{groupid}和{userid}绑定到@PathVariable注解的同名参数上,即入参后groupid=“1”、userid=“admin”

 

 

@RequestBody @ResponseBody实现json数据交互
@RequestBody

作用:

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

 

本例子应用:

@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

 

@ResponseBody

作用:

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

 

本例子应用:

@ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

 

请求json,响应json实现:
环境准备

Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包,如下:

配置:

 

在注解适配器中加入messageConverters

 

<!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

       <propertyname="messageConverters">

         <list>

            <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>

         </list>

       </property>

    </bean>

 

 

controller编写

/**

     * 请求json单个对象,返回json单个对象

     * @param user

     * @return

     * @throws Exception

     */

    @RequestMapping("/requestjson")

    //@RequestBody接收json串自动转为user对象,@ResponseBodyuser转为json数据响应给客户端

    public @ResponseBody User requestjson(@RequestBody User user)throws Exception{

       System.out.println(user);

       return user;

    }

 

 

页面js方法编写:

function request_json(){

         var user =JSON.stringify({name:"张三", age: 3});

         alert(user);

      $.ajax(

       {

           type:'post',

           url:'${pageContext.request.contextPath}/requestjson.action',

           contentType:'application/json;charset=utf-8', //请求内容为json

           data:user,

           success:function(data){

              alert(data.name);

           }

       }    

      )

  }

 

 

测试结果:

 

从上图可以看出请求的数据是json格式

 

从上图可以看出响应的数据也是json格式,json数据的内容是从User对象转换得来。

 

Form提交,响应json实现:

采用form提交是最常用的作法,通常有post和get两种方法,响应json数据是为了方便客户端处理,实现如下:

 

环境准备

同第一个例子

 

controller编写

 

/**

    * 客户端提交表单,服务端返回json

    * @param user

    * @return

    * @throws Exception

    */

   @RequestMapping("/formsubmit")

   public @ResponseBody Userformsubmit(User user)throws Exception{

      System.out.println(user);

      return user;

   }

 

页面js方法编写:

 

function formsubmit(){

        var user ="name=张三&age=3";

        alert(user);

     $.ajax(

      {

         type:'post',//这里改为get也可以正常执行

         url:'${pageContext.request.contextPath}/formsubmit.action',

//ContentType没指定将默认为:application/x-www-form-urlencoded

         data:user,

         success:function(data){

            alert(data.name);

         }

        

      }   

     )

}

 

从上边的js代码看出,已去年ContentType的定义,ContentType默认为:application/x-www-form-urlencoded格式。

 

 

测试结果:

从上图可以看出请求的数据是标准的key/value格式。

 

从上图可以看出响应的数据也是json格式,json数据的内容是从User对象转换得来。

 

 

简化配置:

注解映射器和注解适配器可以使用<mvc:annotation-driven />代替。

<mvc:annotation-driven />默认注册了注解映射器和注解适配器等bean。

 

如下:

 

以下配置可用<mvc:annotation-driven />代替:

 

 

<!-- 注解映射器 -->   

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

       <propertyname="messageConverters">

         <list>

            <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>

         </list>

       </property>

    </bean>

 

10.             拦截器

定义

Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

 

拦截器定义

实现HandlerInterceptor接口,如下:

 

public class HandlerInterceptor1 implements HandlerInterceptor{

 

    /**

     *controller执行前调用此方法

     * 返回true表示继续执行,返回false中止执行

     * 这里可以加入登录校验、权限拦截等

     */

    @Override

    public boolean preHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler) throws Exception {

       // TODO Auto-generatedmethod stub

       return false;

    }

    /**

     *controller执行后但未返回视图前调用此方法

     * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示

     */

    @Override

    public void postHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler,

           ModelAndView modelAndView) throws Exception {

       // TODO Auto-generatedmethod stub

      

    }

    /**

     * controller执行后且视图返回后调用此方法

     * 这里可得到执行controller时的异常信息

     * 这里可记录操作日志,资源清理等

     */

    @Override

    public void afterCompletion(HttpServletRequest request,

           HttpServletResponse response, Object handler, Exceptionex)

           throws Exception {

       // TODO Auto-generatedmethod stub

      

    }

 

}

 

 

拦截器配置

 

<bean

    class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

    <propertyname="interceptors">

       <list>

           <refbean="handlerInterceptor1"/>

           <refbean="handlerInterceptor2"/>

       </list>

    </property>

</bean>

    <beanid="handlerInterceptor1"class="springmvc.intercapter.HandlerInterceptor1"/>

    <beanid="handlerInterceptor2"class="springmvc.intercapter.HandlerInterceptor2"/>

 

 

 

正常流程测试

 

代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。

 

 

运行流程

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

 

HandlerInterceptor2..postHandle..

HandlerInterceptor1..postHandle..

 

HandlerInterceptor2..afterCompletion..

HandlerInterceptor1..afterCompletion..

 

 

中断流程测试

代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2。

 

 

运行流程

HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:

 

HandlerInterceptor1..preHandle..

 

从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。

 

 

HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:

 

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

HandlerInterceptor1..afterCompletion..

 

从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。

 

总结:

preHandle按拦截器定义顺序调用

postHandler按拦截器定义逆序调用

afterCompletion按拦截器定义逆序调用

 

postHandler在拦截器链内所有拦截器返成功调用

afterCompletion只有preHandle返回true才调用

 

 

拦截器应用

 

用户身份认证

 

public class LoginInterceptor implements HandlerInterceptor{

 

    @Override

    public boolean preHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler) throws Exception {

 

       //如果是登录页面则放行

       if(request.getRequestURI().indexOf("login.action")>=0){

           return true;

       }

       HttpSession session = request.getSession();

       //如果用户已登录也放行

       if(session.getAttribute("user")!=null){

           return true;

       }

       //用户没有登录挑战到登录页面

       request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

      

       return false;

    }

}

 

 

目录 (?) [+]

1.               Spring web mvc介绍

 

Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:

 

2.               Web mvc

1、  用户发起request请求至控制器

2、  控制器通过模型准备数据

3、  控制器将模型数据在视图中展示

4、  控制器将视图响应给用户

3.               Sping web mvc 架构

1、  用户发送请求至前端控制器DispatcherServlet

2、  DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、  处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、  DispatcherServlet调用HandlerAdapter处理器适配器

5、  HandlerAdapter经过适配(通过反射)调用具体的处理器(Controller,也叫后端控制器)。

6、  Controller执行完成返回ModelAndView

7、  HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

8、  DispatcherServlet将ModelAndView传给ViewReslover视图解析器

9、  ViewReslover解析后返回具体View

10、             DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中,数据为map类型通用性强)。

11、             DispatcherServlet响应用户

 

重点:

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

 

4.               开发环境准备

本教程使用Eclipse+tomcat7开发

5.               第一个springmvc工程

 

第一步:建立一个Web项目

在eclipse下创建动态web工程springmvc_01。

 

第二步:导入sping3.1.4的jar包

 

第三步:前端控制器配置

在WEB-INF\web.xml中配置前端控制器,

 

<servlet>

    <servlet-name>springmvc</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>classpath:springmvc-servlet.xml</param-value>

    </init-param>

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

  </servlet>

  <servlet-mapping>

    <servlet-name>springmvc</servlet-name>

    <url-pattern>*.action</url-pattern>

  </servlet-mapping>

 

 

load-on-startup:表示servlet随服务启动;

url-pattern:*.action的请交给DispatcherServlet处理。

contextConfigLocation:指定springmvc配置的加载位置,如果不指定则默认加

载WEB-INF/[DispatcherServlet的Servlet 名字]-servlet.xml。

 

第四步:配置处理器映射器

 

在springmvc-servlet.xml文件配置如下:

<?xmlversion="1.0"encoding="UTF-8"?>

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

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"

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

   xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"

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

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

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

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

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

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

       http://www.springframework.org/schema/aop

       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

       http://www.springframework.org/schema/tx

       http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

<!-- HandlerMapping -->

<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

BeanNameUrlHandlerMapping:表示将定义的Bean名字作为请求的url,需要将编写的controller在spring容器中进行配置,且指定bean的name为请求的url,且必须以.action结尾。

 

第五步:配置处理器适配器

 

在springmvc-servlet.xml文件配置如下:

 

<!-- HandlerAdapter -->

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

 

SimpleControllerHandlerAdapter:即简单控制器处理适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean作为

Springmvc的后端控制器。

第六步:配置视图解析器

在springmvc-servlet.xml文件配置如下:

 

<!-- ViewResolver -->

<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

 

InternalResourceViewResolver:支持JSP视图解析

viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar 包;

prefix 和suffix:查找视图页面的前缀和后缀,最终视图的址为:

前缀+逻辑视图名+后缀,逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,则最终返回的jsp视图地址 “WEB-INF/jsp/hello.jsp”

 

第七步:后端控制器开发

后端控制器即controller,也有称为action。

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

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

public class HelloWorldControllerimplements Controller {

@Override

public ModelAndView handleRequest(HttpServletRequest req,HttpServletResponse resp)throws

Exception {

ModelAndView mv = new ModelAndView();

//添加模型数据

mv.addObject("message""Hello World!");

//设置逻辑视图名,最终视图地址=前缀+逻辑视图名+后缀

mv.setViewName("hello");

return mv;

}

}

 

org.springframework.web.servlet.mvc.Controller:处理器必须实现Controller 接口。

ModelAndView:包含了模型数据及逻辑视图名

第八步:后端控制器配置

在springmvc-servlet.xml文件配置如下:

 

<!-- 处理器-->

 <beanname="/hello.action"

class="springmvc.action.HelloWorldController"/>

 

name="/hello.action"前边配置的BeanNameUrlHandlerMapping,表示如过请求的URL 为“上下文/hello.action”,则将会

交给该Bean进行处理。

 

第九步:视图开发

创建 /WEB-INF/jsp/hello.jsp视图页面:

 

<%@ pagelanguage="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>

<!DOCTYPEhtml PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">

<title>Hello World</title>

</head>

<body>

${message}

</body>

</html>

 

${message}表示显示由HelloWorldController处理器传过来的模型数据。

第十步:部署在tomcat测试

通过请求:http://localhost:8080/springmvc_01/hello.action,如果页面输出“Hello World! ”就表明我们成功了!

 

总结:

主要进行如下操作:

1、前端控制器DispatcherServlet配置

2、HandlerMapping配置

3、HandlerAdapter配置

4、ViewResolver配置

5、后端控制器编写

6、后端控制器配置

7、视图编写

 

从上边的步骤可以看出,通常情况下我们只需要编写后端控制器和视图。

 

 

 

6.   HandlerMapping处理器映射器

HandlerMapping 给前端控制器返回一个HandlerExecutionChain对象(包含一个Handler (后端控制器)对象、多个HandlerInterceptor 拦截器)对象。

 

BeanNameUrlHandlerMapping

beanName Url映射器

 

<!—beanName Url映射器 -->

<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

 

将后端控制器的bean name作为请求的url。

SimpleUrlHandlerMapping

 

<!—简单url映射 -->

    <beanclass="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

       <propertyname="mappings">

           <props>

              <propkey="/hello1.action">hello_controller</prop>

              <propkey="/hello2.action">hello_controller</prop>

           </props>

       </property>

    </bean>

 

可定义多个url映射至一个后端控制器。

 

7.   HandlerAdapter处理器适配器

HandlerAdapter会把后端控制器包装为一个适配器,支持多种类型的控制器开发,这里使用了适配器设计模式。

SimpleControllerHandlerAdapter

简单控制器处理器适配器

所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean作为

Springmvc的后端控制器。

适配器配置如下:

<beanclass="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

 

HttpRequestHandlerAdapter

HTTP请求处理器适配器

HTTP请求处理器适配器将http请求封装成HttpServletResquest 和HttpServletResponse对象,和servlet接口类似。

适配器配置如下:

<beanclass="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

 

Controller实现如下:

public class HelloWorldController2 implements HttpRequestHandler {

 

    @Override

    public void handleRequest(HttpServletRequest request,

           HttpServletResponse response) throws ServletException,IOException {

       request.setAttribute("message","HelloWorld!");

       request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request, response);

    }

 

 

}

 

从上边可以看出此适配器器的controller方法没有返回ModelAndView,可通过response修改定义响应内容。

 

8.   Controller控制器

ParameterizableViewController(参数控制器)

 

参数化视图控制器,不进行功能处理(即静态视图),根据参数的逻辑视图名直接选择需要展示的视图。

 

<beanname="/success.action"

class="org.springframework.web.servlet.mvc.ParameterizableViewController">

<propertyname="viewName"value="success"/>

</bean>

 

AbstractCommandController(命令控制器)

 

该控制器能把请求参数封装到一个命令对象(模型对象)中。

 

public class MyCommandController extendsAbstractCommandController{

 

    /**

     * 通过构造函数设置命令对象

     */

    public MyCommandController(){

       this.setCommandClass(Student.class);

       this.setCommandName("student");//不是必须设置

    }

   

    @Override

    protected ModelAndView handle(HttpServletRequest request,

           HttpServletResponse response, Object command,BindException errors)

           throws Exception {

 

       Student student = (Student)command;

       System.out.println(student);

       return null;

    }

 

    /**

     * 字符串转换为日期属性编辑器

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinderbinder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

}

 

 

public class Student {

   

    public Student() {

    }

    public Student(String name) {

       this.name = name;

    }

    private Stringname;//姓名

    private Integerage;//年龄

    private Datebirthday;//生日

    private Stringaddress;//地址

 

….get/set方法省略

 

Controller配置;

 

<beanid="command_controller" name="/command.action"

class="springmvc.action.MyCommandController"/>

 

SimpleFormController(表单控制器)

表单控制器可以实现通用的表单显示及表单提交操作。

 

public class MyFormController extendsSimpleFormController{

   

    public MyFormController(){

       this.setCommandClass(Student.class);

       this.setCommandName("student");

    }

 

   

    /**

     * 注册属性编辑器(字符串转日期)

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

 

    /**

     * 表单显示

     */

    @Override

    protected ModelAndView showForm(HttpServletRequest request,

           HttpServletResponse response, BindException errors, MapcontrolModel)

           throws Exception {

       // TODO Auto-generatedmethod stub

       return super.showForm(request, response, errors, controlModel);

    }

 

    /**

     * 表单提交

     */

    @Override

    protected void doSubmitAction(Object command) throws Exception {

       System.out.println(command);

       super.doSubmitAction(command);

    }

 

}

 

Controller配置:

 

<beanid="from_controller"name="/form.action"class="springmvc.action.MyFormController">

        <!-- 表单视图 -->

       <propertyname="formView"value="student"/><!--逻辑视图名 -->

       <!-- 成功视图 -->

       <propertyname="successView"value="success"/><!--逻辑视图名 -->

    </bean>

 

 

 

问题解决

日期格式化

在controller注册属性编辑器:

/**

     * 注册属性编辑器(字符串转换为日期)

     */

    @Override

    protected void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

Post时中文乱码

在web.xml中加入:

<filter>

    <filter-name>CharacterEncodingFilter</filter-name>

    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <init-param>

      <param-name>encoding</param-name>

      <param-value>utf-8</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>CharacterEncodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

 

 

9.   注解开发

第一个例子

创建工程的步骤同第一个springmvc工程,注解开发需要修改handlermapper和handlMapperAdapter,如下:

 

在springmvc-servlet.xml中配置:

 

<!-- 注解映射器 -->   

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

 

 

注意:

Spring3.1 之前版本,开启注解式处理器为:DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。

 

Spring3.1 之后的版本,开启注解式处理器为:RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

 

 

 

HelloWorldController编写:

 

@Controller

public class HelloWorldController {

 

    @RequestMapping(value="/hello")

    public String hello(Model model)throws Exception{

       model.addAttribute("message","HelloWorld!");

       return"hello";

    }

}

 

 

注解描述:

 

@Controller用于标识是处理器类

 

@RequestMapping请求到处理器功能方法的映射规则

 

 

Controller配置

在springmvc-servlet.xml中配置定义的controller:

<!-- controller -->

<bean class="springmvc.action.HelloWorldController"/>

 

 

组件扫描

 

<context:component-scanbase-package="springmvc.action" />

 

扫描@component、@controller、@service、@repository的注解

 

注意:如果使用组件扫描则controller不需要在springmvc-servlet.xml中配置

 

@Controller

 

标识该类为控制器类,@controller、@service、@repository分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口。

 

@RequestMapping

URL路径映射

@RequestMapping(value="/user")或@RequestMapping("/user")

根路径+子路径

根路径:

@RequestMapping放在类名上边,如下:

@Controller

@RequestMapping("/user")

子路径:

@RequestMapping放在方法名上边,如下:

@RequestMapping("/useradd")

public String useradd(….

 

URI 模板模式映射

@RequestMapping(value="/useredit/{userId}"):{×××}占位符, 请求的URL可以是“/useredit/001”或“/useredit/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

 

@RequestMapping("/useredit/{userid}")

    public String useredit(@PathVariable String userid,Modelmodel)throws Exception{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

 

多个占位符:

 

@RequestMapping("/useredit/{groupid}/{userid}")

public String useredit(@PathVariable Stringgroupid,@PathVariable Stringuserid,Model model)throwsException{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("groupid",groupid);

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

正则表达式url映射

 

限制只允许输入数字:

RequestMapping(value="/useredit/{userid:\\d+}")

限制只允许输入数字、英文字符:

RequestMapping(value="/useredit/{userid:[A-Za-z0-9]+}")

 

 

请求方法限定
限定GET方法

@RequestMapping(method = RequestMethod.GET)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'POST' notsupported

 

例如:

@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)

限定POST方法

 

@RequestMapping(method = RequestMethod.POST)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'GET' notsupported

 

GET和POST都可以

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

 

 

 

请求数据绑定

默认支持的参数类型
HttpServletRequest

通过request对象获取请求信息

HttpServletResponse

通过response处理响应信息

HttpSession

通过session对象得到session中存放的对象

Model、Map、ModelMap

通过model、map及modelMap向页面传递数据,如下:

 

modelMap.put("user1"new User("张三"));

model.addAttribute("user2"new User("李四"));

map.put("user3",new User("王五"));

 

命令/表单对象

自动将请求参数绑定到功能处理方法的命令/表单对象上。

 

Java基本数据类型
布尔型:

页面如下:

 

<tr>

<td>是否好学生:</td>

<td>

<inputtype="radio"name="isgood"value="true"/>

<inputtype="radio"name="isgood"value="false"/></td>

</tr>

<tr>

日期型需要添加属性编辑器:

@InitBinder

    public void initBinder(HttpServletRequest request,

           ServletRequestDataBinder binder) throws Exception {

       binder.registerCustomEditor(Date.class,newCustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));

    }

 

Pojo对象
页面上以pojo对象中属性名称命名:

将pojo对象中的属性名于传递进来的属性名对应,对应上的将值设置在pojo对象中

 

页面定义如下;

 

<inputtype="text" name="age"/>

<inputtype="text" name="birthday"/>

 

页面上以pojo对象名点 属性名命名:

需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。

包装对象定义如下:

public class UserVo {

  private Useruser;

 

public User getUser() {

    return user;

}

 

public void setUser(User user) {

    this.user = user;

}

}

 

页面定义:

 

<inputtype="text" name="user.height" />

 

字符串数组

页面传递逗号分隔的字符串,springmvc中以String[]接收。

 

List

List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。

 

List中对象:

成绩对象

public classStudentScore {

   private Stringcoursename;//课程名称

   private Floatscore;//成绩

   public String getCoursename(){

      return coursename;

   }

   public void setCoursename(Stringcoursename) {

      this.coursename = coursename;

   }

   public Float getScore() {

      return score;

   }

   public void setScore(Float score) {

      this.score = score;

   }

}

 

包装类中定义List对象,并添加get/set方法如下:

 

private List<StudentScore> scores;//成绩

 

页面:

 

<tr>

<td>兴趣课程:</td>

<td>

课程名:<inputtype="text"name="scores[0].coursename"/>成绩:<inputtype="text"name="scores[0].score"/><br/>

课程名:<inputtype="text"name="scores[1].coursename"/>成绩:<inputtype="text"name="scores[1].score"/><br/>

课程名:<inputtype="text"name="scores[2].coursename"/>成绩:<inputtype="text"name="scores[2].score"/><br/>

</td>

</tr>

 

Map

在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。

包装类中定义Map对象如下:

private Map<String, Object>userinfo = new HashMap<String, Object>();

 

 

页面定义如下:

 

<tr>

<td>学生详细信息:</td>

<td>

地址:<inputtype="text"name="userinfo['address']"/>

朋友:<inputtype="text"name="userinfo['firend']"/>

</td>

</tr>

 

 

@RequestParam绑定单个请求参数

 

value参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;

required是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;

defaultValue默认值,表示如果请求中没有同名参数时的默认值

 

 

 

@PathVariable 绑定URI 模板变量值

 

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上

 

@RequestMapping(value="/useredit/{groupid}/{userid}",method={RequestMethod.GET,RequestMethod.POST})

    public String useredit(@PathVariable String groupid,@PathVariable Stringuserid,Model model)throwsException{

       //方法中使用@PathVariable获取useried的值,使用model传回页面

       model.addAttribute("groupid", groupid);

       model.addAttribute("userid", userid);

       return"/user/useredit";

    }

 

如请求的 URL 为“控制器URL/useredit/1/admin.action”,则自动将URL 中模板变量{groupid}和{userid}绑定到@PathVariable注解的同名参数上,即入参后groupid=“1”、userid=“admin”

 

 

@RequestBody @ResponseBody实现json数据交互
@RequestBody

作用:

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

 

本例子应用:

@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

 

@ResponseBody

作用:

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

 

本例子应用:

@ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

 

请求json,响应json实现:
环境准备

Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包,如下:

配置:

 

在注解适配器中加入messageConverters

 

<!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

       <propertyname="messageConverters">

         <list>

            <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>

         </list>

       </property>

    </bean>

 

 

controller编写

/**

     * 请求json单个对象,返回json单个对象

     * @param user

     * @return

     * @throws Exception

     */

    @RequestMapping("/requestjson")

    //@RequestBody接收json串自动转为user对象,@ResponseBodyuser转为json数据响应给客户端

    public @ResponseBody User requestjson(@RequestBody User user)throws Exception{

       System.out.println(user);

       return user;

    }

 

 

页面js方法编写:

function request_json(){

         var user =JSON.stringify({name:"张三", age: 3});

         alert(user);

      $.ajax(

       {

           type:'post',

           url:'${pageContext.request.contextPath}/requestjson.action',

           contentType:'application/json;charset=utf-8', //请求内容为json

           data:user,

           success:function(data){

              alert(data.name);

           }

       }    

      )

  }

 

 

测试结果:

 

从上图可以看出请求的数据是json格式

 

从上图可以看出响应的数据也是json格式,json数据的内容是从User对象转换得来。

 

Form提交,响应json实现:

采用form提交是最常用的作法,通常有post和get两种方法,响应json数据是为了方便客户端处理,实现如下:

 

环境准备

同第一个例子

 

controller编写

 

/**

    * 客户端提交表单,服务端返回json

    * @param user

    * @return

    * @throws Exception

    */

   @RequestMapping("/formsubmit")

   public @ResponseBody Userformsubmit(User user)throws Exception{

      System.out.println(user);

      return user;

   }

 

页面js方法编写:

 

function formsubmit(){

        var user ="name=张三&age=3";

        alert(user);

     $.ajax(

      {

         type:'post',//这里改为get也可以正常执行

         url:'${pageContext.request.contextPath}/formsubmit.action',

//ContentType没指定将默认为:application/x-www-form-urlencoded

         data:user,

         success:function(data){

            alert(data.name);

         }

        

      }   

     )

}

 

从上边的js代码看出,已去年ContentType的定义,ContentType默认为:application/x-www-form-urlencoded格式。

 

 

测试结果:

从上图可以看出请求的数据是标准的key/value格式。

 

从上图可以看出响应的数据也是json格式,json数据的内容是从User对象转换得来。

 

 

简化配置:

注解映射器和注解适配器可以使用<mvc:annotation-driven />代替。

<mvc:annotation-driven />默认注册了注解映射器和注解适配器等bean。

 

如下:

 

以下配置可用<mvc:annotation-driven />代替:

 

 

<!-- 注解映射器 -->   

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!-- 注解适配器 -->

    <beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

       <propertyname="messageConverters">

         <list>

            <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>

         </list>

       </property>

    </bean>

 

10.             拦截器

定义

Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

 

拦截器定义

实现HandlerInterceptor接口,如下:

 

public class HandlerInterceptor1 implements HandlerInterceptor{

 

    /**

     *controller执行前调用此方法

     * 返回true表示继续执行,返回false中止执行

     * 这里可以加入登录校验、权限拦截等

     */

    @Override

    public boolean preHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler) throws Exception {

       // TODO Auto-generatedmethod stub

       return false;

    }

    /**

     *controller执行后但未返回视图前调用此方法

     * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示

     */

    @Override

    public void postHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler,

           ModelAndView modelAndView) throws Exception {

       // TODO Auto-generatedmethod stub

      

    }

    /**

     * controller执行后且视图返回后调用此方法

     * 这里可得到执行controller时的异常信息

     * 这里可记录操作日志,资源清理等

     */

    @Override

    public void afterCompletion(HttpServletRequest request,

           HttpServletResponse response, Object handler, Exceptionex)

           throws Exception {

       // TODO Auto-generatedmethod stub

      

    }

 

}

 

 

拦截器配置

 

<bean

    class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

    <propertyname="interceptors">

       <list>

           <refbean="handlerInterceptor1"/>

           <refbean="handlerInterceptor2"/>

       </list>

    </property>

</bean>

    <beanid="handlerInterceptor1"class="springmvc.intercapter.HandlerInterceptor1"/>

    <beanid="handlerInterceptor2"class="springmvc.intercapter.HandlerInterceptor2"/>

 

 

 

正常流程测试

 

代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。

 

 

运行流程

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

 

HandlerInterceptor2..postHandle..

HandlerInterceptor1..postHandle..

 

HandlerInterceptor2..afterCompletion..

HandlerInterceptor1..afterCompletion..

 

 

中断流程测试

代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2。

 

 

运行流程

HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:

 

HandlerInterceptor1..preHandle..

 

从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。

 

 

HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:

 

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

HandlerInterceptor1..afterCompletion..

 

从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。

 

总结:

preHandle按拦截器定义顺序调用

postHandler按拦截器定义逆序调用

afterCompletion按拦截器定义逆序调用

 

postHandler在拦截器链内所有拦截器返成功调用

afterCompletion只有preHandle返回true才调用

 

 

拦截器应用

 

用户身份认证

 

public class LoginInterceptor implements HandlerInterceptor{

 

    @Override

    public boolean preHandle(HttpServletRequest request,

           HttpServletResponse response, Object handler) throws Exception {

 

       //如果是登录页面则放行

       if(request.getRequestURI().indexOf("login.action")>=0){

           return true;

       }

       HttpSession session = request.getSession();

       //如果用户已登录也放行

       if(session.getAttribute("user")!=null){

           return true;

       }

       //用户没有登录挑战到登录页面

       request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

      

       return false;

    }

}

 

 转自:http://blog.csdn.net/u010575112/article/details/41369431?ref=myread

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值