一、使用入门
步骤:
1、引入依赖jar包

2、编写web.xml,声明创建DispatcherServlet

tomcat解析web.xml时会自动创建该servlet,并且该servlet里面实现了自动创建一个web环境下的spring容器的功能
该创建的web环境spring容器会自动读取一个spring的配置文件(命名:DispatcherServlet的名字-servlet.xml)
读取配置文件规则:
默认会自动读取WEB-INF目录下的与当前DispatcherServlet的名字有关的配置文件
当时用注解配置时,需要将配置文件放入resources资源文件夹,使用初始化赋值,更改spring配置文件的位置

3、配置spring配置文件,设置请求和controller的映射关系(id为请求接口名)

使用注解配置时,只需要开启包扫描和开启mvc注解开发支持,不需要声明bean
注解开发支持命名空间需引入地址为: http://www.springframework.org/schema/mvc

4、编写controller控制层
控制层需要实现 Controller接口 ,复写 ModelAndView方法 ,该方法为handleRequest**默认自动执行的方法,类似servlet的service方法
创建模型对象,将需要显示的信息存入模型对象,将视图和模型对象封装
使用注解开发时:
需要使用注解 @Controller 声明为控制层
方法使用注解 @RequestMapping 声明该方法对应的接口(url)

二、Controller方法返回值
返回ModelAndView:
实现Controller接口后复写的ModelAndView方法默认返回ModelAndView
无返回值类型:
一般用于原生的servlet对象(少)或者阿贾克斯请求(多)
返回字符串:
方法返回值设置为ModelView时,默认会按照默认的视图解析器来进行解析处理
当设置返回值为视图字符串时,默认也会按照默认视图解析器来处理,会自动封装ModelAndView
1、返回字符串时,需要传入参数ModelMap
2、modelMap由容器创建,通过自动装配传入对象,在方法中赋值
3、返回值直接返回视图资源文件(使用相对路径相对于当前父路径,使用绝对路径是从应用名下开始的)
4、返回默认是一个转发操作,手动设置路径 forward/redirect:访问路径 可以不走默认的视图解析规则
5、目录WEB-INF的资源是受保护资源,必须通过服务器转发才能访问,不能直接在地址栏中输入访问接口访问
若需要重定向到某个请求,则重定向的绝对路径也是从应用名开始
三、映射路径(@RequestMapping)
使用:
1、可以在类上使用注解@RequestMapping声明命名空间(类似于什么层什么层(哪个模块)-user/index/dept)
2、使用在方法上是,可以映射请求的接口
3、使用属性 path (可传入多个接口,为动态数组)时,可以省略最前面的 /
4、使用 params属性 传参数时请求参数必须要有 username 和 password 方法参数设置与请求参数一致,springmvc会自动封装
400错误:封装request信息到方法中的时候出错,无法正确封装数据,并没有执行到该方法
_
5、使用属性method,可以指定请求的方式
Restful(一种技术规范):
1、请求地址规则规范(参数路径化)
参数路径化:将请求参数信息放入到请求路径中,而不是链接地址后面拼接或者请求体传递
拼接:/login.mvc?username=admin
请求体:/login.mvc 请求体RequestBody:username=admin(post方式)
restful的请求路径参数化:地址栏/admin/login.mvc
/update.mvc?username=admin&password=123&sex=男 -> /admin/男/123/update.mvc
接收参数时需要使用注解 @PathVariable
2、请求方式规范(请求的method规范)
get:查询(根据id查询数据)
post:新增(添加新数据)
put:修改(修改数据)
delete:删除(根据id删除数据)
四、数据绑定
将请求的表单数据绑定到执行方法的参数变量中,或者将服务器数据绑定到内置对象,传递到页面上
类型:
基本数据类型——基本数据类型+String+包装类
包装数据类型——包装实体类
数组集合类型——List、Map、Set、数组等数据类型
内置数据自动绑定:
ServletAPI(HttpServletRequest、HttpServletResponse、HttpSession)
SpringMVC(Model、ModelMap、ModelAndView)
参数封装:
@Controller
public class UserController {
/**
* 页面传值到后台服务器,方法参数自动封装:
* 方法参数名与前端提交的参数名一致
*/
@RequestMapping("login.mvc")
public String login(String username,String password){
System.out.println(username+"-"+password);
return "/index.html";
}
/**
* 页面传值到后台服务器,方法参数自动封装:
* 前端提交的参数名与方法的参数的属性名一致
* springmvc会自动根据当前方法参数对象的属性名,从request取值封装到对应属性上(需要有对应属性的实体类)
*/
@RequestMapping("login.mvc")
public String login2(User user){
System.out.println(user);
return "/index.html";
}
/**
* 响应数据处理,springmvc 封装:
* Model封装响应数据
* springmvc会自动将model的数据放入request的Attribute中
*/
@RequestMapping("login.mvc")
public String login3(User user, Model model){
System.out.println(user);
model.addAttribute("username",user.getUsername());
return "/success.jsp";
}
@RequestMapping("login.mvc")
public String login4(User user, ModelMap model){
System.out.println(user);
model.put("username",user.getUsername());
return "/success.jsp";
}
/**
* 强制绑定页面传递的参数到后台方法参数
* 当页面传值的参数名与方法参数名不一致的时候使用@RequestParam
*/
@RequestMapping("login.mvc")
public String login5(@RequestParam("username") String name,
@RequestParam("password") String pwd,ModelMap model){
System.out.println(name+"-"+pwd);
model.put("username",name);
return "/success.jsp";
}
/**
* 获得JSP 页面,JSESSIOINID这个Cookie值
* @param cookevalue
*/
@RequestMapping("/cookie.mvc")
public void getCookie(@CookieValue(value="JSESSIONID") String cookevalue){
System.out.println(cookevalue);
}
/**
* 无法自动将日期字符串转换程Date类型,需要设置@DateTimeFormat注解
**/
@RequestMapping("login.mvc")
public String login6(User user, Model model){
System.out.println(user);
model.addAttribute("username",user.getUsername());
return "/success.jsp";
}
}
POST提交方式乱码:
添加spring提供的过滤器
在web.xml配置文件添加编码过滤器
常用注解:
使用一些注解对不能自动绑定的数据进行强制绑定:
1、默认参数绑定的是表单数据,如果数据不是来自表单,那么必须要使用强制绑定
2、数据来自表单的,但是参数名不一致,也需要强制绑定
3、数据来自表单的,但是需要将数据绑定在Map对象里面,也需要强制绑定
@PathVariable 注解:绑定路径参数
@RequestParam 注解:绑定表单数据
@CookieValue 注解:获取cookie的值
@RequestHeader 注解:获取指定请求头的值
五、请求过滤
默认资源拦截:*.form :以 *.form 结尾的后缀请求都会进入springmvc管理/ :除了JSP以外拦截所有,包括html、css、js等静态资源/* :拦截所有请求
在web.xml文件中,使用 / 匹配所有除jsp以外的资源(包含css文件和js文件等静态资源),会造成页面无法应用样式
需要在springmvc-servlet.xml中配置静态资源的映射关系:

mapping:设置需要被映射的请求路径
location:设置静态资源的真实路径
/assets/:表示匹配 /assets 路径下的请求,不包括子目录
/:表示匹配 / 开头的路径,包括其所有子目录
或者使用springmvc默认标签 <mvc:default-servlet-handler />

视图解析器:
默认返回视图字符串,会通过默认的视图解析器来处理(InternalResourceViewResolver)
可以在springmvc-servlet.xml文件中更改默认的视图解析器来添加需要匹配的前缀和后缀

prefix:匹配前缀
suffix:匹配后缀
若更改了默认的视图解析器,有需要访问到其他目录资源时,需要使用转发/重定向
六、JSON支持
ajax的json请求:
1、引入jackson包——spring官方的ajax操作依赖
2、页面传值到后台,自动封装/强制绑定(RequestBody)
3、后台响应数据到页面,强制绑定RequestBody,返回值直接定义为需要返回页面的数据类型
前端请求数据(例如:用户名和密码):
页面传值到后台:非json字符串类型,自动封装(get/post的x-www.form-urlencoded)
必须保证参数名和后台方法参数名一致(也可以直接封装到对象的属性中,前提是有对应属性的实体类对象)
使用注解 @ResponseBody 自动将Java对象转换成json格式字符串

强制绑定:
1、前端使用 row或pplication/json 提交,会自动转换成是字符串格式的对象 "{key:value}" ,后台通过注解@ResquestBody ,告诉springmvc从请求体中获取数据,转化成Java对象@ResquestBody:会自动将返回值得Java对象转换成json字符串,如果需要日期自定义格式,则在实体类中添加日期格式注解
2、前端使用 row或application/json 提交数据,会自动转换成字符串格式对象,后台是Map结构时,必须通过注解 @RequestBody 进行绑定
乱码:
当返回值是字符串类型,springmvc会自动设置content-type为 text/plain;charset=iso8859-1 ,响应数据会有乱码,需要手动设置响应类型(produces:设置响应编码)
七、异常处理
springmvc提供了异常处理注解,可以解决异常处理问题,使用注解 @ExceptionHandler 时,当前类中出现的异常都会自动调用该注解所在的方法来处理
为避免代码重复使用,可以单独写一个控制层切面类,该类需要添加注解 @ControllerAdvice 
八、上传**
1、引入依赖jar包
2、配置springmvc提供的文件上传解析器,必须指定解析器的bean的名字(multipartResolver)
3、编写form表单,必须使用post提交,且提交方式(enctype)必须是 **multipart/form-data** 
4、定义控制层方法,在方法参数列表中添加文件处理对象 **MultipartFile** ,参数名必须与表单的参数名一致
// 单文件上传
@RequestMapping("upload1")
public String upload(MultipartFile file, ModelMap modelMap){
String filename = file.getOriginalFilename(); //提交的上传文件名称
File dir = new File("D:\\upload"); // 文件上传路径
if(!dir.exists()){ //文件夹不存在则创建
dir.mkdirs();
}
File file1 = new File(dir, filename);
try {
file.transferTo(file1); // 上传操作
modelMap.put("src","/upload/"+filename); // 绑定虚拟路径映射,传递到上传成功页面
} catch (IOException e) {
e.printStackTrace();
}
return "/index";
}
// 多文件上传(接收为数组,使用循环)
@RequestMapping("upload2")
public String upload(MultipartFile[] files){
System.out.println("上传多个文件");
File dir = new File("D:\\upload");
if(!dir.exists()){
dir.mkdirs();
}
for (MultipartFile file : files) {
String filename = file.getOriginalFilename();
File file1 = new File(dir, filename);
try {
file.transferTo(file1);
} catch (IOException e) {
e.printStackTrace();
}
}
return "/index";
}


