控制器Controller:

  • 控制器提供复杂访问应用程序的行为,通常通过实现接口定义或注解定义两种方式实现
  • 解析处理用户的请求并将结果返回给DispatcherServlet
定义控制器Controller的两种常用方式:
① 实现Controller接口:

实现org.springframework.web.servlet.mvc.Controller接口,并重写handleRequest方法:

首先创建一个项目,编写web.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">

    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--绑定SpringMVC的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC-servlet.xml</param-value>
        </init-param>
        <!--启动级别-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

再创建springMVC-servlet.xml文件:

<?xml version="1.0" encoding="UTF8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
    <context:component-scan base-package="controller" />
    <!--过滤静态资源,让SpringMVC不处理静态资源,如.css、.js等等-->
    <mvc:default-servlet-handler />
    <!--支持MVC注解驱动,在Spring一般采用@RequestMapping注解来完成映射关系-->
    <!--要想使@RequestMapping注解生效,-->
    <!--必须向上下文中注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例-->
    <!--这两个实例分别在类级别和方法级别处理,而annotation-driven配置帮助我们自动完成上述两个实例的配置注入 -->
    <mvc:annotation-driven />

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <!--后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

创建一个ControllerTest1类实现Controller接口:

package controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 实现Controller接口获得控制器功能
public class ControllerTest1 implements Controller {
    @Override
    // 处理请求并返回一个ModelAndView对象,包含数据和视图信息
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        // 封装数据对象
        modelAndView.addObject("msg","Controller Test 1");
        // 封装要跳转的页面,会被视图解析器处理
        modelAndView.setViewName("test");
        return modelAndView;
    }
}

然后去springMVC-servlet.xml文件注册bean,id对应请求的映射路径,class对应处理请求的控制类

<bean id="/t1" class="controller.ControllerTest1"></bean>

编写一个test.jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>${msg}</h3>
</body>
</html>

启动Tomcat测试:
在这里插入图片描述

  • 实现Controller接口定义控制器是一个比较老的方式
  • 缺点:一个控制器类只有一个处理请求的方法,如果有多个不同的请求则需要定义创建多个Controller
  • 通过Controller接口定义控制器此时springMVC-servlet.xml文件只要配置视图解析器和控制类的Bean即可
② 使用注解 @Controller:

@Controller放在类上用来声明这个类是一个控制器,此时不需要重写方法

Spring使用扫描机制找到应用程序中所有基于注解的控制器类,所以要在配置文件springMVC-servlet.xml中声明组件扫描:

<!--自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
<context:component-scan base-package="controller" />

还要配置静态资源过滤和注解支持驱动:

<!--过滤静态资源,让SpringMVC不处理静态资源,如.css、.js等等-->
<mvc:default-servlet-handler />
<!--支持MVC注解驱动,在Spring一般采用@RequestMapping注解来完成映射关系-->
<mvc:annotation-driven />

创建一个ControllerTest2:

@Controller // 代表这个类被Spring托管
public class ControllerTest2 {
    @RequestMapping("/t2") // 指定请求映射路径为 /t2
    public String test1(Model model){
    	// 封装数据对象
        model.addAttribute("msg","Controller Test 2");
        return "test"; // 视图名字,即要跳转的页面,会被视图解析器拼接前缀后缀处理
    }
}

此时就可以直接启动Tomcat测试了:
在这里插入图片描述

  • @Controller:标志这个类为一个控制器类,被这个注解的类中所有的方法,如果返回值是String,那么就会被视图解析器解析处理
  • @RequestMapping("/t2"):表示请求映射路径 /t2 会映射到该方法上。@RequestMapping注解用于映射URL到控制器类或处理程序方法上,可放在类上也可放在方法上,用于类上,表示类中的所有请求方法都是以该地址作为父路径

上面ControllerTest2就是@RequestMapping用在方法上,现在举例说明@RequestMapping用在类上:

@Controller
@RequestMapping("/c3")
public class ControllerTest3 {
    @RequestMapping("/t2") // 此时请求映射路径为 /c3/t2
    public String test1(Model model){
        // 封装数据对象
        model.addAttribute("msg","Controller Test 3");
        return "test"; // 视图名字,即要跳转的页面,会被视图解析器拼接前缀后缀处理
    }
}

此时仅请求 /t2 还是走的ControllerTest2中的方法:
在这里插入图片描述
只有请求 /c3/t2 才会运行ControllerTest3中的处理程序方法:
在这里插入图片描述

转发与重定向:

① 通过Servlet API:

Controller类可以拿到HttpServletRequest、HttpServletResponse对象,所以可以通过Servlet API实现:

  • 通过HttpServletRequest进行转发
  • 通过HttpServletResponse进行重定向

此时不需要视图解析器,因为不会经过视图解析器

@Controller
public class ControllerTest4 {
    @RequestMapping("/c4/t1")
    public void test1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }
    @RequestMapping("c4/t2")
    public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.sendRedirect("/sendRedirect.jsp");
    }
}
② 通过Spring MVC:
@Controller
public class ControllerTest5 {
    @RequestMapping("/c5/t1")
    public String test1(Model model){
        model.addAttribute("msg","Spring MVC");
        return "test"; // 转发,会被视图解析器处理
    }

    @RequestMapping("/c5/t2")
    public String test2(){
        return "forward:/index.jsp"; // 转发,不会被视图解析器处理
    }

    @RequestMapping("c5/t3")
    public String test3(){
        return "redirect:/sendRedirect.jsp"; // 重定向,不会被视图解析器处理
    }
}
  • 通过在视图名字前添加" forward:" 和" redirect:" 来实现转发和重定向,此时不会经过视图解析器,所以视图名必须是全限定名
  • 不加forward直接返回视图名也是一种转发,但此时会被视图解析器拼接前缀后缀处理
  • 重定向不能直接访问WEB-INF目录下的资源

或者这样编写,效果与上面一样:

@Controller
public class ControllerTest5 {
    @RequestMapping("/c5/t1")
    public ModelAndView test1(ModelAndView model){
        model.addObject("msg","Spring MVC");
        model.setViewName("test"); // 转发,会被视图解析器处理
        return model;
    }

    @RequestMapping("/c5/t2")
    public ModelAndView test2(ModelAndView model){
        model.setViewName("forward:/index.jsp"); // 转发,不会被视图解析器处理
        return model;
    }

    @RequestMapping("c5/t3")
    public ModelAndView test3(ModelAndView model){
        model.setViewName("redirect:/sendRedirect.jsp"); // 重定向,不会被视图解析器处理
        return model;
    }
}
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐