本篇大概两千多字,预计阅读十分钟左右。
主要是对网上的一些常见问题进行收集整理,自己结合平时的项目中出现的一些问题的总结。如果大家在阅读过程中有什么疑问的地方可以一起交流讨论。
SpringMVC 其实是基于 Spring 框架下的的 webmvc 模块发展而来的,底层的实现是 基于 Servlet API 的。
做到 M(Model)— V(View)— C(Controller)分层。降低各层次之间的耦合性,简化开发。
先上一张整体的流程图:
下面详细说下具体流程:
DispatchServlet
;DispatchServlet
收到请求后,调用HandlerMapping
处理器映射器查找对应负责处理请求的 Handler;HandlerMapping
将找到的具体的处理器 Handler 生成处理器对象以及处理器拦截器(如果有则生成),一起返回给 DispatchServlet
;DispatchServlet
调用HandlerAdapter
处理器适配器,请求执行具体的 Handler;HandlerAdapter
将具体 Handler 执行返回的模型和视图返回给到 DispatchServlet
;DispatchServlet
已经得到具体的 视图名称了,然后向 ViewResolver
发起请求,请求解析视图,返回已经解析好的视图对象;DispatchServlet
对视图进行渲染,将 model 与view 进行渲染;DispatchServlet
返回响应给到用户浏览器;前端控制器
DispatcherServlet
:接收请求、响应结果,相当于转发器,有了DispatcherServlet
能够减少了其它组件之间的耦合度。
处理器映射器HandlerMapping
:根据请求的URL来查找Handler
处理器适配器HandlerAdapter
:负责执行Handler
处理器 Handler:处理器,需要程序员开发
视图解析器ViewResolver
:进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图(view)
视图View:View是一个接口, 它的实现类支持不同的视图类型,如jsp,freemarker,pdf等等
@RequestMapping
:用于处理 URL 映射的的注解,既可用于类上,也可用于方法上,当作用于类上时则表示当前类中的所有响应方法都是以这个 url 作为父路径;@RequestBody
:请求体注解,能够将前端传到后端的 json 字符串中的数据(请求体中的数据)封装到对应的类型中。(注意:只能解析请求体中的数据!!所以使用 GET 请求方式是拿不到数据的!)这里参考一个写的非常nice 的文章:@RequestBody的使用@ResponseBody
:将 Java 对象转为 json 格式的数据,同样贴一篇详情文章:@ResponseBody详解Controller
返回一个页面:
单独使用 Controller
不加 @ResponseBody
使用的话就要经过视图解析流程 (ViewResolve),最后返回给到前端一页面,这种情况属于比较传统的 Spring MVC 应用,对应前后端不分离的情况;
@RestController
返回 json 或者 xml 形式的数据:
@RestController
只返回对象,对象以 json 或者 xml 格式写入到 http 响应中,属于 RESTful 风格,也是目前流行的前后端分离方式;
@Controller
+ @ResponseBody
返回 json 或者 xml 形式数据:
在 Spring 4.x 之前如果想要使用 RESTful 风格的话,是需要使用这两个注解组合进行使用的。但是在之后就可以使用上面的 @RestController
一步到位。
参考文章:SpringMVC与Struts2区别与比较总结
解决 POST 请求乱码问题:在 web.xml 中配置一个 CharacterEncodingFilter 过滤器,设置成 utf-8 ;
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
GET 请求中出现中文乱码,讲真在url 中传递中文,就不是什么明智之举,最好不要这用做!
但是事情已经发生了,总得要解决的:
详解get请求和post请求参数中文乱码的解决办法
是单例模式,之前在 Spring 篇章里面有说过控制层和Service 层以及 DAO 层一般是无状态的实例,不涉及数据的增删改等操作,只有简单的查询操作,那么就是线程安全的,所以解决方案就是:在控制器里面不要写可变的状态量,如果需要这些可变的状态量,那么可以通过 ThreadLocal
进行解决,为每个线程提供一个独立的变量副本,进行数据操作;
"forword:index.do?name=2"
“redirect:http://www.baidu.com”
关于请求转发和重定向底层原理可以看我以前写的一篇博客:Servlet重定向和请求转发的区别
定义一个实现 HandlerInterceptor
接口的拦截器,然后在 web.xml 文件中配置拦截器即可
详细细节
通过 Jackson 框架可以将 Java 中的对象直接转换为 json 对象:
@ResponseBody
注解;参考文章SpringMVC与Ajax交互的几种形式
可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。
参考文章:springmvc异常处理
直接在方法的形参中声明 request,SpringMVC 就自动把 request 对象传入。
直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。
直接在方法形参中声明这个对象,SpringMVC 就自动会把属性赋值到这个对象里面。
返回值可以有很多类型,有String,ModelAndView。ModelAndView类把视图和数据都合并的一起的,但一般用String比较好。
下面是以小样例代码,具体可以参考这篇文章:springMVC向页面传值
@RequestMapping("/bind")
public String bindData(String str, HttpServletRequest request, ModelMap map, ModelAndView modelAndView, HttpSession session) {
logger.info("...bind 方法");
request.setAttribute("str", str);
map.put("str", str);
modelAndView.addObject("str", str);
session.setAttribute("str", str);
return "success";
}
可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。
今天收获一句话:你若对得起时间,时间便对得起你!分享给大家,一起共勉!
☀️ 学而不思则罔,思而不学则殆
我是 江璇 ,一个不断努力的新人程序猿
关注我,一起成长!一起进步!