Spring MVC

一、三层架构介绍和MVC设计模型介绍

1. 三册架构

在这里插入图片描述

2. MVC设计模式

MVC全名是Model View Controller
Model(模型):通常指的是数据模型,一般情况下用于封装数据
View(视图):通常指定的就是我们的jsp或者html
Controller(控制器)

二、SpringMVC简介

1. SpringMVC概述

SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架

2. 快速入门

  1. 导入SpringMVC相关坐标
 <!--Spring坐标-->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.1.5.RELEASE</version>
 </dependency>
 <!--SpringMVC坐标-->
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-webmvc</artifactId>
     <version>5.0.5.RELEASE</version>
 </dependency>
<!--Servlet坐标-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>
<!--Jsp坐标-->
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
</dependency>
  1. 在web.xml中配置SpringMVC的核心配置器DispatcherServlet
<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:spring-mvc.xml</param-value>
    </init-param>
    <!--启动时加载-->
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>   
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  1. 创建Controller和业务方法
@Controller
@RequestMapping("/user")
public class UserController {
	@RequestMapping("/quick")
	public String quickMethod() {
		System.out.println("QuickMethod running...");
		return "/success.jsp";
	}
}
  1. 创建spring-mvc.xml
<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="cn.mvc.controller"/>
</beans>
  1. 访问测试
    访问http:localhost:8080/mvc/user/quick

3. SpringMVC的组件解析

3.1 SpringMVC的执行流程

SpringMVC执行流程图

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器
  3. 处理器映射器找到具体的处理器(根据xml配置或注解),生成处理器对象及处理器拦截器(如果有处理器拦截器则生成)一并返回给DispatcherServlet
  4. DispatcherServlet调用HandlerAdapter处理器适配器
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充值至视图中),DipatcherServlet响应用户
3.2 SpringMVC组件解析
  1. 前端控制器:DispatcherServlet

     用户请求到达前端控制器,相当于MVC模式中的C(controller),DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。
    
  2. 处理器映射器:HandlerMapping

     HandlerMapping负责根据用户请求找到Handler处理器,SpringMVC提供了不同的映射器实现不同的映射方式,如配置文件方式、实现接口、注解等。
    
  3. 处理器适配器:HandlerAdapter

     通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
    
  4. 处理器:Handler

     就是编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler,然后Handler对具体的用户请求进行处理。
    
  5. 视图解析器:View Resolver

     View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户
    
  6. 视图:View

     SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等
    
3.3 RequestMapping注解
  1. RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
  2. RequestMapping注解可以作用在方法和类上
    • 作用在类上:第一级的访问目录
    • 作用在方法上:第二级的访问目录
    • 细节:路径可以不编写 / 表示应用的根目录开始
    • 细节:${pageContext.request.contextPath}也可以省略不写,但是路径上不能写 /
  3. RequestMapping的属性
    • path 指定请求路径的URL
    • value value属性和path属性是一样的
    • method 指定该方法的请求方式
    • params 指定限制请求参数的条件
    • headers 发送的请求中必须包含的请求头
3.4 SpringMVC的XML配置解析

SpringMVC的默认组件配置由DispatcherServlet.properties配置,该文件配置了默认的视图解析器,这个视图解析器的默认设置有

REDIRECT_URL_PREFIX = "redirect:"  --重定向前缀
FORWARD_URL_PREFIX = "forward:"    --转发前缀(默认值)
prefix = "";     --视图名称前缀
suffix = "";     --视图名称后缀

我们可以通过属性注入的方式修改视图的前后缀

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/pages/"></property>
  <property name="suffix" value=".jsp"></property>
</bean>

三、SpringMVC的请求和响应

1. 数据响应

1.1 页面跳转

(1) 返回字符串形式
页面跳转

(2) 返回ModelAndView形式

//自己创建ModelAndView对象
@RequestMapping("/quick2")
public ModelAndView test2() {
	ModelAndView modelAndView = new ModelAndView();
	modelAndView.addObject("username","itcast");
	modelAndView.setViewName("success");
	return modelAndView;
}

//在形参中声明ModelAndView
@RequestMapping("/quick3")
public ModelAndView test3(ModelAndView modelAndView) {
	modelAndView.addObject("username","itcast");
	modelAndView.setViewName("success");
	return modelAndView;
}

@RequestMapping("/quick4")
public String test3(Model model) {
	model.addObject("username","itcast");
	return "success";
}
1.2 回写数据

(1) 直接回写字符串

@RequestMapping("/quick5")
@ResponseBody	//告知SpringMVC框架,不进行视图跳转,直接进行数据响应
public String test5() {
	return "Hello MVC";
}

(2) 直接回写json格式字符串
使用jackson工具进行转换,需导入jackson工具的依赖

@RequestMapping("/quick6")
@ResponseBody	//告知SpringMVC框架,不进行视图跳转,直接进行数据响应
public String test6() throws IOException {
	User user= new User("lisi", 30);
	ObjectMapper objectMapper = new ObjectMapper();
	String json = objectMapper.writeValueAsString(User);
	return json;
}

(3) 返回对象或集合
SpringMVC可以自动将对象或集合转换成json字符串,我们只需要为处理器适配器配置消息转换参数

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
  <property name="messageConverters">
    <list>
      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </list>
  </property>
</bean>

配置之后返回对象或集合就可以自动转换

@RequestMapping("/quick7")
@ResponseBody
public User test7(){
    User user = new User();
    user.setUsername("lisi2");
    user.setAge(32);
    return user;
}

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器被称为SpringMVC的三大组件。
在spring-mvc.xml配置文件中使用mvc:annotation-driven/替代注解处理器和适配器的配置,mvc:annotation-driven/默认底层就会集成jackson进行对象或集合的json字符串的转换

2. 数据请求

2.1 获取基本类型参数

Controller中业务方法的参数名称要与请求参数的名称一致,参数值会自动映射,并且能将请求参数中的文本类型转换为其他数据类型。

@RequestMapping("/quick8")
@ResponseBody
public void test8(String username, int age) {
	System.out.println(username);
	System.out.println(age);
}
2.2 获得POJO类型参数

Controller中业务方法的参数对象的属性名要与请求参数的名称一致,参数值会自动映射。

@RequestMapping("/quick9")
@ResponseBody
public void test9(User user) {
	System.out.println(user.getUsername());
	System.out.println(user.getAge());
}
2.3 获得数组类型参数

Controller中的业务方法的数组参数名称要与请求参数的名称一致,参数值会自动映射

@RequestMapping("/quick10")
@ResponseBody
public void test10(String[] strs) {
	System.out.println(Arrays.asList(strs));
}
2.4 获得集合类型参数
(1) 方式1

可以将集合参数包装到一个POJO中,通常这个POJO名称为VO

<form action="user/quick11" method="post">
	<input type="text" name="userList[0].username"><br>
	<input type="text" name="userList[0].age"><br>
	<input type="text" name="userList[1].username"><br>
	<input type="text" name="userList[1].age"><br>
	<input type="submit" value="提交">
</form>

VO对象

public class VO {
	private List<User> userList;
	
	public List<User> getUserList() {
		return userList;
	}

	public void setUserList(List<User> userList) {
		this.userList = userList;
	}

	@Override
    public String toString() {
        return "VO{" +
                "userList=" + userList +
                '}';
    }
}

Controller对象

@RequestMapping("/quick11")
@ResponseBody
public void test11(VO vo) {
	System.out.println(vo);
}
(2) 方式二

当使用ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用**@RequestBody**可以直接接收集合数据而无需使用POJO进行包装

<script src="${pageContext.request.contextPath}/js/jquery.js"></script>
    <script>
        var userList = new Array();
        userList.push({username:"zhangsan",age:18});
        userList.push({username:"lisi",age:19});
        $.ajax({
            type:"POST",
            url:"${pageContext.request.contextPath}/user/quick12",
            data:JSON.stringify(userList),
            contentType:"application/json;charset=utf-8"
        });
</script>

因为前端控制器无法访问静态资源,所以需要在spring-mvc.xml中开放资源的权限或者使用默认Tomcat服务器处理

<!-- 开放资源的权限 -->
<mvc:resources mapping="/js/**" location="/js/"/>

<!-- 使用默认服务器处理 -->
<mvc:default-servlet-handler/>
2.5 配置全局乱码过滤器

当post请求中有中文时,数据会出现乱码,我们可以设置一个过滤器来进行编码的过滤。

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
2.6 参数绑定注解

当请求的参数与Controller的业务方法不一致时,就需要通过@RequestParam注解来进行参数的绑定

@RuquesteMapping("/quick12")
@ResponseBdoy
public void test12(@RequestBody(value="name", required=false, defaultValue="springmvc") String username) {
	System.out.println(username);
}
2.7 Restful风格的参数的获取

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
(1) GET:用于获取资源
(2) POST:用于新建资源
(3) PUT:用于更新资源
(4) DELETE:用于删除资源
在SpringMVC中可以使用占位符进行参数绑定,在业务方法中使用@PathVariable注解进行占位符的匹配获取工作。
http://localhost:8080/spring_mvc_war_exploded/quick13/zhangsan

@RuquesteMapping("/quick13/{name}")
@ResponseBdoy
public void test13(@PathVariable("name") String username) String username) {
	System.out.println(username);
}
2.8 自定义类型转换器

Spring默认提供的类型转换器可能会不满足业务的需求,因此需要配置自定义的类型转换器。

//通过实现Converter接口创建自定义转换器
public class Date2StringConverter implements Converter<String, Date> {
	@Override
	public Date converter(String dateStr) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date date = sdf.parse(dateStr);
			return date;
		} catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}
}
@RequestMapping("/quick13")
@ResponseBody
public void test13(Date date) {
	System.out.println(date);
}
2. 9 获得Servlet相关API
@RequestMapping("/quick14")
@ResponseBody
public void test14(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    System.out.println(request);
    System.out.println(response);
    System.out.println(session);
}
2. 10 获得请求参数

@RequestHeader

@RequestMapping("/quick15")
@ResponseBody
public void test15(@RequestHeader(value = "User-Agent",required = false) String user_agent) {
    System.out.println(user_agent);
}

@CookieValue

@RequestMapping("/quick16")
@ResponseBody
public void test16(@CookieValue(value = "JSESSIONID") String jsessionId) {
    System.out.println(jsessionId);
}

四、 SpringMVC实现文件上传

1. 客户端表单实现

实现文件上传客户端表单需要满足三个条件:
(1) 表单项type=“file”
(2) 表单提交方式是post
(3) 表单的enctype属性是多部分表单形式,enctype=“multipart/form-data”

<form action="user/quick17" method="post" enctype="multipart/form-data">
	名称<input type="text" name="username"><br>
	文件1<input type="file" name="uploadFiles"><br>
	文件2<input type="file" name="uploadFiles"><br>
	<input type="submit" value="提交">
</form>

2. 文件上传实现

2.1 添加依赖
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.3</version>
</dependency>
2.2 配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="defaultEncoding" value="UYF-8"/>
	<property name="maxUploadSize" value="500000"/>
</bean>
2.3 后台程序
@RequestMapping("/quick18")
@ResponseBody
public void test18(String username, MultipartFile[] uploadFiles) {
    System.out.println(username);
   	for (MultipartFile uploadFile : uploadFiles) {
		String originalFilename = uploadFile.getOriginalFilename();
		uploadFile.transferTo(new File("D:\\" + originalFilename));
	}
}

五、 SpringMVC拦截器

1. 概念

1.1 作用

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

1.2 interceptor和filter的区别
使用范围拦截范围
interceptor是属于SpringMVC框架的,只有使用了SpringMVC框架的工程才能使用只会拦截访问控制器的方法,不会拦截静态资源的访问
filter是Servlet规范中的一部分,任何Web工程都可以使用在url-pattern中配置/*后可以对所有要访问的资源拦截

2. 开发

1. 步骤
  1. 创建拦截器类实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
    //在目标方法执行之前执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String param = request.getParameter("param");
        System.out.println("preHandle11111111");
        if("yes".equals(param)) {
            return true;
        } else {
            request.getRequestDispatcher("/jsp/error.jsp").forward(request, response);
            return false;
        }
//        return true; //返回true代表放行,返回false代表拦截
    }

    //在目标方法执行之后,视图返回之前执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        modelAndView.addObject("name","mvc");
        System.out.println("postHandle1111111");

    }

    //在整个流程都执行完毕后执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion1111111111");
    }
}
  1. 配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 对哪些资源进行拦截操作 -->
        <mvc:mapping path="/target"/>
        <!-- 排除哪些资源进行拦截 -->
        <mvc:exclude-mapping path="/login"/>
        <bean class="cn.mvc.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

注意

1. 多个拦截器组成InterceptorChain时,配置在前的先执行;
2. 拦截器方法的执行顺序:preHandler-------目标资源----postHandle---- afterCompletion
方法名说明
preHandle()方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的,当返回false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true时就会继续调用下一个interceptor的preHandler方法
postHandle()当preHandle方法返回true之后会被调用,它执行在目标资源执行完之后,DispatcherServlet进行视图渲染之前。常用于对Controller处理之后的ModlAndView对象操作
afterCompletion该方法执行在整个请求结束之后,前提是preHandle方法的返回值为true

六、 SpringMVC异常处理

1. 异常处理的思路

系统中异常包括两类:预期异常和运行时异常,预期异常通过捕获异常从而获取异常信息,而运行时异常主要通过规范代码开发、测试等手段减少运行时异常的发生。
系统的Dao、Service、Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理。

2. 简单异常处理器SimpleMappingExceptionResolver

SpringMVC已经定义好了该异常处理器,在使用时可以根据项目情况进行相应异常与视图的映射配置

<!--配置简单映射异常处理器-->
    <bean class=“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>    <property name=“defaultErrorView” value=“error”/>   <!--默认错误视图-->
    <property name=“exceptionMappings”>
        <map>		<!--key是异常类型-->		      <!--value是错误视图-->
            <entry key="com.itheima.exception.MyException" value="error"/>
            <entry key="java.lang.ClassCastException" value="error"/>
        </map>
    </property>
</bean>

3. 自定义异常处理步骤

  1. 创建异常处理器类实现HandlerExceptionResolver
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, 
    HttpServletResponse response, Object handler, Exception ex) {
    //处理异常的代码实现
    //创建ModelAndView对象
    ModelAndView modelAndView = new ModelAndView(); 
    modelAndView.setViewName("exceptionPage");
    return modelAndView;
    }
}
  1. 配置自定义异常处理器
<bean id="exceptionResolver" class="com.itheima.exception.MyExceptionResolver"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值