目录:
- [Spring MVC 的"核心类" 和 "注解" :](#Spring MVC 的“核心类” 和 “注解” :)
-
- 1.DispatcherServlet (前端控制器)
- [2.@Controller 注解](#2.@Controller 注解)
- [3.RequestMapping 注解](#3.RequestMapping 注解)
-
- [3.1 @RequestMapping 注解的 "使用"](#3.1 @RequestMapping 注解的 “使用”)
-
- [标注在 "方法" 上](#标注在 “方法” 上)
- [标注在 "类" 上](#标注在 “类” 上)
- [3.2 @RequestMapping 注解的 "属性"](#3.2 @RequestMapping 注解的 “属性”)
- 4.组合注解
-
- [4.1 请求处理方法的 "参数类型" 和 "返回值类型"](#4.1 请求处理方法的 “参数类型” 和 “返回值类型”)
-
- [请求处理方法中的 "参数类型"](#请求处理方法中的 “参数类型”)
- [请求处理方法的 "返回值类型"](#请求处理方法的 “返回值类型”)
-
- [通过返回值"String类型"进行 "重定向"](#通过返回值“String类型”进行 “重定向”)
- [通过返回值"String类型"进行 "请求forward转发"](#通过返回值“String类型”进行 “请求forward转发”)
- 5.ViewResolver(视图解析器)
Spring MVC 的"核心类" 和 "注解" :
- 在 Spring 2.5之前,只能使用实现Controller接口 的方式来开发一个控制器 ,"SpringMVC的入门" 中例子的就是使用的此种方式。
- 在 Spring 2.5之后,新增加了基于注解的控制器 以及其他一些 常用注解 (即Spring2.5之后 ,可以通过注解 来操作Spring),这些注解 的使用极大地减少了程序员 的开发工作。
1.DispatcherServlet (前端控制器)
DispatcherServlet 的全名 是 org .springframework .web .servlet .DispatcherServlet,它在程序中充当着 前端控制器 的角色。 在使用时,只需将其配置 在项目的web.xml 文件 中。(在web.xml 中配置 "前端控制器")
在 web.xml 中 配置 DispatcherServlet (前端控制器 ) 的配置代码如下 :
xml<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- 在web.xml中配置"前端控制器" : DispatcherServlet --> <!-- 配置"前端过滤器" : DispatcherServlet --> <!-- 假如下面没有通过init-param元素来配置"springmvc配置的位置的话",应用程序会自动在web-inf目录下找名字为 : SpringMvc-servlet.xml的文件来充当"springmvc配置文件" (此处的名字和 DispatcherServlet的名称(SpringMvc)有关系) --> <servlet> <servlet-name>SpringMvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <!-- 初始化时加载SpringMVC的"配置文件" : springmvc-config.xml --> <!-- 如果配置"前端控制器"时,没有用<init-param>元素配置"Springmvc配置文件的位置",应用程序会到web-inf目录下找名字为: "servletName-servlet.xml" 的文件来充当 "springmvc配置文件" --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <!-- 表示容器启动时立刻加载此Servlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringMvc</servlet-name> <!-- 会将所有的url进行拦截 --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
在上述代码 中,<load-on-startup>元素 和**<init-param>元素** 都是可选的。如果 <load-on-startup>元素 的 值为 1,则在应用程序启动时会立即加载该Servlet;如果 <load-on-startup>元素不存在 ,则应用程序会 在第一个Servlet请求 时加载该Servlet 。 如果 <init-param>元素存在 并且通过其子元素 配置了 Spring MVC配置文件 ( Springmvc-config.xml )的路径 ,则应用程序在启动 时会加载配置路径下 的配置文件 ; 如果没有通过<init-param>元素 配置,则应用程序会默认 到WEB-INF目录下 寻找如下方式命名 ( servletName-servlet.xml )的配置文件。
java//如果配置"前端控制器"时,没有用<init-param>元素配置"Springmvc配置文件的位置",应用程序会到web-inf目录下找名字为: "servletName-servlet.xml" 的文件来充当 "springmvc配置文件" //其中servletName的"泛指",指的是在web.xml中的配置的DispatcherServlet的"名称",如上面中的DispatcherServlet的名字为: SpringMvc,则servletName则替换为SpringMvc //所以最后会在web-inf目录下找到"SpringMvc-servlet.xml"的文件来充当"springmvc配置文件" servletName-servlet.xml
其中,servletName ( 是根据实际情况而定 ,不是固定的名字 )指的是部署在web.xml 中的 DispatcherServlet 的名称 ,在上面 web.xm中 的配置代码中 即为SpringMvc ,而 -servlet.xml 是配置文件名 的固定写法 ,所以应用程序 会在 WEB-INF 下寻找 "SpringMvc-servlet.xml " (来充当"springmvc 的配置文件")。
注意点 :(重点,重点,重点 )
( 如果在 web.xml 中 配置"前端控制器 "时,没有通过<init-param>元素 进行添加"Springmvc配置文件 :springmvc-config.xml "的位置 的话,应用程序会到web-inf目录 下找名字为 :"servletName-servlet.xml " 的文件 来充当 "springmvc配置文件"。)
2.@Controller 注解
org.springframework.stereotype .Controller 注解类型 ( @Controller )用于指示 Spring 类 的实例 是一个控制器,其注解形式 为 @Controller 。该 注解在使用 时不需要再实现Controller 接口 (通过将加 @Controller注解 的方式来替代"实现controller接口" ),只需要将 @Controller注解 加入到控制器类 上,然后通过Spring 的扫描机制 找到标注了该注解的控制器即可。
java/** * 控制器类 可用实现"@Controller"接口来 替代implements Controller (两者都能实现相同的效果) */ /** * ① 此处使用@Controller注解的方式来替代 实现"controller接口",此时要通过设置 *@RequestMapping()注解来映射URL * ②使用注解后,要配置<context:component-scan>元素来进行"指定要扫描的包",让注解生效 */ public class FirstController2 implements Controller { //其中的方法要配合@RequestMapping注解一起使用 }
为了保证 Spring 能够找到控制器类,还需要在SpringMVC的配置文件 ( springmvc-config.xml )中添加相应的 扫描配置信息 (用 <context:component-scan>元素 ,来指定需要扫描的包,来进行 "根包扫描 "),( springmvc-config.xml ) 具体配置信息 如下 :
xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 配置"根包扫描",指定需要扫描的包 --> <context:component-scan base-package="com.myh.controller"/> </beans>
注意点1 : ① 与 实现controller接口 不同,使用 @Controller注解 的类中的方法通常使用 @RequestMapping注解 来映射URL ,这样你可以更直观地映射请 求到具体的方法 。此外,@controller注解 通常与 @Autowired等注解 一起使用,以实现依赖注入 ,这使得控制器之间的解耦
更为方便。
② 在使用@controller注解的类中,你可以使用 @ModelAttribute 、@RequestParam等注解 来自动绑定请求参
数 ,也可以使用 @ResponseBody注解 来直接将方法返回 值写入响应体 ,这使得处理请求和响应更为简洁。注意点2 :
使用注解方式 时,程序的运行 需要依赖Spring的 AOP 包,因此需要向 lib目录中添加spring-aop-.jar ,否则程序运行时会报错。
3.RequestMapping 注解
3.1 @RequestMapping 注解的 "使用"
Spring 通过 @Controller 注解 找到相应的控制器类 后,还需要知道控制器内部 对每一个请求 是如何处理的,这就需要使用org.springframework.web.bind.annotation.RequestMapping注解类型。
RequestMapping注解类型 用于 映射一个请求 或一个方法 ,其注解形式为 : @RequestMapping,可以使用该注解 标注在 一个方法 或一个类上。
( 即通过 @Controller注解 则用于 标记"控制器类 ",@RequestMapping注解 则用于 "映射一个方法或一个类" :即前端发送的 "url请求" 通过 "@RequestMapping注解" 能找到对应 的"类 或方法 "上,"类或方法 "则对请求做出"响应"。)
(前端url请求 --找到"控制器 " ---再根据自身携带"url请求信息 ",对比"@RequestMapping 中的url信息 ",找到能做出"响应"的类 或方法。)
标注在 "方法" 上
当 标注 在一个方法 上时,该方法 将成为一个请求处理方法,它会在程序接收到对应 的 URL请求时被调用 (即前端的url请求信息 和 该方法上的@RequestMapping( )注解的 url信息一致 ,该方法就会被调用)。
java/** * 控制器类 */ @Controller //比较该类为"控制器类" public class FirstController { /** * 为"前端的url请求" 和 该"方法"中的"/firstController" 设立URL映射关系 : * 只要是 /firstController 的前端url请求 就会请求到该方法上, 执行该方法,并作出响应。 */ @RequestMapping(value = "/firstController") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { ... return mav; } }
使用 @RequestMapping注解 后,上述代码中的 handleRequest( )方法 就可以通过地址:
标注在 "类" 上
当 @RequestMapping注解 标注在一个类 上时,该类中的所有方法 都将映射为相对于类级别 的请求 ,表示该控制器 所处理的所有请求 都被映射到value属性 值所指定的路径下。
(简而言之 :
@RequestMapping 用在类 上,就表明前端能通过"url路径 / url请求" 找到被 @RequestMapping标记 的"控制器类"上,将 "控制器类 " 和 "前端url请求" 进行URL映射绑定。)
java/** * 控制器类 */ @Controller //比较该类为"控制器类" @RequestMapping(value = "hello") //前端的"url请求"能找到该"控制器类" public class FirstController3 { @RequestMapping(value = "/FirstController3") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { ... return mav; } }
由于在 "控制器类"上 添加了 @RequestMapping 注解,并且其value 属性值为"/hello",所以上述代
码中 的 handleRequest( )方法 的请求路径将变为:http://localhost:8080/springMVC_Demo/hello/firstController。如果该**类中还包含其他方法** ,那么在其他方法的请求路径中 也需要加入"/hello"。
3.2 @RequestMapping 注解的 "属性"
@RequestMapping注解 中 "属性"-详解 :
属性 类型 描述 name String 可选属性 ,用于为映射地址 指定别名。 value (默认属性) String[] 可选属性 ,同时也是 默认属性,用于映射一个请求 和一种方法,可以标注在 一个方法 或一个类上 。 ps : 当 value 是其唯一属性 时,可以省略属性名 ,即当注解中 只有value 这一个属性 时,可省略不写value ( 省略属性名 ) method RequestMethod[] 可选属性 ,用于 指定 该方法用于处理哪种类型 的请求方式,其请求方式 包括 GET 、POST 、HEAD 、OPTIONS 、PUT 、PATCH 、DELETE 和 TRACE 。 例如 method=RequestMethod.GET 表示只支持 GET 请求 ,如果需要支持多个请求方式 则需要通过 { }写成数组的形式 ,并且多个请求方式之间 是有英文逗号分隔。 params String[] 可选属性 ,用于指定Request 中 必须包含某些参数的值 ,才可以通过其标注的方法处理。 headers String[] 可选属性 ,用于指定Request 中必须包含 某些指定的header的值,才可以通过其标注的方法处理。 consumes String[] 可选属性 ,用于指定处理请求 的提交内容类型( Content-type ),比如 application/json 、text/html 等。 produces String[] 可选属性 ,用于指定返回 的内容类型,返回的内容类型 必须是request请求头 ( Accept )中所包含的类型。 在上表中,所有属性 都是可选的,但其 默认属性 是value。当 value 是其唯一属性 时,可以省略属性名 ,例如下面两种标注的含义 相同 (因为只有value这个一个属性 ) :
java/** * 因为只有value这一个属性,所以value这个属性名可以省略不写。 * (这两个注解含义相同) */ @RequestMapping(value = "hello") @RequestMapping("hello")
4.组合注解
在Spring框架的4.3版本中,引入 了 组合注解,来帮助简化常用的HTTP 方法 的映射 ,并更好地表达被注解方法 的语义 。其组合注解如下所示 :
@GetMapping : 匹配 GET 方式 的请求 。
@PostMapping : 匹配 POST 方式 的请求 。
@PutMapping : 匹配 PUT 方式 的请求 。
@DeleteMapping : 匹配 DELETE 方式 的请求 。
@PatchMapping : 匹配 PATCH方式 的请求。以 @GetMapping 为例,该 组合注解 是 @RequestMapping(method = RequestMethod.GET)
的 缩写,它会将 HTTP GET映射 到特定的处理方法上。
例子如下 :
传统的@RequestMapping注解 的使用方式 如下 :
java//"传统"的@RequestMapping注解使用方式 @RequestMapping(value = "/user/{id}",method = RequestMethod.GET) public String selectUserById(String id) { .... }
新注解 : @GetMapping 的 使用方式 如下 :
java//"新注解 :@GetMapping注解的使用 //新注解比"传统的注解方式" 使用起来更简单 @GetMapping(value = "/user{id}") public String selectUserById(String id) { .... }
新注解 ( 组合注解 )比"传统的注解方式 " 使用起来更简单 ,可以省略method属性。
4.1 请求处理方法的 "参数类型" 和 "返回值类型"
请求处理方法中的 "参数类型"
在控制器类 中,每一个请求处理方法 都可以有多个不同类型 的参数 ,以及一个多种类型 的返回结果。例如在入门案例 中,handleRequest()方法 的 参数 就是对应请求的 HttpServletRequest 和 HttpServletResponse 两种参数类型。除此之外,还可以使用其他的参数类型,例如在请求处理方法中需要访问HttpSession 对象,则可以添加 HttpSession 作为 参数,Spring会将对象正确地传递给方法,其使用示例如下 :
java@GetMapping(value = "/user{id}") public String selectUserById(HttpSession session) { //该"请求处理方法"的参数为 : HttpSession .... }
在 请求处理方法 中, 可以出现 的参数类型 如下:(注意: 下面的"请求方法 "中的"参数内容" )
.javax.servlet.ServletRequest / javax.servlet.http.HttpServletRequest
javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse
javax.servlet.http.HttpSession
org.springframework.web.context.request.WebRequest 或
org.springframework.web.context.request.NativeWebRequest
java.util.Locale
java.util.TimeZone (Java 6+) / java.time.Zoneld (on Java 8)
java.io.InputStream / java.io.Reader
java.io.OutputStream / java.io.Writer
org.springframework.http.HttpMethod
java.security.Principal
@PathVariable 、@MatrixVariable 、@RequestParam 、@RequestHeader 、@RequestBody
@RequestPart 、@SessionAttribute 、@RequestAttribute 注解
HttpEntity<?>java.util.Map / org.springframework.ui.Model / org.springframework.ui.ModelMap
.org.springframework.web.servlet.mvc.support.RedirectAttributes
org.springframework.validation.Errors /org.springframework.validation.BindingResult
org.springframework.web.bind.support.SessionStatus
·org.springframework.web.util.UriComponentsBuilder
ps :
需要注意的是 ,org.springframework.ui.Model类型不是一个Servlet API类型,而是一个包含了 Map 对象 的 Spring MVC 类型。如果方法中添加 了Model 参数 ,则每次调用该请求处理方法时 ,Spring MVC 都会创建Model对象 ,并将其作为参数传递给方法。
请求处理方法的 "返回值类型"
在上面代码案例中,请求处理方法返回 的是一个ModelAndView类型 的数据 ( 请求处理方法 的返回值类型 为 :ModelAndView类型 )。除了此种类型外 ,请求处理方法 还可以返回其他类型的数据。
Spring MVC 所支持 的常见方法返回类型 ( 返回值类型 )如下 :
返回值类型 描述 ModelAndView (常用) ModelAndView 类型中可以 添加Model 数据,并 指定视图 Model (常用) --------- Map --------- View String (常用 ) ps : 实际开发中通用String 类型跳转""视图"" + Model参数 传递"属性值"。 String类型 的 返回值 可以跳转视图,但不能携带数据。 ps : String 类型除了可以跳转"视图 "外,还能 "重定向 " 和 "请求转发"。 void (常用) void类型 主要在 异步请求时使用,它只返回数据 ,而不会跳转视图。 HttpEntity<?> 或 ResponseEntity<?> --------- Callable<?> --------- DeferredResult<?> --------- 注意点 :
由于==ModelAndView 类型未能实现数据与视图之间 的解耦 ,所以在企业开发时,方法 的返回类型 通常都会使用String 。既然 String 类型 的返回值不能携带数据 ,那么在方法中 是如何将数据带入视图页面的呢 ?这就用到 ==了上面所讲解的 Model 参数类型 ( Mode类型 : 属于处理方法 中的 参数类型 ),通过该参数类型 ,即可添加需要在视图中显示 的属性。
(实际开发 中,常用 的是 :
① 通过String 类型跳转""视图" " ② 通过Model参数 类型传递"属性值")
java@Controller //比较该类为"控制器类" @RequestMapping(value = "/firstController") //前端的"url请求"能找到该"控制器类" public class FirstController3 { @GetMapping(value = "/firstController") //返回值类型为 : String : 可跳转"视图"。 //处理方法中的"参数类型" : Model(模型对象) : 可传递"属性"(给"视图")--通过Model向视图中添加传递数据 public String selectUserById(HttpServletRequest request, HttpServletResponse response ,Model model) { //向Model(模型对象)中添加数据 --进行数据的传递 model.addAttribute("msg", "这是我的第一个Spring MVC程序。"); //通过String类型返回"视图" return "WEB-INF/jsp/first.jsp"; } }
在上述方法代码 中,"处理方法 "中参数 的类型有 : Model (模型对象),通过该参数实例 的addAttribute( )方法即可添加所需数据 。"处理方法 "的返回值类型 为 : String类型 ,String类型 除了可以返回上述代码中 的视图页面 外,还可以进行 重定向 与请求转发。
通过返回值"String类型"进行 "重定向"
java//通过String类型进行"重定向" @RequestMapping(value = "/update") //返回值类型为 : String ,此处通过String来进行"重定向" public String selectUserById(HttpServletRequest request, HttpServletResponse response ,Model model) { ..... return "redirect:queryUser"; }
通过返回值"String类型"进行 "请求forward转发"
java//通过String类型进行"forward请求转发" @RequestMapping(value = "/toEdit") public String selectUserById(HttpServletRequest request, HttpServletResponse response ,Model model) { ..... return "forward:editUser"; }
5.ViewResolver(视图解析器)
Spring MVC 中的 视图解析器 负责解析视图,可以通过在配置文件中 定义一个ViewResolver 来配置视图解析器 ,其配置示例如下 :
xml<!-- 配置"视图解析器" : 在"处理方法"中可直接写要返回的"视图文件名",不用写"该视图"对应的前后缀 --> <!-- 在视图解析器中配置要返回的视图的对应的"前后缀" --> <!-- 配置视图解析器 : 可简化在"处理方法"中要填的"视图的路径" --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 设置返回的"视图"对应的"前缀" --> <property name="prefix" value="/WEB-INF/jsp"/> <!-- 设置返回的"视图"对应的"后缀" --> <property name="suffix" value=".jsp"/> </bean>
在上述代码 中,定义了一个id 为viewResolver 的 视图解析器,并设置了 视图的前缀 和后缀 属性。这样设置后,方法中所定义的view 路径 将可以简化。例如,上面例子 中的逻辑视图名 只需设置为"first ",而不再需要设置为"WEB-INF/jsp/first.jsp" (配置了前后置,现在只return "first" 就能返回一个视图 ),在访问时视图解析器 会自动地增加前缀 和后缀。