springmvc全面学习
一.springmvc概述
1.概述
SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架。它通过一套注解让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。
2.优点
-
多视图共享一个模型,大大提高了代码的可重用性
-
MVC 三个模块相互独立,松耦合架构
-
控制器提高了应用程序的灵活性和可配置性
-
有利于软件工程化管理
二.springmvc工作原理
1.DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求,
DispatcherServlet接收请求并拦截请求
2.HandlerMapping为处理器映射,DispatcherServlet调用,主要作用是根据url查找Handler3.HandlerExecution表示具体的Handler,主要作用是根据url查找控制器,如上url被查找控制器为hello
4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
5.HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
6.Handler让具体的Controller执行
7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
8.HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
9.DispatcherServlet调用视图解析器(ViewResolver)来解析HanderAdapter传递的逻辑视图名
10.视图解析器将解析的逻辑视图名传递给DispatcherServlet
11.DispatcherServlet根据视图解析器的视图结果调用具体的视图
12.视图呈现给用户
三.springmvc第一个程序
1.使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency> </dependencies>
2.创建SpringMVC控制器类(等同于Servlet功能)
//定义表现层控制器bean @Controller public class UserController { //设置映射路径为/save,即外部访问路径 @RequestMapping("/save") //设置当前操作返回结果为指定json数据(本质上是一个字符串信息) @ResponseBody public String save(){ System.out.println("user save ..."); return "{'info':'springmvc'}"; } //设置映射路径为/delete,即外部访问路径 @RequestMapping("/delete") @ResponseBody public String delete(){ System.out.println("user save ..."); return "{'info':'springmvc'}"; } }
3.初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
//springmvc配置类,本质上还是一个spring配置类 @Configuration @ComponentScan("com.itheima.controller") public class SpringMvcConfig { }
4.加载SpringMVC环境,并设置SpringMVC技术处理的请求,专用于加载springmvc的核心配置,我们需要做的就是创建空容器并注册,返回出去
//定义一个servlet容器的启动配置类,在里面加载springmvc的配置 public class ServletContainitConfig extends AbstractDispatcherServletInitializer { //加载Springmvc容器配置的 @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); //上方操作完成后并未加载MVC的配置,所以是一个空的容器,需要以下操作来加载配置 ctx.register(SpringMvcConfig.class); return ctx; } //设置哪些请求归springmvc处理的 @Override protected String[] getServletMappings() { return new String[]{"/"}; } //加载spring容器配置,注意与springMVC区分 @Override AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); //上方操作完成后并未加载MVC的配置,所以是一个空的容器,需要以下操作来加载配置 ctx.register(SpringConfig.class); return ctx; }
5.导入tomcat坐标
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>80</port> <path>/</path> </configuration> </plugin> </plugins> </build>
四.springmvc多种类型数据响应
-
页面跳转
(1)配置视图解析器
-
xml方式:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean>
-
注解方式:
//在spring配置类中加入视图解析器的配置 @Bean public InternalResourceViewResolver internalResourceViewResolver(){ InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; }
-
编写控制器和处理请求的方法
@Controller public class HelloController { @RequestMapping("/hello") public String hello(){ System.out.println("hello···"); return "hello"; } }
(2)返回字符串
-
直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转
资源地址:/WEB-INF/views/hello.jsp
-
返回带有前缀的字符串:
转发:forward:/WEB-INF/views/hello.jsp
重定向:redirect:/index.jsp
@RequestMapping("/forward") public String forword(){ System.out.println("forward···"); return "forward:/WEB-INF/views/index.jsp"; } @RequestMapping("/redirect") public String redirect(){ System.out.println("redirect···"); return "redirect:/login.jsp"; }
(3)返回ModelAndView对象
- 修改hello.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> 你好,SpringMVC!${username} </body> </html>
- 编写控制器中处理请求的方法
@RequestMapping("/hello2") public ModelAndView hello2(){ //Model:模型,用于封装数据 //View:视图,用于展示数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("username","pep7chiao"); modelAndView.setViewName("hello"); return modelAndView; } @RequestMapping("/hello3") public ModelAndView hello3(ModelAndView modelAndView){ modelAndView.addObject("username","pep7chiao"); modelAndView.setViewName("hello"); return modelAndView; } @RequestMapping("/hello4") public String hello4(Model model){ model.addAttribute("username","messi"); return "hello"; } @RequestMapping("/hello5") public String hello5(HttpServletRequest reqest){ //HttpServletRequest需要添加依赖 reqest.setAttribute("username","ronaldo"); return "hello"; }
-
-
回写数据
(1)直接返回字符串
-
通过SpringMVC框架注入的response对象,使用response.getWriter().print(“hello world”)回写数据,此时不需要视图跳转,业务方法返回值为void。
@RequestMapping("/data1") public void data1(HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=utf-8"); response.getWriter().print("重庆工程学院"); }
-
将需要回写的字符串直接返回,但此时需要通过**@ResponseBody**注解告知SpringMVC框架,方法返回的字符串不是跳
转,而是直接在http响应体中返回。
@RequestMapping(value = "/data2",produces = "text/html;charset=utf-8") @ResponseBody public String data2(){ return "软件工程研究所"; }
(2)返回对象或集合
- 导入json相关依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency>
-
开启mvc的注解驱动
-
xml方式:spring核心配置文件中加以下配置
<mvc:annotation-driven/>
-
注解方式:spring配置类上加以下注解
@EnableWebMvc
-
-
在com.cqgcxy.entity包下创建实体类
package com.cqgcxy.entity; public class Phone { // phone_id bigint private Long phoneId; // brand_id bigint private Long brandId; // model_number varchar private String modelNumber; // capacity int private Integer capacity; public Long getPhoneId() { return phoneId; } public void setPhoneId(Long phoneId) { this.phoneId = phoneId; } public Long getBrandId() { return brandId; } public void setBrandId(Long brandId) { this.brandId = brandId; } public String getModelNumber() { return modelNumber; } public void setModelNumber(String modelNumber) { this.modelNumber = modelNumber; } public Integer getCapacity() { return capacity; } public void setCapacity(Integer capacity) { this.capacity = capacity; } @Override public String toString() { return "Phone{" + "phoneId=" + phoneId + ", brandId=" + brandId + ", modelNumber='" + modelNumber + '\'' + ", capacity=" + capacity + '}'; } }
-
编写控制器中处理请求的方法
@RequestMapping("/data3") @ResponseBody public Phone data3() { Phone phone = new Phone(); phone.setPhoneId(1L); phone.setBrandId(1L); phone.setModelNumber("mate60"); phone.setCapacity(256); return phone; }
-
五.springmvc拦截器
1.概念
拦截器是基于Java的jdk动态代实现的,实现HandlerInterceptor接口。不依赖于servlet容器,拦截器针对于contraller方法,并且能获取到所有的类,对类里面所有的方法实现拦截,粒度更小,拦截器中可以注入service,也可以调用业务逻辑。
2.实现
•通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类(例如 HandlerInterceptorAdapter)来定义;
• 通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义
public class MyTestInterceptor implements HandlerInterceptor {
// 在调用目标controller方法“前”会被调用
// 返回值:true代表放行,false代表拦截住不继续往下执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器:preHandle");
return true;
}
// 在调用目标controller方法“后”,解析视图之"前"
// 可以让编程者,控制最终视图的走向、以及视图中携带的数据内容是否发生更改
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器:postHandle");
}
// 在调用目标controller方法“后”,以及视图渲染完成,数据返回成功才执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器:afterCompletion");
}
}
<!-- 拦截器的配置 -->
<mvc:interceptors>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- 哪些路径进入拦截器 -->
<mvc:mapping path="/**"></mvc:mapping>
<!-- 描述自定义拦截器实例 -->
<bean class="com.huawei.mvcdemo2023.testClass.interceptors.MyTestInterceptor" />
</mvc:interceptor>
</mvc:interceptors>