SpringMVC框架整理(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangligong/article/details/52971816

博客主要对SpringMVC框架的知识点进行整理,该篇介绍了SpringMVC的HelloWorld环境搭建,常用注解的使用,Ant路径风格,RestFul编程风格,最后使用SpringMVC实现一个RestFul编程风格的CRUD。



MVC概述

     Model(模型)-View(视图)-Controller(控制器)
     Model(模型):
             业务模型:业务流程和业务逻辑
             数据模型:页面显示的数据.数据库保存的数据对应的javaBean
     View(视图):和用户直接交互的页面、程序界面
     Controller(控制器):调度器控制整个网站的转发逻辑

SringMVC概述

     SpringMVC是基于MVC理念的表现层框架,是目前最主流的MVC框架。
      Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
      支持 REST 风格的 URL 请求 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性


SpringMVC运行流程

SpringMVC的运行逻辑:

        ①客户端请求提交到DispatcherServlet(SpringMVC前端控制器)
      ②由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。
          根据 HandlerMapping提供的信息,再去找到能真正解析和调用业务逻辑方法的适配器。
      ③DispatcherServlet将请求提交到Controller(也称为Handler),也就是使用适配器去执行目标方法
          mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
      ④Controller调用业务逻辑处理后,返回ModelAndView
          ModelAndView包含了要去向视图的信息,以及其他信息
      ⑤ DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
          ViewResoler进行视图解析,调用render.解析出去哪个页面
      ⑥视图负责将结果显示到客户端,渲染
           RequestDispatcher rd
           rd.forward(requestToExpose, response);
 总结:请求到达-->找到能够执行目标方法的适配器--->执行目标方法--->返回视图信息以及数据信息(MV)--->根据返回信息渲染视图--->展示视图

HelloWorld环境搭建


①导入jar包
     Spring基础包
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar

     SpringMVC需要的包
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar

②在web.xml中配置前端控制器
<!--SpringMVC的前端控制器,它是一个真实的Servlet继承于HttpServlet
    因此配置和Servlet配置基本一致
-->
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--这个location写SpringMVC配置文件的-->
             <param-value>location</param-value>
        </init-param>
        <!--这个是启动的优先级,数值越小,优先级越高-->
        <load-on-startup>1</load-on-startup>
    </servlet>
     <!--配置拦截那些请求-->
    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!--这里配置成/,可以拦截所有请求同时又覆盖了DefaultServlet的配置,这样所有的请求都由我们的前端控制器拦截
         同时也体现了RestFul风格编程
         -->
         <url-pattern>/</url-pattern>
    </servlet-mapping>
    
  创建springmvc配置文件,并将配置文件的地址写到location
     
        
     配置location(classpath表示在类路径下)
<param-value>classpath:springmvc.xml</param-value>
     这样基础的环境就搭建好了。

  ④编写一个简单的请求响应流程,测试运行环境
               ①index.jsp(请求/hello)       
    <h1 align="center"><a href="${pageContext.request.contextPath }/hello">Hello</a></h1>                 
               ②编写一个handle处理这个请求
package com.springmvc.handle;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
//基于注解注入,需要加入相关注解
@Controller
public class MyHandle {
    //映射请求地址
    @RequestMapping(" /hello ")
    public String hello() {
        System.out.println("接收到请求");
        return "success";
    }
}
           ③配置SpringMVC框架,让框架帮忙处理请求(springmvc.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 开启包的自动扫描,将加了controller注解的handle类注入 -->
    < context:component-scan base-package="com.springmvc.handle"></context:component-scan>
    <!-- 配置视图解析器,用于渲染mv -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 给返回地址配置一个前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 配置一个后缀 -->
        <property name="suffix" value=".jsp"></property>
        <!--/success.jsp(前缀+返回结果+后缀共同构成转发地址)-->
    </bean>

</beans>
               ④编写响应页面success.jsp
<h1>HelloWorld运行环境配置成功</h1>
               ⑤运行测试

@RequestMapping

      ① 在类上标注,表示该类中的所有handle方法都以这个映射地址开始。 相对于 WEB 应用的根目录
      ② 在方法上标注,若类上没有@RequestMapping,直接表示请求地址,若类上有,类上映射+方法上映射共同构成请求地址。 相对于标记在类上的URL

      作用:DispatcherServlet 截获请求后,就通过控制器上@RequestMapping 提供的映射信息确定请求所对应的处理方法。      
 
      属性:
      value:设置请求地址,在类上标注和在方法上标注/表示的含义不同
      method:设置某个方法处理什么样的请求,method是个数组表示可以处理多个符合要求的请求。默认可以处理任意请求
      params:设置请求参数(可以设置多个请求参数)(支持简单的表达式)
          当配置了params时,必须在请求的时候传入配置的参数,不匹配或者不传都会报错404
          当设置多个请求参数的时候必须都设置,否则报错404
          结论:params设置的请求参数必须精确匹配,否则报错
params = !user 表示请求参数不能设置为user,其他的都可以
params = user!=1 表示请求参数值不能等于1

含有params的代码:
    /**
     * 这个请求地址中必须有password,user可以有可以没有,但是若有user的值不能是1,不能有username
     * 还可以有其他请求
     * @return
     */
    @RequestMapping(value="/test5", params={"user!=1", "password", "!username"})
    public String test5() {
        System.out.println("接受到请求");
        return "success";
    }
     
     headers设置请求头
          发送请求的请求头必须包含headers中的内容,不同的浏览器请求头不同,可以用于区分不同的浏览器
    /**
     * headers (设置只有某一浏览器可以访问)
     * @return
     */
    @RequestMapping(value="/testheader", headers="User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0")
    public String test6() {
        System.out.println("接受到请求");
        return "success";
    }

   设置@RequestMapping的条件后,在发送请求的时候,必须满足上边的所有规则,否则报错,什么也不写表示默认规则。

   return String 转发地址,在springmvc配置文件中配置的视图解析器还会对这个地址进行包装 

  Ant路径风格

   ? : 表示匹配任意一个字符
   * : 表示匹配任意零个或者多个字符
   ** : 表示多层模糊匹配 (要使用**多层模糊匹配要把这两个**包起来)(这样就可以在具体路径之前写多层嵌套路径)
  
  匹配原则:当都是模糊匹配的时候,先精确再模糊,先范围大的再范围小的

     示例:
     Ant路径:/user/*/createUser:
            匹配/user/aaa/createUser、/user/bbb/createUser等URL
                 /user/**/createUser:
           匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL
                  /user/createUser??:
          匹配 /user/createUseraa、/user/createUserbb 等 URL

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class AntUrlPathHandle {
    /**
     * ant路径风格
     *      ?:表示匹配任意一个字符
     *      *:表示匹配任意零个或者多个字符
     *      **:表示多层模糊匹配 (要使用**多层模糊匹配要把这两个**包起来)
     *
     *      当都是模糊匹配的时候,先精确在模糊,先范围大的再范围小的
     * @return
     */
    @RequestMapping(value="/??ervice")
    public String test2() {
        System.out.println("接收到请求地址是模糊匹配?的请求");
        return "success";
    }
    @RequestMapping(value="/*ervice")
    public String test3() {
        System.out.println("接收到请求地址是模糊匹配*的请求");
        return "success";
    }
    @RequestMapping(value="/*/*ervice")
    public String test5() {
        System.out.println("接收到请求地址是模糊匹配一层*的请求");
        return "success";
    }
    @RequestMapping(value="/**/ervice")
    public String test4() {
        System.out.println("接收到请求地址是模糊匹配**多层模糊的请求");
        return "success";
    }
}

RestFul编程风格

   简介:
     REST:即 Representational State Transfer。 (资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
      资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它, 每种资源对应一个特定的 URI。要获取这个资源,访问它的URI就可以, 因此 URI 即为每一个资源的独一无二的识别符
      表现层(Representation)把资源具体呈现出来的形式,叫做它的表现层(Representation)比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
      状态转化(State Transfer)每发出一个请求,就代表了客户端和服务器的一次交互过程HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。 体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

    原生web项目的订单处理的路径
      /order/delete?id=1
      /order/update?id=1
      /order/save
     /order/get?id=1
    
    RestFul编程风格
     order/1 GET 查询1号订单
     order/1 DELETE 删除1号订单
     order/1 PUT 更新1号订单
     order POST 保存一个订单
     每一个路径{orderHandle}只能占一层路径,而且必须有

     RestFul本质就是充分利用Http协议中定义了很多请求方式。有了这个支持。地址还是不变。不同的请求方式就代表当前资源不同的状态转化(删除?修改?保存?....)数据都放在请求体中,不放在地址栏后

@PathVariable 映射 URL 绑定的占位符
     带占位符的 URL 是 Spring3.0 新增的功能,该功能在 SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
     通过@PathVariable 可以将 URL中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable("xxx") 绑定到操作方法的入参中。

这样在@RequestMapping配置的映射地址设置占位符,同时使用@PathVariable注解可以获取到

HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支持, Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求。
    
    原生的jsp页面无法发送DELETE请求和PUT请求,要想发送需要在web.xml中进行配置
        <!-- 配置配置org.springframework.web.filter.HiddenHttpMethodFilter来支持页面发起restful请求 PUT、DELETE -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter. HiddenHttpMethodFilter </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <servlet-name>springDispatcherServlet</servlet-name>
    </filter-mapping>

写一个简易的RestFul风格的程序
               orderManage.jsp
<%@ 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>Insert title here</title>
</head>
<body>
    <h1>订单管理</h1>
    <!-- get请求获取订单 -->
    <a href="/myspringmvc01 /order/1">获取一个订单</a>
    <br>
    <!-- post请求添加订单 -->
    <form action="/myspringmvc01/order" method="post" >
        <input type="submit" value="新增一个订单">
    </form>
    <br>
    <!-- PUT请求修改订单 -->
    <form action="/myspringmvc01/order/1" method="post" >
        <input type="hidden" name="_method" value="PUT" >
        <input type="submit" value="修改一个订单">
    </form>
    <br>
    <!-- DELETE请求删除订单 -->
    <form action="/myspringmvc01/order/1" method="post" >
        <input type="hidden" name="_method" value="DELETE" >
        <input type="submit" value="删除一个订单">
    </form>
</body>
</html>

            处理请求的handle方法
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class RestFulPathHandle {
    /**
     *  订单处理
     *  order 1 GET 获取订单号为1的订单
     *  order 1 DELETE 删除订单号为1的订单
     *  order 1 PUT 更新订单号为1的订单
     *  order   POST 新增订单
     * RestFul 利用Http协议中的多种请求方式实现状态转换
     * 通过判断提交的请求类型来选择执行不同的处理请求的方法
     * {路径,请求参数}只能表示一层路径,必须得有
     * 利用@PathVariable注解从url中获取值给参数赋值
     */
    @RequestMapping(value="/order/ {id}",method=RequestMethod.GET)
    public String getOrder(@PathVariable(" id")String id) {
        System.out.println("获取订单号为" + id + "的订单");
        return "success";
    }
    @RequestMapping( value="/order" ,method=RequestMethod.POST)
    public String saveOrder() {
        System.out.println("新增一个订单");
        return "success";
    }
    @RequestMapping( value="/order/{id}" ,method=RequestMethod.PUT)
    public String updateOrder(@PathVariable( "id" )String id) {
        System.out.println("更新订单号为" + id + "的订单");
        return "success";
    }
    @RequestMapping( value="/order/{id}" ,method=RequestMethod.DELETE)
    public String deleteOrder(@PathVariable( "id" )String id) {
        System.out.println("删除订单号为" + id + "的订单");
        return "success";
    }
}

请求数据传入(请求方法签名处理)

     Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中。 Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。 必要时可以对方法及方法入参标注相应的注解( @PathVariable 、@RequestParam、@RequestHeader 等)、Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。

在原生web中获取请求参数值的时候
     例如:
     请求参数:username=admin 其中username相当于请求参数的键,admin相当于请求参数的值
     我们在servlet中获取的时候是,request.getParameter("username")拿到admin
    
在SpringMVC中类似并且更为简单
获取请求参数的方式
      ①直接在方法的参数列表处,声明一个(保存请求参数值的)参数(入参)
          若不使用@RequestParam注解,参数名就是请求参数的键(相当于getParameter("键")),key=参数名
          在发送请求的时候,不传入任何值,或者键不匹配,key(参数名)=null(value=null)
          键匹配不传值,值为空串。
          可以传入多个键值对。
     
          使用@RequestParam注解(使用注解匹配,注解的value值是键)可以传入多个键值对
          属性:
          value 默认空串(设置键)
          required 默认true (就是必须传参数与这个键匹配的键值对,不传,或者不匹配都会400)
          defaultValue 默认没有,用于设置默认值(键的默认值)
          设置默认值后,required=false,可以不传这个键值对
    
     当获取多个请求参数键值对,SpringMVC框架可以自动匹配,赋值
     注:当不使用注解,参数名就是键,SpringMVC根据参数名获取到对应的值并赋值给这个参数
     使用注解,注解的value值是键,根据键获取对应的值,赋值给这个参数
          
          不使用@RequestParam
    @RequestMapping(value="/testparam")
    public String testParam(String username) {
        //这样就可以拿到传入的username的值
        System.out.println("username=" + username);
        return "success";
    }

          使用@RequestParam
    @RequestMapping(value="/testrequestparam")
    public String testParam2(@RequestParam(value="user",defaultValue="default")String username, String password) {
        System.out.println("username=" + username);
        System.out.println("password=" + password);
        return "success";
    }

      ②还可以使用@PathVariable,@RequestHeader,@CookieValue对入参进行修饰
     请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中
          @RequestHeader修饰入参(将请求头中的某些值和入参进行绑定)
  /**
     * 入参与请求头中的键值对(任意的)进行绑定
     * @RequestHeader   value=key(将入参(参数列表处设置的参数)和请求头中key对应的值绑定)
     * 这些注解的属性和@RequestParam注解属性一致,含义一致
     */
    @RequestMapping(value="/testheader")
    public String testHeader(@RequestHeader(value="User-Agent")String agent) {
        System.out.println("Agent=" + agent);
        return "success";
    }
    @RequestMapping(value="/testheader2")
    public String testHeader2(@RequestHeader(value="Accept-Language")String language) {
        System.out.println("Accept-Language=" + language);
        return "success";
    }

        @CookieValue修饰入参(将Cookie值与入参进行绑定)
    /**
     * 使用@RequestHeader获取Cookie,在第一次请求的时候会报500错,因为第一次请求时没有Cookie
     *  Missing header 'Cookie' of type [java.lang.String]找不见Cookie
     * 获取Cookie使用@CookieValue注解获取(设置defaultValue=""就不会出现500错),Cookie值为空串
     *          还可以获取JSESSIONID
     * @param cookie
     * @return
     */
    @RequestMapping(value="/testcookie")
    public String testCookie(@CookieValue(value="Cookie", defaultValue="")String cookie) {
        System.out.println("Cookie=" + cookie);
        return "success";
    }
    @RequestMapping(value="/testcookie2")
    public String testCookie2(@CookieValue(value="JSESSIONID",defaultValue="")String JSESSIONID) {
        System.out.println("JSESSIONID=" + JSESSIONID);
        return "success";
    }
      
      使用 POJO 对象绑定请求参数值
           使用表单提交数据,Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。

      测试:
          POJO类
Employee类
public class Employee {

    private Integer id;
    private String name;
    private Integer age;
    private Address address;
    public Employee() {
        super();
    }
    public Employee(Integer id, String name, Integer age, Address address) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age
                + ", address=" + address + "]";
    }

}
      
Address
public class Address {
    private String city;
    private String street;
    public Address() {
        super();
    }
    public Address(String city, String street) {
        super();
        this.city = city;
        this.street = street;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    @Override
    public String toString() {
        return "Address [city=" + city + ", street=" + street + "]";
    }
}
         表单:
    <form action="/myspringmvc02/testpojo" method="post">
        name<input type="text" name="name"><br>
        age<input type="text" name="age"><br>
        address.city<input type="text" name="address.city"><br>
        address.street<input type="text" name="address.street"><br>
        <input type="submit" value="提交">
    </form>
          
      处理请求的方法:
   /**
     * SpringMVC框架也可以自动处理POJO(JavaBean对象)
     * 只需要让表单的属性和POJO属性一一对象,然后在方法参数列表设置一个对象引用保存这个对象,
     * 入参设置为一个对象SpringMVC框架在处理这个方法的时候会帮你自动封装,级联属性也可以自动封装
     *
     * 根据表单给的属性值,自动封装成对象
    */
    @RequestMapping(value="/testpojo")
    public String testPOJO(Employee employee) {
        System.out.println(employee);
        return "success";
    }
解决POST中文乱码问题
乱码:
        请求乱码:
           post请求 (原生解决方式)在服务器第一次接收到请求的时候(在filter中设置)
                request.setCharacterEncoding("utf-8")
           get请求 服务器的server.xml中设置
                URIEncoding="UTF-8" (8080端口号设置的那里,大小写都行)
       响应乱码:
          response响应的时候乱码(将数据从服务器发送到浏览器的时候乱码)
          response.setContentType("text/html;charset=UTF-8");

       SpringMVC框架的乱码问题解决方式:
     get请求和原生的解决方式一致
     post请求

               web.xml中配置CharacterEncodingFilter  
<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>
     <init-param>
     <!-- 配置响应编码设置 设置的时候根据请求编码的参数设置-->
          <param-name>forceEncoding</param-name>
          <param-value>true</param-value>
     </init-param>
</filter>
<filter-mapping>
     <filter-name>characterEncodingFilter</filter-name>
     <!-- 对所有请求和.jsp进行拦截 -->
     <url-pattern>/*</url-pattern>
</filter-mapping>

注意: 
     当使用框架提供的响应方式的时候,SpringMVC自动的配置好请求和响应编码
       若使用原生的响应,需要配置编码的text/html(utf-8已经帮你设置)

使用原生的ServletAPI作为入参
      使用原生的ServletAPI作为入参,这些原生的东西,在想要用的时候,只需要在入参处设置即可,SpringMVC框架会给你准备好
      HttpServletRequest
      HttpServletResponse
      HttpSession
      java.security.Principal
      Locale
      InputStream
     OutputStream
     Reader
     Writer
/**
     * 响应的编码测试
     * 使用SpringMVC框架的一个好处就是在想要用的时候直接声明一个变量保存就好
     * 想要使用原生的api只需要在参数列表设置就行
     * @param employee
     * @return
     */
    @RequestMapping(value="/testpon")
    public void testResponse(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("使用原生的api不需要设置返回值");
        System.out.println("param:" + request.getParameter("user"));
        try {
            /*
             * 只有使用原生api,CharacterEncodingFilter会出现乱码,原因,没有设置text/html
             * 但是设置了响应和请求的解码格式
             *
             */
            response.setContentType("text/html");
            response.getWriter().write("你好");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

响应数据传出(处理模型数据)


     从服务器向页面发送响应
          原生:web通过request,session,application域对象传递,然后在页面获取
      SpringMVC实现方式

           ①返回ModelAndView对象 框架自动保存在request域中可以直接在页面获取
           ②方法的参数列表,设置一个Map,ModelMap(实际是一个map),Model(Spring定义的接口)类型的引用,
           添加到这三个类型参数中的对象会被自动保存到request域中
           他们三个在SpringMVC框架中最后都被包装成BindingAwareModelMap

   返回MV对象
 @RequestMapping("/testresponse")
    public ModelAndView testResponse() {
        //创建对象
        Employee employee1 = new Employee(1, "小红", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒", 2000, new Address("盘丝洞", "南郊区"));
        //创建一个ModelAndView对象
        ModelAndView mv = new ModelAndView();
        //设置视图路径,返回的String
        mv.setViewName("success");
        //添加对象到ModelAndView中
        mv.addObject("emp1", employee1);
        mv.addObject("emp2", employee2);
        return mv;
    }
     
     设置 Map/ModelMap/Model
    @RequestMapping("/testres01")
    public String testRes01(Map<String, Object> map) {
        Employee employee1 = new Employee(1, "小红1", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒1", 2000, new Address("盘丝洞", "南郊区"));

        map.put("emp1", employee1);
        map.put("emp2", employee2);
        return "success";
    }
    @RequestMapping("/testres02")
    public String testRes02(ModelMap modelMap) {
        Employee employee1 = new Employee(1, "小红2", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒2", 2000, new Address("盘丝洞", "南郊区"));

        modelMap.addAttribute("emp1", employee1);
        modelMap.addAttribute("emp2", employee2);

        return "success";
    }
    @RequestMapping("/testres03")
    public String testRes02(Model model) {
        Employee employee1 = new Employee(1, "小红3", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒3", 2000, new Address("盘丝洞", "南郊区"));
        model.addAttribute("emp1", employee1);
        model.addAttribute("emp2", employee2);
        System.out.println(model.getClass());
        return "success";
    }
          ③上面的这些方式都是将需要的对象放到request域中

怎么将对象放到session域中?

       两种方式,原生api和@SessionAttributes注解

@SessionAttributes注解只能加到类上
@SessionAttributes(types=Employee.class)
//value和type都可以设置多个,value将指定的对象放到session域中,type将某一类型全部放到session域中
//@SessionAttributes(value="emp1")
@Controller
public class EmployeeHandle {
 将对象放到session域中
    /**
     * 给session域中保存对象
     *  方式 ①使用原生api
     *     ②使用SessionAttributes注解 这个注解只能加到类上
     *          value表示key (表示添加到session域中的key,
     *          具体实现是,保存到request域中的时候再给session中保存一份
     *          type 表示类型,指定类型添加
     *      value,type都可以指定多个
     *      加上注解后,还需要将其添加到request中,才能添加到session
     */
    @RequestMapping("testres04")
    //只需要在参数列表设置参数就可以获取到session
    public String testRes03(HttpSession session){
        Employee employee1 = new Employee(1, "小红3", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒3", 2000, new Address("盘丝洞", "南郊区"));

        session.setAttribute("emp1", employee1);
        session.setAttribute("emp2", employee2);
        return "success";
    }
    @RequestMapping("testres05")
    public String testRes04(ModelMap modelMap) {
        Employee employee1 = new Employee(1, "小红3", 21, new Address("大同", "南郊区"));
        Employee employee2 = new Employee(2, "猪八戒3", 2000, new Address("盘丝洞", "南郊区"));

        modelMap.addAttribute("emp1", employee1);
        modelMap.addAttribute("emp2", employee2);
        return "success";
    }

  @ModelAttribute



对数据库中的数据进行更新,当我们对数据进行更新的时候,并不需要将所有的数据进行更新,一般是 修改部分数据
这是就需要将从数据库获取到的原始数据和从页面获取到的新数据,进行整合,保存起来

在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了 @ModelAttribute 的方法。

在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参
将方法入参对象添加到模型中

测试代码:
     POJO
Employee
public class Employee {

    private Integer id;
    private String name;
    private Integer age;
    private Address address;
    public Employee() {
        super();
    }
    public Employee(Integer id, String name, Integer age, Address address) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age
                + ", address=" + address + "]";
    }

}

Address
public class Address {
    private String city;
    private String street;
    public Address() {
        super();
    }
    public Address(String city, String street) {
        super();
        this.city = city;
        this.street = street;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    @Override
    public String toString() {
        return "Address [city=" + city + ", street=" + street + "]";
    }
}

编写框架的基本配置  

表单:(执行更新操作,只更新name,age但是不能丢失数据库中的原有数据,例如Address)
   <form action="/myspringmvc03/update" method="post">
        name<input type="text" name="name"><br>
        age<input type="text" name="age"><br>
        <input type="submit" value="修改用户">
    </form>

@ModelAttribute
    @ModelAttribute
    public void modelAtt(Map<String, Object> map) {
        System.out.println("预处理,从数据库中查询数据,并放到map中");
        Employee employee = new Employee(1, "张三", 12,new Address("天宫", "南苑"));
        //这里的map,put的key要和之后的方法的@ModelAttribute(value)值,一致才能正确获取
        map.put("emp", employee);
    }

@RequestMapping
    /**
     * 若是直接执行update操作,Address(不需要修改的值)就无法获取到
     * 使用@ModelAttribute,在执行@RequestMapping之前提前给隐藏模型传一些数据库中获取的值
     *
     * 更新操作的思想,将数据库中的原始数据和需要更改的新数据,进行整合,然后保存
     * @param employee
     * @return
     */
    @RequestMapping("/update")
    public String update(@ModelAttribute("emp")Employee employee) {
        System.out.println("执行更新操作");
        System.out.println("更新后的employee=" + employee);
        return "pages/success";
    }

视图和视图解析器

      不论控制器返回一个String,ModelAndView,View都会转换为ModelAndView对象,由视图解析器解析视图,然后,进行页面的跳转。

     请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图。
     Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图
  
     视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
      为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口: 视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题

      视图解析器
     SpringMVC 为逻辑视图名的解析提供了不同的策略, 可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。
      视图解析器的作用:将逻辑视图解析为一个具体的视图对象。
      所有的视图解析器都必须实现 ViewResolver 接口。
     
       常用的视图解析器实现类


     JSP 是最常见的视图技术,可以使用 InternalResourceViewResolver 作为视图解析器,helloworld使用的就是InternalResourceViewResolver

    <!-- 配置视图解析器,用于渲染mv -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver ">
        <!-- 给返回地址配置一个前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 配置一个后缀 -->
        <property name="suffix" value=".jsp"></property>
        <!--/success.jsp(前缀+返回结果+后缀共同构成转发地址)-->
    </bean>

若项目中使用了 JSTL,则 SpringMVC 会自动把视图由 InternalResourceView 转为 JstlView 若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件
  <bean id="messageSource" class="org.springframework.context.support. ResourceBundleMessageSource ">
     <!-- 指定国际化文件的基本名 -->
    <property name="basename" value="i18n"></property>
  </bean>

若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:view-controller 标签实现 (不用编写处理请求的handle方法,但是SpringMVC渲染页面)

    <!-- 使用穿越火线,不过handle直接到指定页面
        直接使用SpringMVC渲染视图
        path,请求路径,view-name视图名字
     -->
     <mvc:view-controller view-name="i18n" path="/i18n"/>

Excel视图
若希望使用 Excel 展示数据列表,仅需要扩展 SpringMVC 提供的 AbstractExcelView 或 AbstractJExcel View 即可。实现 buildExcelDocument() 方法,在方法中使用模型数据对象构建 Excel 文档就可以了。
AbstractExcelView 基于 POI API,而 AbstractJExcelView 是基于 JExcelAPI 的。
视图对象需要配置 IOC 容器中的一个 Bean,使用 BeanNameViewResolver 作为视图解析器即可
若希望直接在浏览器中直接下载 Excel 文档,则可以 设置响应头 Content-Disposition 的值为 attachment;filename=xxx.xls

重定向
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
如果返回的字符串中带 forward:redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和 redirect: 当成指示符,其后的字符串作为 URL 来处理
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
forward:success.jsp:会完成一个到 success.jsp 的转发操作

SpringMVC RestFul风格的CRUD


基本环境配置:
     ①导入jar包
commons-logging-1.1.3.jar
jstl.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
standard.jar
taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar

js静态资源
jquery-1.9.1.min.js
     ②创建springmvc配置文件,并配置web.xml
     spingmvc配置文件
<?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:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 开启自动扫描 -->
    <context:component-scan base-package="com.atguigu"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 标配 加上它,干活的是RequestMappingHandlerAdapter,高级干活的可以做很多的事情,且不会被干掉-->
    <mvc:annotation-driven></mvc:annotation-driven>
     <!--可以引入静态资源-->
    <mvc:default-servlet-handler/>
</beans>
     web.xml配置,并提供乱码解决和可以发送DELETE,PUT请求
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>myspringmvcCRUD</display-name>
  <!-- 配置用于拦截所有请求的前端控制器 -->
  <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!--拦截所有请求 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- CharacterEncodingFilter是SpringMVC专门用来解决请求响应乱码的组件(一个类,这个类来解决乱码问题)
         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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!-- 拦截所有请求,包含*.jsp -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 配置一个支持发送PUT,DELETE请求的filter -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

     ③POJO类和Dao类
Department
package com.atguigu.entities;

public class Department {

    private Integer id;
    private String departmentName;

    public Department() {
    }

    public Department(int i, String string) {
        this.id = i;
        this.departmentName = string;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    @Override
    public String toString() {
        return "Department [id=" + id + ", departmentName=" + departmentName + "]";
    }

}

Employee
package com.atguigu.entities;

public class Employee {

    private Integer id;
    private String lastName;

    private String email;
    //1 male, 0 female
    private Integer gender;

    private Department department;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Employee(Integer id, String lastName, String email, Integer gender,
            Department department) {
        super();
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.department = department;
    }

    public Employee() {
    }
    @Override
    public String toString() {
        return "Employee [id=" + id + ", lastName=" + lastName + ", email="
                + email + ", gender=" + gender + ", department=" + department
                + "]";
    }
}

DepartmentDao
package com.atguigu.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.atguigu.entities.Department;

@Repository
public class DepartmentDao {
    /**
     * departments来保存所有的部门,初始化的时候直接进行赋值
     */
    private static Map<Integer, Department> departments = null;

    static{
        departments = new HashMap<Integer, Department>();

        departments.put(101, new Department(101, "D-AA"));
        departments.put(102, new Department(102, "D-BB"));
        departments.put(103, new Department(103, "D-CC"));
        departments.put(104, new Department(104, "D-DD"));
        departments.put(105, new Department(105, "D-EE"));
    }
    /**
     * 获取所有的部门
     * @return Collection<Department>
     */
    public Collection<Department> getDepartments(){
        return departments.values();
    }

    /**
     * 根据id获取部门
     * @param id
     * @return  Department
     */
    public Department getDepartment(Integer id){
        return departments.get(id);
    }
}

EmployeeDao
package com.atguigu.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.atguigu.entities.Department;
import com.atguigu.entities.Employee;

@Repository
public class EmployeeDao {
    //使用employees集合保存所有的员工,使用static代码块直接进行初始化赋值
    private static Map<Integer, Employee> employees = null;

    @Autowired
    private DepartmentDao departmentDao;

    static{
        employees = new HashMap<Integer, Employee>();

        employees.put(1001, new Employee(1001, "E-AA", "[email protected]", 1, new Department(101, "D-AA")));
        employees.put(1002, new Employee(1002, "E-BB", "[email protected]", 1, new Department(102, "D-BB")));
        employees.put(1003, new Employee(1003, "E-CC", "[email protected]", 0, new Department(103, "D-CC")));
        employees.put(1004, new Employee(1004, "E-DD", "[email protected]", 0, new Department(104, "D-DD")));
        employees.put(1005, new Employee(1005, "E-EE", "[email protected]", 1, new Department(105, "D-EE")));
    }

    private static Integer initId = 1006;
    /**
     * 保存员工,若有id修改,没有id保存
     * @param employee
     */
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
        //设置部门属性
        employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
        //添加一个包装好的员工
        employees.put(employee.getId(), employee);
    }
    /**
     * 获取所有员工
     * @return  Collection<Employee>
     */
    public Collection<Employee> getAll(){
        return employees.values();
    }
    /**
     * 根据id获取员工
     * @param id
     * @return  Employee
     */
    public Employee get(Integer id){
        return employees.get(id);
    }
    /**
     * 根据id删除员工
     * @param id
     */
    public void delete(Integer id){
        employees.remove(id);
    }
}

添加CRUD功能
index.jsp
<%@ 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>Insert title here</title>
<!-- 将导入js文件的标签也放到path中 -->
<%-- <script type="text/javascript" src="${pageContext.request.contextPath }/scripts/jquery-1.9.1.min.js"></script> --%>
<!-- 利用js写一个基础路径 ,和base作用类似,不过比base更通用 -->
<!--  <script type="text/javascript"> -->
    <%
//      String path = request.getContextPath();
//      request.setAttribute("path", path);
    %>
<!-- </script> -->
<!-- 将这个路径抽取出来,使用静态导入,静态包含由服务器解析,使用绝对路径表示(js文件的引入和里面有基础的path)-->
<%@ include file="/WEB-INF/include/path.jsp" %>
</head>
<body>
     <h1 align="center"><a href="${path }/emps">获取所有员工</a></h1>
</body>
</html>

path.jsp(将页面中的基础路径抽取出来单独写在一个jsp中)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<script type="text/javascript" src="${pageContext.request.contextPath }/scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
    <%
        String path = request.getContextPath();
        request.setAttribute("path", path);
    %>
</script>

handle类(用来处理请求的类)
package com.atguigu.handle;

import java.util.Collection;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.atguigu.dao.DepartmentDao;
import com.atguigu.dao.EmployeeDao;
import com.atguigu.entities.Department;
import com.atguigu.entities.Employee;

/**
 * 专门用来处理有关员工增删改查的类
 * @author LENOVO
 *
 */
@Controller
public class EmployeeHandle {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private DepartmentDao departmentDao;

    /**
     * 获取所有员工列表
     * @return
     */
    @RequestMapping("/emps")
    public String getAll(Map<String, Object> map) {
        //获取所有员工
        Collection<Employee> all = employeeDao.getAll();
        //添加到map集合中,自动帮你放到request域中,在页面可以直接使用EL表达式取
        map.put("list", all);
        return "pages/list";
    }
    /**
     * 去编辑页面
     * @return
     */
    @RequestMapping("/toedit")
    public String toEdit() {
        return "pages/edit";
    }
    /**
     * 保存一个用户
     * @return
     */
    @RequestMapping(value="/emp", method=RequestMethod.POST)
    public String saveEmp(Employee employee) {
        //设置POJO,将表单添加的信息自动封装成对象
        System.out.println(employee);
        employeeDao.save(employee);
        //重定向到list页面
        return "redirect:/emps";
    }
    /**
     * 修改员工,需要先查询员工的信息,保存到request中,然后在页面中取出来
     * 这里入参设置一个map,将员工信息保存到request中(渲染页面的时候,会将map中的保存到request中)
     * @return
     */
    @RequestMapping(value="/emp/{id}", method=RequestMethod.GET)
    public String getEmp(@PathVariable(value="id")Integer id, Map<String, Object> map) {
        Employee employee = employeeDao.get(id);
        map.put("employee", employee);
        return "pages/edit";
    }
    /**
     * 更新记录
     * @param id
     * @param employee
     * @return
     */
    @RequestMapping(value="/emp/{id}", method=RequestMethod.PUT)
    public String updateEmp(Employee employee) {
        employeeDao.save(employee);
        return "redirect:/emps";

    }
    @RequestMapping(value="/emp/{id}", method=RequestMethod.DELETE)
    public String delEmp(@PathVariable(value="id") Integer id) {
        employeeDao.delete(id);
        return "redirect:/emps";
    }
    /**
     * 增删改查都以提交表单的形式,因此可以从请求参数中获取id
     * 要想使用SpringMVC提供的from表单显示数据,需要向页面传递一个对象,
     * 这样他们在页面才可以获取到数据
     * 如果这里不放对象会报错
     * @return

     */
    @ModelAttribute
    public Employee modelAttr(@RequestParam(value="id", required=false)Integer id, Map<String, Object> map) {
        //这个方法在执行任意的Handle方法之前都会执行。从请求参数中获取id,当有id的时候是修改,删除,或者查询,否则是添加
        //获取到所有的部门,在页面的下拉列表中显示
        Collection<Department> departments = departmentDao.getDepartments();

        map.put("depts", departments);

        if(id == null) {
            return new Employee();
        } else {
            //需要将这个对象传出去,否则报错(必须传个对象只能传根据id获取的,否则handle方法不能执行)
            //然后执行handle的时候拿到的就是根据id查询到的员工
            Employee employee = employeeDao.get(id);
            return employee;
        }
    }
}

  list.jsp(显示所有员工的页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
<!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>Insert title here</title>
<!-- 引入js和基础的path -->
<%@ include file="/WEB-INF/include/path.jsp" %>
<script type="text/javascript">
    $(function() {
        $(".del").click(function() {
            $("#formdel").attr("action", this.href);
            $("#formdel").submit();
            return false;
        });
    });
</script>
</head>
<body>
    <h1 align="center">员工信息列表</h1>
    <table align="center" border="10" cellpadding="10" cellspacing="0">
        <tr>
            <td>id</td>
            <td>姓名</td>
            <td>性别</td>
            <td>邮箱</td>
            <td>部门</td>
            <td>修改</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${list }" var="emp">
            <tr>
                <td>${emp.id }</td>
                <td>${emp.lastName }</td>
                <c:if test="${emp.gender == 0 }">
                    <td>女</td>
                </c:if>
                <c:if test="${emp.gender == 1 }">
                    <td>男</td>
                </c:if>
                <td>${emp.email }</td>
                <td>${emp.department.departmentName }</td>
                <td><a href="${path}/emp/${emp.id}">修改</a></td>
                <td><a href="${path}/emp/${emp.id}" class="del">删除</a></td>
            </tr>
        </c:forEach>
    </table>
        <h3 align="center"><a href="${path}/toedit" >添加员工</a></h3>
    <form action="${path }/emp/${emp.id}" method="post" id="formdel">
        <input type="hidden" name="_method" value="DELETE">
    </form>
</body>
</html>

edit.jsp(员工编辑页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!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>Insert title here</title>
<%@ include file="/WEB-INF/include/path.jsp" %>
</head>
<body>
    <form:form action="${path }/emp/${id}" modelAttribute="employee" method="post">
        <c:if test="${ empty employee.id }">
            姓名:<form:input path="lastName"/><br><br>
        </c:if>
        <c:if test="${ !empty employee.id }">
            <!-- 若不加这个姓名会丢失 -->
            <form:hidden path="id"/>
            <input type="hidden" name="_method" value="PUT">
        </c:if>
        邮箱:<form:input path="email"/><br><br>
        <!-- 性别使用单选 -->
        性别:
        女<form:radiobutton path="gender" value="0"/>
        男<form:radiobutton path="gender" value="1"/><br><br>
        <!--
            部门使用复选框
            path:select的name值
            items="${depts }":指定下拉列表的值从哪里去
            itemLabel="departmentName" :option标签体中的东西
            itemValue="id":option的value值
            自动遍历
         -->
        部门:<form:select path="department.id" items="${depts }" itemLabel="departmentName" itemValue="id"></form:select><br><br>
        <input type="submit" value="保存">
    </form:form>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/wangligong/article/details/52971816