SpringMVC框架整理(一)

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

     

     src目录下新建

        

     配置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/contexthttp://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", "aa@163.com", 1, new Department(101, "D-AA")));

        employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));

        employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));

        employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));

        employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 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>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值