java深入探究15-SpringMVC


测试代码:链接:http://pan.baidu.com/s/1c1QGYIk 密码:q924

回顾spring+struts

web.xml配置;struts核心过滤器;spring监听器->配置spring.xml;struts.xml

  

1.生命周期

  /hello.action->先访问web.xml->通过springMVC核心核心控制器DispatcherServlet-跳转(可以默认也可以指定)到springmvc.xml配置文件(有4个对象:1.注册Action,我们访问的对象;2.映射器BeanNameUrlHandlerMapping映射Bean name属性url地址,SimpleUrlHandlerMapping映射bean的id属性可以适配多个;3.SimpleControllerHandlerAdapter适配器用于适配继承Control的类;4视图解析器InternalResourceViewResolver通过modelandView视图名找到真正的视图)-》BeanNameUrlHandlerMapping找到action或者通过SimpleControllerHandlerAdapter找到action-》再逻辑处理完后通过视图解析器跳转到目标对象

工作流:

1A)客户端发出http请求,只要请求形式符合web.xml
   文件中配置的*.action的话,就由DispatcherServlet
   来处理。

1B)DispatcherServlet再将http请求委托给映射器
   的对象来将http请求交给对应的Action来处理

2)映射器根据客户的http请求,再对比   如果匹配正确,再将http请求交给程序员写的Action

3)执行Action中的业务方法,最终返回一个名叫ModelAndView
   的对象,其中封装了向视图发送的数据和视图的逻辑名

4)ModelAndView对象随着响应到到DispatcherServlet中了


5)这时DispatcherServlet收到了ModelAndView对象,
   它也不知道视图逻辑名是何意,又得委托一个名叫
   视图解析器的对象去具体解析ModelAndView对象
   中的内容

6)将视图解析器解析后的内容,再次交由DispatcherServlet
   核心控制器,这时核心控制器再将请求转发到具体的
   视图页面,取出数据,再显示给用户

2.spring快速入门 XML版

  1)步一:创建springmvc-day01这么一个web应用

  2)步二:导入springiocspringweb , springmvc相关的jar

  3)步三:在/WEB-INF/下创建web.xml文件

    
    <servlet>
        <servlet-name>DispatcherServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServletservlet-name>
        <url-pattern>*.actionurl-pattern>
    servlet-mapping>

    其中再web中还可以配置乱码过滤器

      在org.springframework.web.filter.CharacterEncodingFilter


    <filter>
        <filter-name>CharacterEncodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter filter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
过滤器加上这个作用:无论客户段是否有编码都用过滤其中编码解析 
         
            forceEncoding  
            true  
        

  4)创建HelloAction.java控制器类

/**
 * 控制器
 * @author AdminTC
 */
public class HelloAction implements Controller{
    /**
     * 业务方法
     */
    public ModelAndView handleRequest(HttpServletRequest requqest,HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message","这是我的第一个springmvc应用程序");
        modelAndView.setViewName("/jsp/success.jsp");
        return modelAndView;
    }
}

  其中:

    1.继承Controller实现接口对ModelAndView对象模块视图对象赋值处理返回结果并跳转页面

      这个对象是单例对象,构造函数只在程序运行的时候执行;之后执行都是handleRequest方法

    2.

  5)/WebRoot/下创建jsp/success.jsp;这里反应结果页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    success.jsp 成功<br>
    ${requestScope.message }<br/>
    姓名:${requestScope.emp.username}<br/>
    性别:${requestScope.emp.gender}<br/>
     入职时间:${requestScope.emp.hiredate}<br/>
    入职时间:<fmt:formatDate 
                value="${requestScope.emp.hiredate}"
                type="date"
                dateStyle="medium"
            />
        
  body>
html>

  可以通过requestScope获得对象;日期问题可以通过:

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

    入职时间:<fmt:formatDate 
                value="${requestScope.emp.hiredate}"
                type="date"
                dateStyle="medium"
            />
        

  6)/WEB-INF/创建DispatcherServlet-servlet.xml配置文件,xml头部信息与spring.xml相同

       注意:该配置文件的命名规则:web.xml文件中配置的的值-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:context="http://www.springframework.org/schema/context"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:tx="http://www.springframework.org/schema/tx"
      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/aop 
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        
      ">
      
      
    
    
    <bean name="/hello.action" class="cn.itcast.javaee.springmvc.base.HelloAction">bean>  
    
    
      
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">bean>  
      
      
      
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">bean>  
      
      
      
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">bean>  
      
      
beans>

  其中,配置位置可以自己定义;也可以在包中创建再通过src下的配置文件引用这个配置文件

  配置文件中四个对象

  7)部署web应用到tomcat中,通过浏览器访问如下URL

       http://127.0.0.1:8080/springmvc-day01/hello.action

3.加载自定义目录下的springmvc.xml配置文件

    
    <servlet>
        <servlet-name>DispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:spring.xmlparam-value>    
        init-param>
    servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServletservlet-name>
        <url-pattern>*.actionurl-pattern>
    servlet-mapping>

4.解析视图逻辑名对应的真实路径

      
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>

5.映射器Mapping

1) org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping(核心)

      
      <bean name="/add.action" class="cn.itcast.javaee.springmvc.mapping.UserAction">bean>

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

2) org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

      
      <bean id="userActionID" class="cn.itcast.javaee.springmvc.mapping.UserAction">bean>
        
      
      <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
              <property name="mappings">
                  <props>
                      <prop key="/delete.action">userActionIDprop>
                      <prop key="/update.action">userActionIDprop>
                      <prop key="/find.action">userActionIDprop>
                  props>
              property>
      bean>

6.控制器Controller

  org.springframework.web.servlet.mvc.ParameterizableViewController

  如果请求是/hello.action的请求路径,则直接跳转到/jsp/success.jsp页面,不经过程序员定义的控制器Action

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

  org.springframework.web.servlet.mvc.AbstractCommandController

  能够以实体的形式,收集客户端参数

public class AdminAction extends AbstractCommandController{
    public AdminAction(){
        this.setCommandClass(Admin.class);
    }
    @Override
    protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response, Object obj, BindException bindException)throws Exception {
        System.out.println("AdminAction::handle");
        ModelAndView modelAndView = new ModelAndView();
        Admin admin = null;
        if(obj instanceof Admin){
            admin = (Admin) obj;
        }
        modelAndView.addObject("username",admin.getUsername());
        modelAndView.addObject("gender",admin.getGender());
        modelAndView.addObject("hiredate",admin.getHiredate());
        modelAndView.setViewName("/jsp/success.jsp");
        return modelAndView;
    }
}

7.日期转换和编码过滤器

  1) 在默认情况下,springmvc不能将String类型转成Date类型,必须自定义类型转换器

public class AdminAction extends AbstractCommandController{
    @Override
    protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
    }

  2spring提供的,专用于解决POST提交中文乱码问题,需要在web.xml文件中配置

    
    
        CharacterEncodingFilter
        class>
    org.springframework.web.filter.CharacterEncodingFilter
        class>
        
            encoding
            UTF-8
        
    
    
        CharacterEncodingFilter
        /*
    

------------------------------------------------------------------------

8.springmvc快速入门(注解版本)

   1)一个Action中,可以写多个类似的业务控制方法

@Controller
@RequestMapping(value="/user")
public class UserAction{
    @RequestMapping(value="/add")
    public String add(Model model) throws Exception{
        System.out.println("HelloAction::add()");
        model.addAttribute("message","增加用户");
        return "/success.jsp";
    }
    @RequestMapping(value="/find")
    public String find(Model model) throws Exception{
        System.out.println("HelloAction::find()");
        model.addAttribute("message","查询用户");
        return "/success.jsp";
    }    
}

http://127.0.0.1:8080/myspringmvc-day02/user/add.action;

http://127.0.0.1:8080/myspringmvc-day02/user/find.action

  2)在业务控制方法中写入普通变量收集参数

以参数形式收集客户端参数,springmvc采用方法参数形式的

@Controller
@RequestMapping(value="/user")
public class UserAction{
    @RequestMapping(value="/add")
    public String add(Model model,int id,String name,Double sal) throws Exception{
        System.out.println("HelloAction::add()");
        System.out.println(id + ":" + name + ":" + sal);
        model.addAttribute("message","增加用户");
        return "/success.jsp";
    }    
}

  3)限定某个业务控制方法,只允许GETPOST请求方式访问

@Controller
@RequestMapping(value="/user")
public class UserAction{
    @RequestMapping(value="/add",method=RequestMethod.POST)
    public String add(Model model,int id,String name,double sal) throws Exception{
        System.out.println("HelloAction::add()::POST");
        System.out.println(id + ":" + name + ":" + sal);
        model.addAttribute("message","增加用户");
        return "/success.jsp";
    }    
}

  4)在业务控制方法中写入RequestResponse等传统web参数

传统web参数,这种方式我们不提倡,耦合了

@Controller
@RequestMapping(value="/user")
public class UserAction{
    @RequestMapping(value="/add",method=RequestMethod.POST)
    public void add(HttpServletRequest request,HttpServletResponse response) throws Exception{
        System.out.println("HelloAction::add()::POST");
        int id = Integer.parseInt(request.getParameter("id"));
        String name = request.getParameter("name");
        double sal = Double.parseDouble(request.getParameter("sal"));
        System.out.println(id + ":" + name + ":" + sal);
        request.getSession().setAttribute("id",id);
        request.getSession().setAttribute("name",name);
        request.getSession().setAttribute("sal",sal);
        response.sendRedirect(request.getContextPath()+"/register.jsp");
    }    
}

  5)在业务控制方法中写入模型变量收集参数,且使用@InitBind来解决字符串转日期类型

    
"${pageContext.request.contextPath}/user/add.action" method="POST"> 编号:"text" name="id" value="${id}"/>
姓名:"text" name="name" value="${name}"/>
薪水:"text" name="sal" value="${sal}"/>
入职时间:"text" name="hiredate" value=''/>
"submit" value="注册"/>
@Controller @RequestMapping(value = "/user") public class UserAction { @InitBinder protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception { binder.registerCustomEditor( Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } @RequestMapping(value = "/add", method = RequestMethod.POST) public String add(int id, String name, double sal, Date hiredate, Model model) throws Exception { System.out.println("HelloAction::add()::POST"); model.addAttribute("id", id); model.addAttribute("name", name); model.addAttribute("sal", sal); model.addAttribute("hiredate", hiredate); return "/register.jsp"; } }

  6)务控制方法中写入UserAdmin多个模型收集参数

@Controller
@RequestMapping(value = "/user")
public class UserAction {
    @InitBinder
    protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(
                Date.class, 
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
    }
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String add(User user,Model model) throws Exception {
        System.out.println("HelloAction::add()::POST");
        model.addAttribute("user",user);
        return "/register.jsp";
    }
}

  7)在业务控制方法中收集数组参数

@Controller
@RequestMapping(value="/user")
public class UserAction {
    @RequestMapping(value="/delete")
    public String deleteMethod(int[] ids,Model model) throws Exception{
        System.out.println("UserAction::deleteMethod()");
        System.out.println("需要删除的id为:");
        for(int id : ids){
            System.out.print(id+" ");
        }
        model.addAttribute("message","批量删除成功");
        return "/success.jsp";
    }
}

  8)在业务控制方法中收集List参数

批量注册用户

UserAction.java
@Controller
@RequestMapping(value="/user")
public class UserAction {
    @RequestMapping(value="/addAll")
    public String addAll(Bean bean,Model model) throws Exception{
        for(User user : bean.getUserList()){
            System.out.println(user.getName()+":"+user.getGender());
        }
        model.addAttribute("message","批量增加用户成功");
        return "/success.jsp";
    }
}
Bean.java
public class Bean {
    private List userList = new ArrayList();
    public Bean(){}
    public List getUserList() {
        return userList;
    }
    public void setUserList(List userList) {
        this.userList = userList;
    }
}
 registerAll.jsp
    
"${pageContext.request.contextPath}/user/addAll.action" method="POST"> 姓名:"text" name="userList[0].name" value="哈哈"/> 性别:"text" name="userList[0].gender" value=""/>
姓名:"text" name="userList[1].name" value="呵呵"/> 性别:"text" name="userList[1].gender" value=""/>
姓名:"text" name="userList[2].name" value="嘻嘻"/> 性别:"text" name="userList[2].gender" value=""/>
"submit" value="批量注册"/>

  9)结果的转发和重定向

在转发情况下,共享request域对象,会将参数从第一个业务控制方法传入第二个业务控制方法,反之,重定向则不行

@Controller
@RequestMapping(value="/user")
public class UserAction {

    @RequestMapping(value="/delete")
    public String delete(int id) throws Exception{
        System.out.println("删除用户->" + id);
        //转发到find()
        return "forward:/user/find.action";
        //重定向到find()
        //return "redirect:/user/find.action";
    }
    
    @RequestMapping(value="/find")
    public String find(int id) throws Exception{
        System.out.println("查询用户->" + id);
        return "/success.jsp";
    }
    
}

  10)异步发送表单数据到JavaBean,并响应JSON文本返回

@ResponseBody

@Controller
@RequestMapping(value="/user")
public class UserAction {

    @RequestMapping(value="/add")
    public @ResponseBody User add(User user) throws Exception{
        System.out.println(user.getId()+":"+user.getName()+":"+user.getSal());
        return user;
    }
    
}

------------------------------------需要注意的点-----------------------------------------

1.@restController 和@Controller区别

  @restController是包含@Controller和@ResponseBody的,这里不能配合视图解析器InternalResourceViewResolver,返回jsp页面

  @Controller会配合InternalResourceViewResolver返回jsp页面

  建议:@Controller和@ResponseBody组合使用