出处: https://blog.csdn.net/sinat_33921105/article/details/81951156

在web开发中我们经常会遇到/和/*的问题,有的时候稍不注意就容易忘了两者的区别,从而导致一些小错误,所以是时候彻底弄懂他们两个的区别了!

小白:让我先想想在实际的开发中哪些地方会遇到这个问题,嗯。。。哦,知道了。在SpringMVC的开发中用到这块,也就是那个DispatcherServlet,对,就是它

<!--前端控制器-->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

<servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

这是在SpringMVC中非常重要的一个前端控制器,当有请求过来,会经由此servlet分配控制器,也就是说这个前端控制器会对我们的请求进行拦截,而如何拦截,以及拦截什么样的请求就在这个中配置

<servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

这里说的/和/*也就是在这个url-pattern中配置。

不过,我记得我一般就是像上面的代码一样,直接写成/* 了,让我突然去说/和/* 的区别,还真一时间有点懵呢!

庆哥:可以啊,看来你对SpringMVC掌握的不错啊,说到这两个问题,你立马就想到了SpringMVC中的前端控制器,确实,一般对于这个问题,我们最常使用的也就是在这个前端控制器了,因为使用SprinfMVC比较多,所以自然也就会遇到这个问题,不过,也许有大多人和你一样,在平常的开发中就知道这样使用,但是如果突然问他/和/*有啥区别,就会很容易大脑一片空白!

小白: 我记得这个url-pattern是讲的关于匹配规则的,就是具体的请求到底会匹配到哪一个servlet去处理就看这个url-pattern的配置,那咱们今天是要说匹配规则这块吗?

庆哥: 你说的很对,这个url-pattern,是关乎匹配规则的,但是今天并不是要讲匹配规则,而就是单纯的说一下/和/*的区别。

小白: 那我的记忆中这两个好像都是可以代表所有的意思吧,就是所有的请求都会被这个servlet处理!

庆哥: 这就是今天我们要讨论的问题了,其实两者是有区别的,只有一个才是真正意义上的所有!

庆哥透漏:其实上面谈话中涉及的一个知识点是有错误的,你发现了吗?继续看下去,你就知道了!

小白: 那么,到底哪一个才是代表真正意义上的拦截所有请求呢?
/ *是拦截所有请求吗?

庆哥: 接下来我们就实际操作一下看看,首先搭建SpringMVC环境,导入依赖

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.0</version>
    </dependency>

搭建SpringMVC的开发环境,我们只需要导入以上jar包,由于maven会自动导入相关依赖jar包,所以当我们引入spring-webmvc的依赖时,maven就会帮我们导入其他相关的jar包。

然后再来写SpringMVC的核心也就是前端控制器

<!--配置前端控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

注意我们这里的url-pattern可是/*啊,配置好前端控制器之后就需要再来一个SpringMVC的配置文件,这个我们在配置前端控制器的时候加上了初始化参数指定SpringMVC的配置文件,也就是这些

<init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

然后我们在我们的类路径下新建一个springmvc.xml文件即可!

小白: 对了,庆哥,这里SpringMVC的配置文件是不是还有一种以《servlet-name》-servlet.xml的方式,放在WEB-INF目录下

庆哥: 对的,如果你不指定SpringMVC的配置文件,就会默认去加载WEB-INF目录下的《servlet-name》-servlet.xml,这是一种默认的方式

小白: 嗯嗯,知道了,那么接下来是不是就该编写控制了,我知道,控制器可以这样写

public class Hello implements Controller {

@Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

ModelAndView mv1 = new ModelAndView();
        mv1.setViewName("/WEB-INF/views/hello.jsp");
        return mv1;
    }
}

庆哥: 对的,我们这里是为了说明/和/*的问题,所以就不使用注解以及视图解析器了,就是怎么简单怎么来,就按照你写的这个控制器来,接下来需要做的就是,将具体的请求和控制器关联起来,在SpringMVC的配置文件中写上这么一句

<bean id="/hello" class="com.ithuanqging.test.controller.Hello"/>

也就是说,当你输入http://localhost:8080/hello 的时候,这个请求会被DispatcherServlet拦截然后交由Hello这个控制器处理,然后我们访问一下试试

这里写图片描述

首先看到的就是这个

小白: 这是怎么回事啊,我记得一般都是会显示一个默认的页面,好像就是index.jsp吧,这里怎么404,是不是哪里出错了

庆哥: 不着急,我们输入http://localhost:8080/hello 看看

这里写图片描述

小白: 不对吧,怎么都是404啊,是不是程序出错了啊,可是我看程序也没有错啊

庆哥: 这里我们需要知道这么一点就是当你输入http://localhost:8080 的时候是不是就相当于输入http://localhost:8080/index.jsp

小白: 是的,这有啥关系

庆哥: 那么当你输入http://localhost:8080/hello的时候实际的请求路径是什么呢?

小白: 这个嘛,让我看看,我们的控制器是这样写的

public class Hello implements Controller {

@Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

ModelAndView mv1 = new ModelAndView();
        mv1.setViewName("/WEB-INF/views/hello.jsp");
        return mv1;
    }
}

那么我们输入http://localhost:8080/hello的话,这个请求被DispatcherServlet拦截交给这个控制器处理,这个控制器返回给我们一个页面,那么最终的请求应该就是http://localhost:8080/WEB-INF/views/hello.jsp

庆哥: 分析的非常对,那么这个时候你有没有发现http://localhost:8080/index.jsp 和http://localhost:8080/WEB-INF/views/hello.jsp是不是都是一个请求,而且请求的都是一个jsp页面,但是这个页面却没有找到,那是什么原因呢?

小白: 哦哦,我知道了,这两个请求jsp页面的请求也被DispatcherServlet给拦截了,所以导致404!

庆哥: 正解!

小白: 原来是这样啊,那这个又能说明什么呢?
/会拦截所有请求吗?

庆哥: 别着急,我们改成/来看看,也就是这样

<!--配置前端控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
然后再次访问发现

这里写图片描述

这里写图片描述

这下全部访问成功,也就是得到jsp页面了,那么,你能得到什么结论呢?

小白: 这么一对比,我倒是明白了,/不拦截jsp的页面请求,而/*的话会拦截,这么说这个/就不可能是真正意义上的拦截所有请求了!

庆哥: 对的,这么一个例子可以得出,/并不会拦截所有请求,对于JSP的页面请求就不会拦截,而/*则会拦截,那么由此,结论就出来了

/并不是真正意义上的拦截所有请求,它不会拦截jsp的页面请求,其他的请求则会拦截
    /*才是真正意义上的拦截所有请求

那么你说我们在SpringMVC开发中应该使用哪个比较好?

小白: 这么来说的话,当然是使用/比较好,因为我们要经常性的返回一些JSP页面。

庆哥: 对的,在SpringMVC中配置前端控制器,一般就这样

<!--配置前端控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

使用/来拦截请求,不拦截我们的jsp页面请求,那你知道什么时候经常使用/*吗?

小白:这个。。。一时间想不起来!

庆哥: 那么你们呢?

最新文章

  1. Clone Graph leetcode java(DFS and BFS 基础)
  2. SQL Server获取下一个编码字符串的实现方案分割和进位
  3. NOJ1008-第几天
  4. centos 安装jdk
  5. Spring4.0学习笔记(5) —— 管理bean的生命周期
  6. MongoDB学习笔记1(简介)
  7. Kafka 在行动:7步实现从RDBMS到Hadoop的实时流传输
  8. 什么是vue?
  9. 复选框checkbox——用背景图片替换样式
  10. 【English】20190315
  11. [linux]主机访问虚拟机web服务(CentOS)
  12. 【最短路+最大流】上学路线@安徽OI2006
  13. AJAX请求返回HTTP 400 错误 - 请求无效 (Bad request)
  14. 通过pip安装python web
  15. 解决Mac下idea运行速度慢
  16. 软工实践——团队作业需求规格说明书——原型UI设计
  17. MySQL 分区表原理及数据备份转移实战
  18. Wannafly挑战赛28 Solution
  19. Hibernate Cannot release connection 了,有办法解决!
  20. 204. Singleton

热门文章

  1. spoj1716 Can you answer these queries III
  2. 数据库commit问题
  3. PreparedStatement预编译对象实现
  4. 删除XML文档中某节点
  5. javascript js获取url及url参数解析
  6. [SinGuLaRiTy] 分治题目复习
  7. 【转】32位plsql连接64位oracle
  8. poj2409(polya 定理模板)
  9. OkHttp 3.x 源码解析之Interceptor 拦截器
  10. Redis及虚拟机windows两种环境安装配置