Spring框架(四)——SpringMVC

一、概述

SpringMVC是基于MVC思想实现的web开发框架。可以用来替代Servlet的使用。

SpringMVC的优点:

1)简化Servlet的繁琐操作;
2)基于组件设计。ViewResolver urlmapper
3)springmvc支持不同视图技术,jsp、html、freemarkder等等
4)很方便与ajax进行数据交互。jackson List Map等等

二、运行原理

  1. 当用户发起请求的时候,首先该请求会被前端控制器(DispatcherServlet)拦截;
  2. 前端控制器会调用HandlerMapping组件根据请求路径生成一个Handler对象,并返回给前端控制器;
  3. 前端控制器调用HandlerAdapter组件执行Handler;
  4. Handler返回一个ModelAndView给前端控制器;
  5. 前端控制器获取到ModelAndView对象后,就会调用ViewResolver组件根据viewName把对应的视图页面加载出来。加载出来后进行数据渲染,渲染完成最后把页面的内容发送给浏览器显示。
    在这里插入图片描述

三、SpringMVC组件

3.1 HandlerMapping组件

SimpleUrlHandlerMapping:该处理器是根据请求URL来匹配Bean的id属性。

BeanNameUrlHandlerMapping:该处理器根据请求名来查找匹配的Bean。

ControllerClassNameHandlerMapping:该处理器是根据请求名和Controller的类名进行匹配。请求名就是Controller类名,然后把Controller去掉的名字。例如:HelloController -> /hello*。


3.2 Handler组件

UrlFilenameViewController:把请求名直接转换成视图名,并返回该视图。

ParameterizableViewController:该控制器总是返回一个预定义的视图。

ServletForwardingController:把请求转发给一个Servlet来处理。

MultiActionController:该处理器允许在一个Controller中处理多个请求。


3.3 Resolver组件

InternalResourceViewResolver:把JSP解析成View对象。
PropertiesMethodNameResolver:根据指定的请求URL适配指定的方法。
InternalPathMethodNameResolver:根据请求的URL自动适配相应的方法。
StandardServletMultipartResolver:文件上传解析器

四、入门示例

第一步:
下载jar包:Spring
或者使用Maven下载依赖包

<dependencies>
    <!--Spring依赖包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.9.RELEASE</version>
    </dependency>
    <!--Spring-web包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.9.RELEASE</version>
    </dependency>
    <!--Spring-webMVC包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.9.RELEASE</version>
    </dependency>
    <!-- servlet依赖的jar包 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
    <!-- jsp依赖jar包 -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
    </dependency>
    <!--jstl标签依赖的jar包 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
</dependencies>

第二步:
配置tomcat服务器,具体操作见:
IDEA之配置和使用Tomcat

第三步:
在web.xml配置核心控制器

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!-- 配置Spring的核心控制器 -->
  <servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

第四步:
创建一个类,实现Controller接口,并重写handleRequest方法

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        System.out.println("进入到Hello控制器中");
        ModelAndView mv = new ModelAndView();
        mv.setViewName("hello"); // 设置视图名
        return mv;
    }
}

第五步:
在WEB-INF目录下新建SpringMVC配置文件
在这里插入图片描述
配置文件名称格式为“控制器名(web.xml中配置的核心控制器名字)-servlet.xml”

配置文件内容如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!--配置控制器类-->
    <bean id="hello" class="com.tung.HelloWorld.controller.HelloController"/>

    <!-- 定义URL匹配器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="sayHello.do">hello</prop>
            </props>
        </property>
    </bean>

    <!-- 配置结果解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

第六步:
在WEB-INF/jsp目录下新建一个jsp文件,文件内容如下:

<h2>Hello World!</h2>

第七步:
启动Tomcat服务器,然后在浏览器上输入地址http://localhost:8080/sayHello.do

五、SpringMVC注解

5.1 常用注解

注解名作用范围功能
@Controller在类上使用标注该类是一个控制器类
@RequestMapping可以在类上使用,也可以在方法上使用指定请求的url路径
@RequestParam在形参中使用用于指定参数名
@PathVariable在形参中使用处理请求url中的占位参数
@ResponseBody在方法上使用把方法的返回值内容输出到页面上
@SessionAttributes在类上使用把model中指定名字或类型的属性绑定到session
@ModelAttribute在形参中使用从session中获取数据,并且绑定到指定参数中。

5.2 环境准备

在src目录下创建Spring的配置文件applicationContext.xml,并启用注解和包扫描功能。

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      					 http://www.springframework.org/schema/beans/spring-beans.xsd
      					 http://www.springframework.org/schema/context
      					 http://www.springframework.org/schema/context/spring-context.xsd
      					 http://www.springframework.org/schema/mvc
      					 http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 启动注解功能 -->
    <mvc:annotation-driven/>

    <!-- 启用包扫描功能 -->
    <context:component-scan base-package="com.tung.HelloWorld.controller"/>

</beans>

六、中文乱码问题

提交表单数据时,浏览器会使用页面编码UTF-8进行编码,而服务器使用默认的字符集(iso-8859-1)进行解码。因为编码和解码使用了不同的字符集,才导致了获取的参数出现中文乱码的问题。

一般有两种办法解决中文乱码问题:

6.1 手动解决

对数据进行字符集转换

name = new String(name.getBytes("iso-8859-1"), "utf-8");

6.2 全局处理

在web.xml文件中配置CharacterEncodingFilter过滤器,该过滤器用于处理所有请求的中文乱码问题。

<!-- 处理中文乱码的过滤器 -->
<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>
    <init-param>  
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>  
    </init-param>
</filter>
<filter-mapping>    
    <filter-name>CharacterEncodingFilter</filter-name>    
    <url-pattern>/*</url-pattern>    
</filter-mapping>

注意:在实际开发中,应该使用全局的方式来处理请求的中文乱码。

使用过滤器可能导致web.xml报红,那是因为我是用maven创建的,默认使用的是Servlet2.3模板,最后将头部改成Servlet3.1的就好了

<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_3_1.xsd"
          version="3.1">

6.3 响应中有中文乱码

如果响应内容包含中文,那么可以在@RequestMapping注解中使用produces属性来指定响应数据的编码格式。

@RequestMapping(value = "/{id}/del.do",method = RequestMethod.GET,produces = {"text/html;charset=utf-8"})

七、请求路径的优先级

@Controller
@RequestMapping("/hello")
public class hello{
	@RequestMapping("/test.do")
	public String test1(){
		return "test1...";
	}
	
	@RequestMapping("/*.do")
	public String test2(){
		return "test2...";
	}
	
	@RequestMapping("/test*.do")
	public String test3(){
		return "test3...";
	}
}

当访问路径http://localhost:8080/hello/test.do时,匹配顺序为:*test.do > test.*.do> .do
匹配成功则不会继续匹配。

八、参数传递

springmvc使用model对象来传递数据。例如:

@RequestMapping(value = "/sayHi")
    public String sayHi(Model model){
        // 使用model传递数据
        model.addAttribute("name", "aabbcc");
        // 返回视图名
        return "hello";
    }

上面方法返回视图名,对应着hello.jsp页面。页面内容如下:

<%--
  Created by IntelliJ IDEA.
  User: ss
  Date: 2021/2/18
  Time: 16:09
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html>
<head>
    <title>Title</title>
</head>
<body>
<h1>欢迎${name}回来!</h1>
</body>
</html>

效果如下:
在这里插入图片描述

九、方法返回值

控制器方法可以返回不同类型的数据。除了ModelAndView类型以外,还可以是String类型,代表视图名。例如:

@RequestMapping(value = "/sayHi")
    public String sayHi(){
        // 返回视图名
        return "hello";
    }

如果需要请求重定向到其他页面,那么返回的字符串需要以“redirect:/”开头(只能够重定向到该项目下的其他资源)

@RequestMapping(value = "/index")
    public String toIndex(){
        // 返回视图名
        return "redirect:/index";
    }

想重定向到站外资源

return new ModelAndView(new RedirectView("http://www.baidu.com"));

如果model中包含数据,那么这些数据就会添加到重定向URL的后面;

返回结果类型也可以是集合类型、void或null。如果返回结果是集合、void、null,那么请求路径的名字作为视图名被解析。例如:资源路径为/test.do,则会跳转到/test.jsp;

十、日期类型处理

从页面提交表单时,表单上的日期数据与控制器中的Date参数并不一样,需要进行特殊处理;

10.1 @DateTimeFormat

使用@DateTimeFormat指定转换格式

@RequestMapping(value = "/getDate")
    @ResponseBody
    public String GetData(@DateTimeFormat(pattern = "yyyy-MM-dd") @RequestParam("date1") Date date){
        System.out.println(date);
        return "<h1>数据传递成功!</h1>";
    }

10.2 控制器中初始化

在控制器中使用绑定初始化方法,每次进入控制器对日期数据进行格式化

//绑定初始化方法处理日期格式
@InitBinder
 public void init(WebDataBinder binder){
     System.out.println("执行Init方法...");
     //设置日期格式
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
     binder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,true));
 }

10.3 全局日期类型转换器

定义一个日期转换器类,该类实现Converter接口

//全局日期类型转换器
public class DateConverTer implements Converter<String,Date> {
    @Override
    public Date convert(String date) {
        //设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try{
            return sdf.parse(date);
        }catch (ParseException e){
            e.printStackTrace();
        }
        return null;
    }
}

在Spring的配置文件applicationContext.xml配置转换器

<!--配置转换器-->
    <bean id="con" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.tung.HelloWorld.converter.DateConverTer"/>
            </list>
        </property>
    </bean>

注意:得在启动注解功能的标签中设置conversion-service为转换器的id(下图中的"con")

<!-- 启动注解功能 -->
<mvc:annotation-driven conversion-service="con"/>

十一、异常处理

在项目开发的过程中,我们难免会遇到不可避免或不可预知的异常需要处理。每个异常都要处理的话,系统代码耦合度太高,为了提供维护效率,我们需要统一进行异常处理。

下面介绍三种异常处理方式:

11.1 自带的异常处理器

在Spring的配置文件applicationContext.xml中配置异常处理器

<!-- 配置异常处理器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!--
            配置默认错误处理页
                value:视图的名称
        -->
        <property name="defaultErrorView" value="error"/>
        <!-- 对指定异常类型进行处理 -->
        <property name="exceptionMappings">
            <props>
                <!-- key代表异常类型,value代表视图名 -->
                <prop key="java.lang.RuntimeException">error</prop>
            </props>
        </property>
    </bean>

11.2 异常处理器

创建一个异常处理类,实现HandlerExceptionResolver接口

public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        //输出异常信息
        e.printStackTrace();
        return mv;
    }
}

在配置文件中配置该类

<!-- 配置异常处理类-->
<bean class="com.tung.HelloWorld.errorHandler.MyExceptionHandler"/>

11.3 @ExceptionHandler

在控制器类中定义一个异常处理的方法,并且使用@ExceptionHandler注解标注该方法

@ExceptionHandler
public String handleException(HttpServletRequest request,Exception ex){
    return "error";
}

方法中的两个参数:
request:当前发生异常的请求;
ex:异常对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值