Spring 以一种抽象的 方式实现了控制器概念,这样可以支持不同类型的控制器。Spring 本身包含表单控制器、 命令控制器、向导型控制器等多种多样的控制器。 Spring 控制器架构的基础是 org.springframework.mvc.Controller 接口, 其代码如下 public interface Controller { /** * @param request current HTTP request * @param response current HTTP response * @return a ModelAndView to render, or null if handled directly * @throws Exception in case of errors */ ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; } 虽然 Controller 接口是完全抽象的, 但 Spring 也提供了许多你可能会用到的控制器。 Controller 接口仅仅定义了每个控制器都必须提供的基本功能: 处理请求并返回一个模型 和一个视图 1.4.2. AbstractCommandController AbstractCommandController 可以使用该抽象命令控制器来创建自己的命令控制器,它 能够将请求参数绑定到指定的命令对象。 这个类并不提供任何表单功能, 但是它提供验证功 能,并且让你在控制器中去实现如何处理由请求参数值产生的命令对象 /** * 它能够将请求参数绑定到指定的命令对象 */ @SuppressWarnings("deprecation") public class CommandController extends AbstractCommandController { public CommandController(){ // 指定要绑定的类型 this.setCommandClass(Student.class); } @Override protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { // 输入的数据为,必须转化为指定的类型 Student student=(Student)command; System.out.println("id=" + student.getId()); System.out.println("name=" + student.getName()); // Spring提供了ModelMap类型,用来存储参数,默认的范围是Request ModelMap modelMap=new ModelMap(); // 把数据存储到modelMap中 modelMap.addAttribute("student",student); // 页面可以通过${requestScope.student.id}获取数据 return new ModelAndView("result",modelMap); } } 也可以通过配置文件注入类型(推荐使用) AbstractCommandController,已经是过时的类了,在它的源码中有如下的描述 @deprecated as of Spring 3.0, in favor of annotated controllers 1.5. 基于注解 MVC 实现 只有对应的 HandlerMapping(为了实现类型级别的注解)和/或 HandlerAdapter(为了 实现方法级别的注解)出现在 dispatcher 中时, @RequestMapping 才会被处理, 所以要修 改默认的 HandlerMapping, 修改为如下配置: 1.5.1. AnnotationHandler 1.5.2. @RequestMapping /** * 基于注解的控制器实现(此方式推荐) */ @RequestMapping(value="/annotion") public class AnnotationControll { public AnnotationControll(){ System.out.println("----AnnotationControll----"); } /* * 可以通过三种方式接收 : 属性对应 , 与对象的属性对应 , 直接通过 request对象获取 * 如果属性的值与前面的不同可以采用@RequestParam注解来匹配 * */ @RequestMapping(value="/demo") public String demo01(@RequestParam(value="id") int sid,String name,Student student,HttpServletRequest request){ System.out.println("id=" + sid + ",name=" + name); System.out.println("id=" + student.getId() + ",name=" + student.getName()); System.out.println("id=" + request.getParameter("id") + ",name=" + request.getParameter("name")); return "forward:/WEB-INF/jsp/result.jsp"; // 等 同 于 return result; } } 1.5.3. mvc:annotation-driven 注意: 在 Spring3.0 可以采用注解的方式取代 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 1.6. 优化部分 1.6.1. @SessionAttributes Spring 2.0 定义了一个 org.springframework.ui.ModelMap 类, 它作为通用的模型数 据承载对象, 传递数据供视图所用。 我们可以在请求处理方法中声明一个 ModelMap 类型的 入参,Spring 会将本次请求模型对象引用通过该入参传递进来,这样就可以在请求处理方 法内部访问模型对象了在默认情况下, ModelMap 中的属性作用域是 request 级别是, 也就 是说,当本次请求结束后,ModelMap 中的属性将销毁 如果请求是会话属性, 即在处理类定义处标注了@SessionAttributes("xxx"), 则尝试从会 话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找 不到对应的属性,则抛出 HttpSessionRequiredException 异常 org.springframework.web.HttpSessionRequiredException: Session attribute 'user' required - not found in session... @SessionAttributes(value={"student"}) 和 @SessionAttributes(type={Student.class}) 出现此异常,都可以通过如下方式解决: @ModelAttribute("student") // sessionScope.student来显示 public Student getUser(){ Student student = new Student(); return student; } 1.6.2. 乱码解决方案: encodingFilter org.springframework.web.filter.CharacterEncodingFil ter encoding UTF-8 encodingFilter /* 1.7. 拦截器介绍 Spring MVC 的拦截器, 是属于 HandlerMapping 级别的, 可以有多个 HandlerMapping 每 个 HandlerMapping 可以有自己的拦截器, 创建的拦截器必须实现 HandlerInterceptor 接口 1.7.1. 自定义一个拦截器 /* * 拦截器, 在控制器之前执行,用来做权限验证,等操作,也可以在控制器之后, 视图之前执行,例如全局的异常处理 * */ public class MyHandlerInterceptor implements org.springframework.web.servlet.HandlerInterceptor { public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Action抛出异常也会执行"); } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("控制器之后,生成视图之前执行"); } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("控制器之前执行"); // 如果返回为false则终止 return true; } } 1.7.2. 配置拦截器 xmlns:mvc="http://www.springframework.org/schema/mvc" http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 也可以把拦截器配置到 HandlerMapping 中

1.7.3. 拦截器实现登录验证 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) Exception { HttpSession session = request.getSession(); if(session.getAttribute("user")==null){ response.sendRedirect("/mvc/login.jsp"); return false; } return true; } throws 1.8. JSON 交互 1.8.1. 导入依赖的 json.jar 在 Spring mvc3 中,响应、接受 JSON 都十分方便。 使用注解@ResponseBody 可以将结果(一个包含字符串和 JavaBean 的 Map) ,转换成 JSON。 使用 RequestBody 注解前台只需要向 Controller 提交一段符合格式的 JSON,Spring 会 自动将其拼装成 bean。 Spring 这个转换是靠 org.codehaus.jackson 这个组件来实现的,所有需要引入 jackson-core-asl 和 jackson-mapper-asl 两个 jar 包 jackson-core-asl-1.7.2.jar jackson-mapper-asl-1.7.2.jar 1.8.2. 配置数据转化器(可选)

text/html;charset=UTF-8

1.8.3. 添加 ResponseBody 标签 @ResponseBody // 返回的类型为JSON类型 @RequestMapping("/demo02") // 要添加: public Object demo02(Student temp){ System.out.println("temp.id=" + temp.getId()); System.out.println("temp.name=" + temp.getName()); System.out.println("----demo02-----"); Student student=new Student(); student.setId(1); student.setName("admin"); student.setPass("admin***"); Student student2=new Student(); student2.setId(2); student2.setName("admin2"); student2.setPass("admin2***"); // Student[] arr={student,student2}; 测试过OK List arr=new ArrayList(); arr.add(student); arr.add(student2); return arr; } 前台访问的代码如下: $(function(){ $('#ajax').click(function(){ $.post('third/demo02.action',{id:123,name:'jsontest'},function(da ta){ alert(data); // 无论是一个还是多个返回的是JSON数 组 for(var i=0;i