一、简介
SpringMVC是基于servlet的web层框架。不同于Struts2基于类级别的拦截器,SpringMVC是基于方法进行拦截的。还有就是SpringMVC是单实例的,相比struts2多实例的要更加减少服务器的负担。
二、入门
1.动态web创建项目导入jar包
2.编写测试类及jsp
(1)测试类
package com.xiaohuizi.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloController {
@RequestMapping("/hello")
public ModelAndView hello() {
System.out.println("hello springmvc");
//创建modelandview对象
ModelAndView andView=new ModelAndView();
//设置模型数据
andView.addObject("msg","hello zx");
//设置视图name
andView.setViewName("/WEB-INF/jsp/hello.jsp");
return andView;
}
}
(2)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>hello</title>
</head>
<body>
${msg}
</body>
</html>
3.配置web.xml文件
<?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>SpringMVC01</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 配置前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载springmvc核心配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<!-- 配置拦截路径 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4.配置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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置@Controller处理器,包扫描器 -->
<context:component-scan base-package="com.xiaohuizi.springmvc.controller" />
</beans>
5.SpringMVC执行过程
首先经过拦截器,通过拦截器加载核心配置文件springmvc.xml,之后通过核心配置文件找到所要扫描的包,更具url找到相应的动作,然后执行相应的动作,最终结果返回给jsp页面。
6.小结
SpringMvc的核心就是在web.xml中配置的拦截器,以及springmvc.xml。
三、SpringMVC默认组件加载
1.处理器映射器与处理器适配器
(1)处理器映射器
在springmvc.xml中配置
<!-- 配置处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
(2)处理器适配器
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
(3)小结
映射器与处理器必须配合使用,他们是springmvc处理其组件所必须的,比如:通过注解来找到和执行方法。
2.注解驱动
有了注解驱动就可以不用配置上面的映射器和适配器了。
<!-- 注解驱动配置,代替映射器与适配器的单独配置,同时支持json响应(推荐使用) -->
<mvc:annotation-driven />
3.视图解析器
用来管理视图的,即以什么方式访问页面的配置
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图响应的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置视图响应的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
此时动作中只需要编写jsp的名就好了。
注意:不配置这些的话springmvc也会按照默认的方式来处理,就如开始时不配置也可以正常运行一样。
四、SpringMVC架构
springmvc有三大核心组件映射器找到相应的方法,适配器创建实例执行方法,视图解析器返回处理结果。
五、参数绑定
就是如何获取页面的数据返回给后台
1.默认的方式
通过request和response来获取和传递。
@RequestMapping("itemEdit")
public ModelAndView itemEdit(HttpServletRequest request,HttpServletResponse response,HttpSession session){
ModelAndView mav = new ModelAndView();
//request获取参数
String id = request.getParameter("id");
System.out.println("id为:" + id);
//其它对象输出
System.out.println("response对象:" + response);
System.out.println("session对象:" + session);
//查询商品信息
Item item = itemServices.getItemById(new Integer(id));
//设置商品数据返回页面
mav.addObject("item", item);
//设置视图名称
mav.setViewName("itemEdit");
return mav;
}
(1)除了modelandView还可以使用Model向页面传值
他俩本质都是以request对象向页面传值
(2)ModelMap也可以向页面传值
2.绑定简单类型
// @RequestParam用法:页面入参名字与方法名参数名不一致时使用{
// value:传入的参数名,required:是否必填,defaultValue:默认值
// }
@RequestMapping("itemEdit")
`public ModelAndView itemEdit(@RequestParam(value="id",required=true,defaultValue="1")Integer ids)`{
ModelAndView mav = new ModelAndView();
//查询商品信息
Item item = itemServices.getItemById(ids);
//设置商品数据返回页面
mav.addObject("item", item);
//设置视图名称
mav.setViewName("itemEdit");
return mav;
}
页面传回来的参数的名称如果与方法中的不一致时可以用@RequsetParam注解,其中的value值就是页面里定义的那个参数名。
如果参数一样,可以不用,比如
public ModelAndView itemEdit(Integer id)
3.绑定pojo对象
表单提交的name属性必需与pojo的属性名称一致。
@RequestMapping("updateItem")
public String updateItem(Item item,Model model){
//更新商品
itemServices.update(item);
//返回商品模型
model.addAttribute("item", item);
//返回担任提示
model.addAttribute("msg", "修改商品成功");
//返回修改商品页面
return "itemEdit";
}
4.包装的pojo
通过点(.)传递属性。user.name
private String name;
private User user;
5.数组参数的绑定
在相应的方法里设置接收的数组参数要和页面的参数名一致,就可以把值传回来。
public String queryItem(QueryVo vo, Integer[] ids)
6.List参数绑定
利用实体中的set设置值get获取值,在方法中利用包装实体获得参数值,页面需要用到foreach的valuestatus,来完成下标的获取,status.index
7.@RequestMapping用法
1.放在类名上为请求的url设置分类
原先:http:///move.action
后来:http:///people/move.action
2.限定请求方法
3.路径映射可以是数组
8.Controller方法返回值
1.ModelAndView
返回ModelAndView中设置的值,跳转到相应的页面和返回相应的属性值
2.void返回值
通过request和response向页面传值,或跳转页面
3.返回字符串
就是返回逻辑视图,也就是页面
return “item”转发
return “forward: item”;转发
return “redirect:item”重定向
9.乱码的问题
乱码问题{
提交问题{
post乱码:过滤器解决;
<!-- 解决post乱码问题 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置编码参是UTF8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
get乱码:tomcat配置 URIEncoding="utf-8"
}
响应乱码{
response乱码:获取getWriter之前,response.setCharacterEncoding("utf-8");
}
}
10.异常处理
1.编写全局异常类
public class CustomerException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object hanlder,
Exception e) {
//记录日志
e.printStackTrace();
//错误消息
String msg = "很抱歉,系统发生异常了,请联系管理员";
//响应用户错误提示
ModelAndView mav = new ModelAndView();
//返回错误消息
mav.addObject("msg", msg);
//响应错误提示页面
mav.setViewName("msg");
return mav;
}
}
2.配置springmvc.xml
<bean class="全局异常处理类的位置"/>
3.更加友好的异常处理(具体到具体错误)
在全局异常处理类的基础上,自定义异常类
(1)自定义异常类
public class MyException extends Exception {
//错误消息
private String msg;
public MyException() {
super();
}
public MyException(String msg) {
super();
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
(2)修改全局异常类
public class CustomerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object hanlder,
Exception ex) {
String result = "系统发生异常了,请联系管理员!";
//自定义异常处理
if(ex instanceof MyException){
result = ((MyException)ex).getMsg();
}
ModelAndView mav = new ModelAndView();
mav.addObject("msg", result);
mav.setViewName("msg");
return mav;
}
}
(3)在测试类中添加相应的new MyException(“msg”)
如果出现异常则会抛出。
11.json交互
引入jar包
通过在方法上配置@ResponseBody或者在接收参数上配置@RequestBody,就可以向页面发送json数据,或者从页面接收json数据
@RequestMapping("getItem")
//@ResponseBody把pojo转成json串响应用户
@ResponseBody
//@RequestBody用于接收用户传入json串转成pojo
public Item getItem(@RequestBody Item item2) {
System.out.println("接收到的json商品数据为:" + item2);
Item item = itemServices.getItemById(3);
return item;
}
12.Restful
使得连接更加简介
//RESTful风格url上的参数通过{}点位符绑定
//点位符参数名与方法参数名不一致时,通过@PathVariable绑定
@RequestMapping("/item/{id}")
public String testRest(@PathVariable("id") Integer ids, Model model) {
Item item = itemServices.getItemById(ids);
model.addAttribute("item", item);
return "itemEdit";
}
13.拦截器
(1)拦截器类
public class MyInterceptor1 implements HandlerInterceptor {
//在Controller方法执行后被执行
//处理异常、记录日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("MyInterceptor1.afterCompletion.....");
}
//在Controller方法执行后,返回ModelAndView之前被执行
//设置或者清理页面共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("MyInterceptor1.postHandle.....");
}
//在Controller方法执行前被执行
//登录拦截、权限认证等等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("MyInterceptor1.preHandle.....");
//返回true放行,false拦截
return true;
}
}
(2)在springmvc.xml中配置拦截器
<!-- 拦截器定义 -->
<mvc:interceptors>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- path配置</**>拦截所有请求,包括二级以上目录,</*>拦截所有请求,不包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.itheima.springmvc.interceptor.MyInterceptor1" />
</mvc:interceptor>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- path配置</**>拦截所有请求,包括二级以上目录,</*>拦截所有请求,不包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.itheima.springmvc.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
(3)拦截器调用顺序