SpringMVC知识总结

1.运行流程

运行流程
1)客户端发送请求
2)来到tomcat服务器
3)springmvc的前端控制器收到所有请求
4)来看请求地址和@RequestMapping标注的哪个匹配,来找到到底使用哪个类的哪个方法
5)前端控制器找到目标处理器和目标方法,直接利用反射执行目标方法
6)方法执行完成以后会有一个返回值,springMvc认为这个返回值就是要去找的页面地址
7)拿到方法返回值以后,用视图解析器进行拼接得到完整的页面地址
8)拿到页面地址,前端控制器转发到页面

@RequestMapping

这个就是告诉springMVC,这个方法用来处理什么请求,
这个/是可以省略大的,即使省略了也是默认从当前项目下开始,习惯性加上

*/和/的区别
/拦截所有请求,包括拦截jsp页面
/*拦截所有请求,不拦截jsp页面

2.REST

http协议四个表示操作方式的动词:GET、POST。PUT、DELETE;分别表示获取,新建,更新,删除资源
(操作地址URL相同,请求方式不同)
在这里插入图片描述
但是页面只能发送GET和POST两种方式;
如何使用REST风格
ii)需要在web.xml写上一个过滤器
(把普通的请求转换为规定形式的请求,配置这个filter)

<!--把普通的请求转换为规定形式的请求,配置这个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>

分析:
在这里插入图片描述

ii)jsp代码:

<form action="test/book/1" method="post">
    <input type="submit" value="添加">
  </form>

  <form action="test/book/1" method="post">
    <input name="_method" value="delete"/>
    <input type="submit" value="删除">
  </form>

  <form action="test/book/1" method="post">
    <input name="_method" value="put"/>
    <input type="submit" value="更新">
  </form>
  <form action="test/book/1" method="GET">
    <input type="submit" value="查询">
  </form>

ii)java代码:

 @RequestMapping(value = "/book/{id}",method = RequestMethod.POST)
    public  String insert(@PathVariable("id") String id){
        System.out.println("增加的请求收到了,,");
        return "success";
    }

    @RequestMapping(value = "/book/{id}",method = RequestMethod.DELETE)
    public  String delete(@PathVariable("id") String id){
        System.out.println("删除的请求收到了,,");
        return "success";
    }

    @RequestMapping(value = "/book/{id}",method = RequestMethod.PUT)
    public  String update(@PathVariable("id") String id){
        System.out.println("更新的请求收到了,,");
        return "success";
    }

    @RequestMapping(value = "/book/{id}",method = RequestMethod.GET)
    public  String get(@PathVariable("id") String id){
        System.out.println("查询的请求收到了,,");
        return "success";
    }

高版本tomcat使用put,delete请求方式会报错
SPs only permit GET, POST or HEAD. Jasper also permits OPTIONS;
直接添加一个属性即可isErrorPage=“true”,
如果有错用excetion接收即可

在这里插入图片描述
springMVC的执行流程:
在这里插入图片描述
参考博客:https://blog.csdn.net/weixin_48922154/article/details/113867510

3.源码分析:

在这里插入图片描述

1)前端控制器DispathcherServlet 最主要的方法doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
					//检查是否文件上传请求
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
					//根据当前请求找到哪个类来处理
                    mappedHandler = this.getHandler(processedRequest);
 
					//如果没有找到哪个处理器能处理这个请求就404或者抛出异常
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
					//拿到能执行这个类的所有方法的适配器:(反射工具)
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2)getHandler()细节分析:怎么根据当前请求找到哪个类来处理
handlerMappings:处理器映射,他里面会保存了每一个处理器能处理哪些请求的映射

handlerMapping:ioc容器启动创建Controller对象的时候扫描每一个处理器都能处理什么请求,保存在handlerMapping

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        Iterator var2 = this.handlerMappings.iterator();

        while(var2.hasNext()) {
            HandlerMapping mapping = (HandlerMapping)var2.next();
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }

    return null;
}

3)getHandlerAdapter()

如何找到目标处理器的适配器
遍历所有的适配器,找到能解析的适配器

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        Iterator var2 = this.handlerAdapters.iterator();

        while(var2.hasNext()) {
            HandlerAdapter adapter = (HandlerAdapter)var2.next();
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }

    throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值