一、SpringMVC介绍
SpringMVC:
- 是基于Spring的一个框架,实际上就是Spring的一个模块,是专门用来做web开发的,可以理解为servlet的升级。
- SpringMVC就是一个Spring,SpringMVC也是一个容器,能够创建对象,SpringMVC容器中放的是控制器对象。
- 开发人员要做的就是使用@Controller创建控制器对象,把对象放到SpringMVC容器中,把创建的对象作为控制器使用,这个控制器对象可以接收用户的请求,显示处理结果。
- 使用@Controller注解创建的是一个普通类的对象,不是一个servlet对象。SpringMVC只是赋予了这个控制器对象一些额外的功能。
- DispatherServlet:SpringMVC中的一个servlet对象。负责接收用户的所有请求,用户把请求交给了DispatherServlet,DispatherServlet再把请求转发给我们的控制器对象,最后是控制器对象处理请求。
二、SpringMVC的简单实现
1. 在Web.xml中注册SpringMVC框架的核心对象DispatherServlet
(1)DispatherServlet叫做中央调度器,是一个Servlet,他的父类继承了HttpServlet。
(2)DispatherServlet也叫作前端控制器(front controller)
(3)DispatherServlet负责接收用户提交的请求,然后调用其他的控制器对象,并把请求的处理结果显示给用户。
<!--
声明注册SpringMVC的核心对象DispatcherServlet
需要在tomcat服务器启动后,自动创建DispatcherServlet对象的实例。
因为DispatcherServlet在创建过程中,会同时创建SpringMVC容器对象,
读取SpringMVC的配置文件,吧这个配置文件中的对象都创建好,当用户发起请求的时候就可以直接用对象了。
-->
<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>
<!--
在tomcat启动后,创建servelt对象
load-on-startup:表示tomcat启动后创建对象的顺序。值是一个整数,数值越小,tomcat创建对象的时间越早。
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!--
使用SpringMVC的时候,url-pattern可以有两种方式设置
1.使用扩展名方式,语法:*.xxx,"xxx"是自定义的扩展名。常用方式:*.do / *.action / *.mvc
2.使用斜杠"/"
-->
<url-pattern>*.mvc</url-pattern>
</servlet-mapping>
2. 创建控制器类
<a href="MyController/controller.mvc">发起controller请求</a>
(1)在类的上面加上@Controller注解,创建对象,并放入到SpringMVC容器中。
(2)在类的方法上面加入@RequestMapping注解。
@Controller
@RequestMapping("/MyController")
public class MyController {
/*
处理用户提交的请求,springmvc中使用方法来处理。这个方法需要自定义,可以多种返回值,多种参数,方法名称自定义。
准备使用doController方法处理controller.mvc请求。
@RequestMapping:请求映射,作用是把一个请求地址和一个方法绑定在一起。
属性:1. value是一个String,表示请求的uri地址。(controller.mvc),value的值是唯一的。在使用时推荐地址以“/”开头
位置:1. 在方法的上面。(常用)
2. 在类的上面。
说明:使用RequestMapping修饰的方法叫做控制器方法。这个方法可以处理请求,类似于Servlet中的doGet和doPost方法。
返回值:ModelAndView 表示本次请求的处理结果。
model:数据,请求处理完成后,要显示给用户的数据。
view:视图,如JSP。
*/
@RequestMapping(value = "/controller.mvc")
public ModelAndView doController(){
//处理controller.mvc请求。
ModelAndView modelAndView = new ModelAndView();
//添加数据,框架在请求的最后把数据放到了request作用域里。
//类似于request.setAttributes("msg","Holle SpringMVC");
modelAndView.addObject("msg","Holle SpringMVC");
modelAndView.addObject("function","执行了doController方法");
//指定视图,框架对视图执行forward操作(请求转发)
//类似于request.getRequestDispather("/show.jsp").forward(...)
modelAndView.setViewName("show");
return modelAndView;
}
}
3. 创建SpringMVC的配置文件
(1)声明组件扫描器,指定@Controller所在的包名。
(2)声明视图解析器,帮助处理视图。
<!--声明组件扫描器-->
<context:component-scan base-package="com.roxic.controller"></context:component-scan>
<!--声明视图解析器,帮助开发人员设置视图文件的路径-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀:视图文件的路径-->
<property name="prefix" value="/WEB-INF/view/"></property>
<!--后缀:视图文件的扩展名-->
<property name="suffix" value=".jsp"></property>
</bean>
4. SpringMVC请求的处理流程
(1)发起controller.mvc
(2)tomcat根据web.xml中的url-pattern找到 *.mvc的请求,转发给DispatcherServlet。
(3)DispatcherServlet根据springmvc.xml的配置文件找到了被注解的类。
(4)DispatcherServlet把controller.mvc在转发给MyController类中的doController()方法。
(5)框架执行doController()方法,把得到的ModelAndView进行处理,转发给show.jsp
5. SpringMVC执行过程源代码分析
(1)tomcat服务器启动,创建容器的过程
通过load-on-start标签指定的1,创建DisaptcherServlet对象,在被创建时,会执行init()方法。
//创建容器,读取配置文件
WebApplicationContext wac = new ClassPathXmlApplicationContext("SpringMVC.xml");
//把容器对象放入到ServletContext中
getServletContext().setAttribute(key,wac);
创建容器后,容器就可以创建@Controller注解所在的类的对象,创建了MyController对象,这个对象以Map的方式放到了容器里,类似于Map.put("myController",MyController对象);
(2)请求的过程
- 执行DispatcherServlet的service()→doService()→doDispatch()
protected void service(HttpServletRequest request, HttpServletResponse response)
protected void doService(HttpServletRequest request, HttpServletResponse response)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response){
//调用MyController的doController()方法
}
- doDispatch是中央调度器的核心方法,所有的请求都在这里面完成。
三、控制器接收请求中的参数
1. 通过在控制器方法的形参中放三个对象,请求对象,应答对象,会话对象,框架会自动给这三个对象赋值
@RequestMapping(value = "/controller.mvc")
public ModelAndView doController(HttpServletRequest request, HttpServletResponse response, HttpSession session){
ModelAndView modelAndView = new ModelAndView();;
modelAndView.addObject("msg","Holle SpringMVC" + request.getParameter("name"));
modelAndView.addObject("function","执行了doController方法");
modelAndView.setViewName("show");
return modelAndView;
}
2. 逐个接受请求参数
<form action="MyController/Sumbit.mvc" method="post">
姓名:<input type="text" name="name"><br>
性别:<input type="radio" name="gender" value="true" checked="true">男<input type="radio" name="gender" value="false">女<br>
<input type="submit" value="提交">
</form>
- 要求:
控制器方法的形参名必须和请求中的参数名相同。同名的请求参数会赋给同名的形参。 - 框架的操作过程:
①使用request对象接收请求参数
String strName = rquest.getParameter(“name”);
String strGender = rquest.getParameter(“gender”);
②框架通过DispatcherServlet调用MyController的doSumbit()方法,调用时,根据名称,把处理后的请求参数赋给形参,doSumbit(strName, Boolean.valueOf(strGender))
@RequestMapping(value = "/Sumbit.mvc")
public ModelAndView doSumbit(String name, boolean gender){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg",name + (gender?"男":"女"));
modelAndView.setViewName("sumbit");
return modelAndView;
}
- 解决POST请求乱码过滤器
在web.xml中注册过滤器
<!--注册过滤器,解决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>
<!--强制请求对象使用encoding的值-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--强制应答对象使用encoding的值-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--/*:表示所有请求必须先通过过滤器-->
<url-pattern>/*</url-pattern>
</filter-mapping>
- @RequestParam
解决请求中参数名和形参名不一样的问题
(1)属性:① value,请求中的参数名。②required,是一个布尔类型,默认是true,表示请求中必须包含此参数。
(2)位置:控制器方法的形参定义的前面。
public ModelAndView doSumbit(@RequestParam(value="xxx")String name, @RequestParam(value="xxx")boolean gender)
3. 对象接收请求参数
(1)创建一个普通类,保存请求参数值。类中的属性名要和请求参数名相同。
(2)在控制器方法的形参中加上(1)中创建的普通类,框架会为形参创建java对象,给属性赋值。
(3)这种方式,在实际应用时用的比较多。形参中可以加入多个普通类对象,框架会依次创建它们的实例并给属性赋值。
四、控制器方法的返回值
1. 返回ModelAndView
- 当控制器方法处理完成后,需要跳转到其他资源,而且又需要在跳转的资源之间传递数据,此时返回ModelAndView比较恰当。否则ModelAndView总是有一部分多余,要么Model多余,要么View多余。
2. 返回String
- 当返回的String表示视图,可以是逻辑名称,也可以是完整视图路径。
@RequestMapping(value = "/Sumbit.mvc")
public String doSumbit(String name, boolean gender){
//sumbit是逻辑视图的名称(因为已经配置了视图解析器)
return "sumbit";
}
- 当返回的String表示数据,和以上的区分的关键在于控制器方法上面有没有@ResponseBody注解。(返回数据默认以ISO-8859-1作为字符集,需要给RequestMapping增加一个produces属性,指定新的contenType)
@RequestMapping(value = "/Sumbit.mvc",produces="text/plain;charset=utf-8")
@ResponseBody
public String doSumbit(String name, boolean gender){
//sumbit是逻辑视图的名称(因为已经配置了视图解析器)
return "我是一个数据";
}
3. 返回void
- 不能表示数据也不能表示视图。在处理ajax的时候可以用void返回值,通过HttpServletResponse输出数据,响应ajax请求。ajax请求服务器端返回只有数据,没有视图。
4. 返回对象Object
- Object返回,不是作为逻辑视图出现,而是作为直接在页面上显示的数据出现。用@ResponseBody注解,转换成JSON对象,放入到响应体中。
- 现在实现AJAX,主要用JSON的数据格式。实现步骤:
(1)加入处理JSON的工具依赖,默认是用的Jackson。
(2)在SpringMVC配置文件中加入<mvc:annotation-driven>注解驱动。(作用是将java对象转换成json格式的数据)
(3)在控制器方法上加入@ResponseBody注解。(作用是将json数据输出)
(4)SpringMVC框架返回一个Object,并转换成一个json,响应ajax请求的原理:
①<mvc:annotation-driven>它实现的功能是将java对象转换到json,xml,text,二进制等数据格式的转换。
涉及到了HttpMessageConverter接口(消息转换器),这个接口的功能定义了java对象转换成json,xml,text,二进制等数据格式的方法。
这个接口有很多的实现类,这些实现类具体完成了这些数据格式的转换。
源码:
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
- 第一个方法的作用是检查控制器方法的返回值,能不能转成var2表示的数据格式。(MediaType就表示json,xml,text等各种数据格式)
- 第二个方法的作用是把控制器方法返回值对象,调用Jackson中的ObjectMapper转换为json数据格式。
②@ResponseBody注解,放在控制器方法上面,通过HttpServletResponse输出数据,响应ajax请求。
五、SpringMVC处理静态资源
- 在默认情况下,所有的静态资源都会交给tomcat中叫default的一个Servlet,它的url-pattern是
"/"。 - 当在web.xml中,将SpringMVC的DispatherServlet的url-pattern改成
"/"后,我们的静态资源都会404,因为SpringMVC默认是无法请求静态资源的,所以需要添加新内容。
1. 第一种处理静态资源的方式
需要在SpringMVC的配置文件中加入<mvc:default-servlet-handler />
原理:加入这个标签后,框架会创建控制器对象DefaultServletHttpRequestHandler,DefaultServletHttpRequestHandler这个对象可以吧接收到的请求转发给tomcat里叫default的Servlet。
- 注意:加入了
<mvc:default-servlet-handler />后,一定也要加入注解驱动<mvc:annotation-driven>,不然会起冲突,所有的请求都会转发给tomcat的default。
2. 第二种处理静态资源的方式(项目开发主要使用)
在SpringMVC的配置文件中加入:
<mvc:resources mapping="/img/**" location="/img/" />
加入mvc:resources后,框架会创建ResourcesHttpRequestHandler这个控制器对象,让这个对象处理静态资源的访问,不依赖tomcat。(主要用这种方式)
mapping:访问静态资源的uri地址,用通配符 **
location:静态资源在你项目中的路径。
- 注意:加入了
<mvc:resources mapping="/img/**" location="/img/" />后,一定也要加入注解驱动<mvc:annotation-driven>,不然会起冲突。
六、SSM整合开发
SSM:SpringMVC+Spring+Mybatis
SpringMVC:视图层,界面层。负责接收请求,显示处理结果。
Spring:业务层,管理service,dao,工具类的对象。
Mybatis:持久层,访问数据库。
用户发起请求→SpringMVC接收→Spring中的Service对象→Mybatis处理数据
SSM整合中有很多容器
- 第一个容器SpringMVC容器,管理Controller控制器对象。
- 第二个容器Spring容器,管理Service,Dao,工具类对象。
开发人员要做的就是把合适的对象交给合适的容器创建,管理。 - SpringMVC容器和Spring容器是有关联的,SpringMVC容器是Spring容器的子容器。(类似于java中的继承)在子容器中的Controller对象可以访问父容器中的Service对象。
七、SSM整合实现步骤
-
加入SpringMVC,Spring,Mybatis,Jackson,mysql,druid连接池,jsp,servlet依赖。
-
配置web.xml
① 注册DispatcherServlet,目的是创建SpringMVC容器对象,才能创建Controller对象,并且可以作为Servlet,接受用户的请求。
② 注册Spring的监听器(ContextLoaderListener),目的是创建Spring容器对象,才能创建Service,Dao等对象。
③ 注册字符集过滤器,解决Post乱码问题。 -
创建Controller包,Service包,Dao包,实体包
-
创建SpringMVC,Spring,Mybatis的配置文件
① SpringMVC配置文件
② Spring配置文件
③ Mybatis配置文件
④ 数据库配置文件 -
写代码,dao接口,mapper文件,service接口和实现类,controller类,实体类。
八、异常处理(AOP处理思想)
- SpringMVC框架采用的是统一,全局的异常处理。把Controller中所有异常处理都集中到第一个地方,采用的是AOP的思想,把业务逻辑和异常处理代码分开,解耦合。
- SpringMVC框架处理异常的常用方式:使用@ExpectionHandler和@ControllerAdvice注解处理异常。
1. 实现步骤
(1)创建一个普通类,作为全局异常处理类
①在类的上方加上@ControllerAdvice
②在类中定义的方法上面加入@ExpectionHandler
(2)配置SpringMVC配置文件
①添加组件扫描器,扫描控制器类的@Controller注解。
②添加组件扫描器,扫描@ControllerAdvice所在包名。
③声明注解驱动。
九、拦截器
- 拦截器是SpringMVC的一种,需要实现HandlerInterceptor接口。
- 拦截器和过滤器类似,但功能方向侧重点不同。过滤器是用来过滤请求参数,设置编码字符集等工作。拦截器是拦截用户的请求,做请求判断处理的。
- 拦截器是全局的,可以对多个Controller拦截,一个项目中可以有多个拦截器,它们一起拦截用户的请求,常用在用户登录处理,权限检查,记录日志。
- 拦截器的实现步骤:
- 定义类实现HandlerInterceptor接口
- 在SpringMVC配置文件中,声明拦截器。
<!--声明拦截器:可以有零个或多个-->
<mvc:interceptors>
<!--声明第一个拦截器-->
<mvc:interceptor>
<!--指定拦截的uri地址,path就是uri地址,可以用通配符 **-->
<mvc:mapping path="/**" />
<!--声明拦截器对象-->
<bean class="" />
</mvc:interceptor>
</mvc:interceptors>
- 拦截器的执行时间:
- 在请求处理之前,也就是控制器方法执行之前就会被拦截。
- 在控制器方法执行之后也会执行拦截器。
- 在请求处理完成后也会执行拦截器。
- HandlerInterceptor接口中的三个方法
①preHandle()
(1)参数:Object handler:被拦截的控制器对象
(2)返回值boolean:
true:通过了拦截器的验证,可以执行控制器方法。
false:请求没有通过拦截器验证,请求到拦截器就截止了,没有被处理。
(3)特点:
方法在控制器方法之前先执行。用户的请求首先到达此方法,在这个方法中,我们可以获取请求的信息,验证请求是否符合要求。
②postHandle()
(1)参数:Object handler被拦截的处理器对象。
ModelAndView mv控制器方法的返回值。
(2)特点:在控制器方法之后执行的,可以获得控制器方法的返回值ModelAndView,可以修改ModelAndView 中的数据和视图,可以影响到最后的执行结果,可以做二次修正。
③afterCompletion()
(1)参数:Object handler被拦截的处理器对象。
Exception ex程序中发生的异常
(2)特点:在请求处理完成后执行的。框架中规定当视图处理完成后(执行了forward),就是请求处理完成。一般拿来做资源回收,程序请求过程中创建了一些对象,在这个时机可以删除。
- 拦截器和过滤器的区别:
(1)过滤器是servlet中的对象,拦截器是框架中的对象。
(2)过滤器是实现Filter接口的对象,拦截器是实现HandlerInterceptor接口的对象。
(3)过滤器是用来设置rquest,response的参数,是侧重对数据的过滤。拦截器是用来验证请求的,能截断请求。
(4)过滤器在拦截器之前先执行。
(5)过滤器是tomcat服务器创建的对象,拦截器是SpringMVC容器中创建的对象。
(6)过滤器只有一个执行时间点,拦截器有三个执行时间点。
(7)过滤器可以处理jsp,js,html等等。拦截器是侧重拦截控制器对象,如果请求不能被中央调度器接受,这个请求也不会遇到拦截器。
本文深入解析SpringMVC框架,涵盖其工作原理、配置步骤、异常处理及拦截器使用,同时详述SSM(SpringMVC+Spring+Mybatis)整合开发流程,适合Web开发人员学习。

被折叠的 条评论
为什么被折叠?



