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>