java深入探究15-SpringMVC

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

回顾spring+struts

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

  <!-- 
  struts核心过滤器
  <filter>
      <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
      <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  spring监听器
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring.xml</param-value>
  </context-param>
   -->
View Code

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请求,再对比<bean name="/hello.action
   如果匹配正确,再将http请求交给程序员写的Action

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

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


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

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

2.spring快速入门 XML版

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

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

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

    <!-- 注册springmvc框架核心控制器 -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
View Code

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

      在org.springframework.web.filter.CharacterEncodingFilter

<!-- 注册spring提供的针对POST请求的中文乱码问题 -->
    <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>
View Code

  

过滤器加上这个作用:无论客户段是否有编码都用过滤其中编码解析 
       <init-param>  
            <param-name>forceEncoding</param-name>  
            <param-value>true</param-value>  
        </init-param>
View Code

  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;
    }
}
View Code

  其中:

    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"
            />
        <!-- 
        1)fmt:formatDate 来源于 http://java.sun.com/jsp/jstl/fmt
        2)fmt:formatDate作用是格式化日期的显示,例如:2015年5月10日 星期日
        3)value表示需要格式化的值
        4)type表示显示日期,时间,都显示
          type=date表示只显示日期
          type=time表示只显示时间
          type=both表示日期时间均显示
        5)dateStyle表示显示日期的格式:short/medium/default/long/full
    -->
  </body>
</html>
View Code

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

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

    入职时间:<fmt:formatDate 
                value="${requestScope.emp.hiredate}"
                type="date"
                dateStyle="medium"
            />
        <!-- 
        1)fmt:formatDate 来源于 http://java.sun.com/jsp/jstl/fmt
        2)fmt:formatDate作用是格式化日期的显示,例如:2015年5月10日 星期日
        3)value表示需要格式化的值
        4)type表示显示日期,时间,都显示
          type=date表示只显示日期
          type=time表示只显示时间
          type=both表示日期时间均显示
        5)dateStyle表示显示日期的格式:short/medium/default/long/full
    -->
View Code

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

       注意:该配置文件的命名规则:web.xml文件中配置的<servlet-name>的值-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>
View Code

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

  配置文件中四个对象

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

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

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

    <!-- 注册springmvc框架核心控制器 -->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring.xml</param-value>    
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
View Code

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

    <!-- 视图解析器(框架) -->  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
View Code

5.映射器Mapping

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

      <!-- 注册控制器(程序员) -->
      <bean name="/add.action" class="cn.itcast.javaee.springmvc.mapping.UserAction"></bean>

      <!-- 注册映射器(handler包)(框架) -->
      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
View Code

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

      <!-- 注册控制器(程序员) -->
      <bean id="userActionID" class="cn.itcast.javaee.springmvc.mapping.UserAction"></bean>
        
      <!-- 注册映射器(handler包)(框架) -->
      <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
              <property name="mappings">
                  <props>
                      <prop key="/delete.action">userActionID</prop>
                      <prop key="/update.action">userActionID</prop>
                      <prop key="/find.action">userActionID</prop>
                  </props>
              </property>
      </bean>
View Code

6.控制器Controller

  org.springframework.web.servlet.mvc.ParameterizableViewController

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

      <!-- /index.action请求,直接转发到/index.jsp页面 -->
      <bean name="/index.action" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
              <property name="viewName" value="/index.jsp"/>
      </bean>
      
      
     <!-- 注册视图解析器(view包)(框架) 
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/"/>
              <property name="suffix" value=".jsp"/>
      </bean>
      -->
View Code

  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;
    }
}
View Code

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));
    }
View Code

  2spring提供的,专用于解决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>
View Code

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

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";
    }    
}
View Code

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";
    }    
}
View Code

  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";
    }    
}
View Code

  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");
    }    
}
View Code

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

    <form action="${pageContext.request.contextPath}/user/add.action" method="POST">
        编号:<input type="text" name="id" value="${id}"/><br/>
        姓名:<input type="text" name="name" value="${name}"/><br/>
        薪水:<input type="text" name="sal" value="${sal}"/><br/>
        入职时间:<input type="text" name="hiredate" value='<fmt:formatDate value="${hiredate}" type="date"/>'/><br/>
        <input type="submit" value="注册"/>
    </form>

@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";
    }
}
View Code

  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";
    }
}
View Code

  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";
    }
}
View Code

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

批量注册用户

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<User> userList = new ArrayList<User>();
    public Bean(){}
    public List<User> getUserList() {
        return userList;
    }
    public void setUserList(List<User> userList) {
        this.userList = userList;
    }
}
 registerAll.jsp
    <form action="${pageContext.request.contextPath}/user/addAll.action" method="POST"> 
         
        姓名:<input type="text" name="userList[0].name" value="哈哈"/>
        性别:<input type="text" name="userList[0].gender" value=""/>
        <hr/>
        
        姓名:<input type="text" name="userList[1].name" value="呵呵"/>
        性别:<input type="text" name="userList[1].gender" value=""/>
        <hr/>

        姓名:<input type="text" name="userList[2].name" value="嘻嘻"/>
        性别:<input type="text" name="userList[2].gender" value=""/>
        <hr/>
        
        <input type="submit" value="批量注册"/>
        
    </form>
View Code

  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";
    }
    
}
View Code

  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;
    }
    
}
View Code

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

1.@restController 和@Controller区别

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

  @Controller会配合InternalResourceViewResolver返回jsp页面

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

原文地址:https://www.cnblogs.com/xiaoping1993/p/6951521.html