SpringMVC
1. 核心组件
SpringMVC框架中提供给用户如下几个概念:
-
DispatcherServlet:(又称前端控制器)
核心控制器,用来过滤客户端发送过来,想要进行逻辑处理的请求
-
Handler(Controller):
处理器。开发人员自定义,用来处理用户请求的,并且处理完成之后返回给用户指定视图的对象。
-
HandlerMapping:
处理器映射器。DispatcherServlet在根据URL转发请求给Handler时得有一个匹配规则,这个匹配规则由HandlerMapping决定。
-
HandlerAdaptor
处理器适配器。处理器适配器用来适配每一个要执行的Handler对象。
-
ViewResolver
视图解析器,Handler返回的是逻辑视图名,需要有一个解析器能够将逻辑视图名转换成实际的物理视图
Spring的可扩展性决定了视图可以由很多种,所以需要不同的视图解析器,解析不同的视图。
配置如下:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 设置生成的视图的类型,比如jsp对应的视图类为 JstlView--> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"> </property> <!-- 如果要返回的所有的视图都在同一个package下,比如都在/WEB-INF下,可以使用同一的前缀 --> <property name="prefix" value="/WEB-INF/"></property> <!-- 如果所有页面返回的均是.jsp页面,可以省略后缀 .--> <property name="suffix" value=".jsp"></property> </bean>
注意:
处理器适配器,处理器映射器,视图解析器等都的配置都可以省略,
在spring的jar中都拥有默认的配置的。
2.组件交互
流程图:
流程介绍:
首先 用户在浏览器 发送一个请求,然后前端控制器收到请求后,将具体访问路径传给 处理映射器,处理映射器 根据 url 找到响应的Controller。然后返回一个对象,包含了 请求路径对应的处理对象和多个拦截器。前端控制器将收到的处理对象交给适配器,然后适配器根据 处理对象 的类型,(可能是实现接口,也可能是继承抽象类,也可能是注解)去适配处理器,然后处理器调用指定方法,返回数据和视图(逻辑视图,只有视图的名字),适配器将获得到的modelAndView 再交给 前端控制器,前端控制器再传给 视图解析器,视图解析器通过逻辑视图,找到真正的物理视图传送给前端控制器,再把物理视图交给jsp引擎去视图渲染,渲染完成后,通过前端控制器返回给用户,用户就看到了具有图形界面的视图
3.基于注解实现:
Spring MVC 是表现层框架 所以在动态web项目中配置。
而一个常规配置的web项目 拥有javaResources,build,WebConten。三类文件夹。
在WebConten/WEB-INF 中 先对lib 放入我们需要的jar包,然后在web.xml中配置前端控制器(也就是核心控制器)和加载SpringMVC的配置文件,以及启动时创建servlet 对象,最后需要配置拦截,默认将所有的访问都经过springMVC。
需要的包:
lo4j 与lombook 只是辅助,不是必须的。commons 是被log4j所依赖。
其他spring开头的 都是我们SpringMVC需要的jar包。
Web.xml 配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>你的项目名~</display-name>
<!--配置spring mvc的核心控制器 -->
<servlet>
<servlet-name>SpringMVCDispatcherServlet</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对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 拦截-->
<servlet-mapping>
<servlet-name>SpringMVCDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
而SpringMVC 需要配置在src包底下。
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--在beans的配置中,注意一个细节,有的标签的xsi:schemaLocation 是不支持https的,如果在配置之后 启动tomcat 报找不到元素 'beans’的声明的错误 记得将https改成http 例如bean的版本,只有5.1.7以上版本才能使用https (改观点来自同站笔友:https://blog.csdn.net/qq_43342172/article/details/103217262)感谢-->
<!--mvc:annotation-driven覆盖了DispatcherServlet对象的很多默认配置信息 有了它,我们才能像使用xml那样去通过注解使用SpringMVC(相当于有了处理映射器和处理解析器)-->
<mvc:annotation-driven/>
<!--spring 中的扫描 扫描com.mvc包底下所有的文件查看是否有类头上有@Controller注解,如果有,那它就是一个控制器类-->
<context:component-scan base-package="com.mvc"></context:component-scan>
<!-- 视图解析器,prefix 前缀,suffix 后缀 具体用法在控制类中解释-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
控制类:
package com.mvc;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
//与spring 中的 Component 一样 有了这个才能被扫描 才能够使用注解的形式实现应用
@Controller
public class HelloController {
//这是在没有配置视图解析的情况下
//RequestMapping 代表 当前控制器里面的控制器方法对外提供的访问路径
// 相当于将一个请求路径与方法进行绑定
//可以有多个地址
@RequestMapping(value = {"/hello","say"})
public ModelAndView hello() {
ModelAndView mv = new ModelAndView();
mv.addObject("rs","wuwuwuwuwuwu");
mv.setViewName("index.jsp");
// 直接 返回 ModelAndView 对象
return mv;
}
//这是在没有配置视图解析的情况下
//返回类型为String类型 返回的就是逻辑视图名 模型里面就没有数据了
@RequestMapping("/hello2")
public String hello2() {
return "index.jsp";
}
// 一下俩种就是配了视图解析器,在视图解析的作用下,默认的为视图的名称加上了前缀和后缀,所以这里只需要 返回 index 在视图解析器查找物理视图的时候,它事件上查找的是 /WEB-INF/index.jsp
@RequestMapping("/hello3")
public String hello3() {
return "index";
}
/* 这里的二级标题 意思是 可以随便传参数。都会被获取到这个方法中来,比如说
* /p/dasdasdasdsadsa 此时的param 就是dasdasdasdsadsa
*/
@RequestMapping("/p/{param}")
public String p() {
return "index";
}
/* 可以通过@PathVariable 获取param 的值。这个可以用在未来 匹配数据库时的
数据依据
*/
@RequestMapping("/p/{param}")
public String ptwo(@PathVariable String param) {
System.out.println(param);
return "index";
}
//上面那种是形参名字相同,所以可以直接匹配,如果形参名字不同,则不能匹配,而在
//注解的后面加上与网页形参相同的标识,则可以匹配。这里我说的是大概这个意思。
// 看不懂可以看代码 就能理解
@RequestMapping("/p/{param}")
public String ptwo(@PathVariable("param") String param1) {
System.out.println(param1);
return "index";
}
}
4.一些小细节
在web.xml 配置文件中,我们拦截了所有的请求,但是如果我们想要访问静态资源,能否正常访问到呢? 在当前情况下,我们所有的访问都会被拦截到springmvc中去,而springmvc 根据视图名称去查找是否有对应的控制器,如果没有 则没有响应。在我们想要访问静态资源时,springmvc将静态资源名当作视图名称去查找控制器,是查找不到我们想要的静态资源的。所以在这个时候,我们可以使用一些配置,在我们访问静态资源时,能够访问到我们想要的静态资源。
方法一:tomcat自带的defaultServlet
缺点:每种类型的静态资源需要分别配置一个servlet-mapping
<!--这样在我们访问 /css /image 底下的文件 和所有后缀是js的文件时,就可以直接访问到。不会被拦截到springmvc-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/image/*</url-pattern>
</servlet-mapping>
方法二:在spring的配置文件中启用mvc 这个schema
<!-- 俩个星号 代表则穿透 比如说 /css/da/dgsas/gfjhjdsa/sassdh
那么这样的访问也是会访问到/css/文件夹底下的静态资源,至于是否能展示出效果,就看你自己在这个路径下是否有对应的静态资源了。。
-->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
方法三:使用 <mvc:default-servlet-handler >
<mvc:default-servlet-handler />
性能最好的应该是直接利用的Default Servlet
,让它最先拦截静态资源请求,这样就避免了后续的转发等操作,提高了性能,但是无法访问classpath下的资源文件。
而通过mvc:resources
标签可以简单配置匹配规则和资源文件路径,应该说是最简单快捷的一种方式,当然这大概也是mvc命名空间设计的初衷
今天就先这样。比心。