前言

前一篇使用了非注解的方法配置构建了一个简单的SpringMVC程序,因为每个Handler对应一个方法,我们实现Controller接口时就需要重写相对应的方法,使用注解就可以快速实现多个方法。

使用注解开发

1、创建一个空的module,导入依赖,配置web.xml

  1. <!--注册DispatcherServlet-->
  2. <servlet>
  3. <servlet-name>springmvc</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
  6. <init-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:springmvc-servlet.xml</param-value>
  9. </init-param>
  10. <!--启动级别-1:启动优先级-->
  11. <load-on-startup>1</load-on-startup>
  12. </servlet>
  13. <!--/ 获取所有的请求;(不包括.jsp)-->
  14. <!--/* 获取所有的请求;(包括.jsp)-->
  15. <servlet-mapping>
  16. <servlet-name>springmvc</servlet-name>
  17. <url-pattern>/</url-pattern>
  18. </servlet-mapping>

2、配置web.xml中关联的springmvc配置文件springmvc-servlet.xml

与非注解的开发操作相比减少了处理映射器和处理适配器,使用代替,会自动注册BeanNameUrlHandlerMapping与SimpleControllerHandlerAdapter两个bean,是spring MVC为@Controllers分发请求所必须的,解决了@Controller注解使用的前提配置,保留了视图解析器。

<?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: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/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 让Spring MVC不处理静态资源-->
    <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 name="suffix" value=".jsp" />
    </bean>

</beans>

3、创建要进行操作的包,并在springmvc配置文件中配置出自动扫描

配置了标签后,IOC容器可以自动去扫描base-pack所指定的包或其子包下面的java类文件,如果扫描到有注解修饰的Java类,则将这些类注册为容器中的bean。

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

4、使用注解编写一个方法

使用@Controller注解就定义了它是一个控制器的类,执行完后就会返回一个ModelAndView给视图解析器。@RequestMapping映射请求路径,此处在方法上有注解映射所以访问时应为/hello,方法返回结果为test,与配置文件中的配置的前后缀进行拼接完整路径为:WEB-INF/jsp/test.jsp。

package...
import...

@Controller
public class AnnotationController {

    @RequestMapping("/hello")
    public String ShowMaV(Model model){

        model.addAttribute("msg","Hello,AnnotationController!");

        return "test";
    }
}

5、视图复用

既然使用注解后就已经承认它是一个控制器的类,那么我就可以使用不同的注解映射对不同的方法进行注解然后跳转访问同一个jsp页面。如两个不同的方法映射为/test和/test1,方法返回结果都是test,拼接出的完整路径都为:WEB-INF/jsp/test.jsp,但显示的内容不同,可以看出视图是复用的。
注:@RequestMapping可以写在方法上或类上,写在类上时就表示这个地址是所有的响应的父类地址,若启用第五行,则两个方法的映射地址为:/ftest/test。可直接在类中的方法上写死@RequestMapping(“/ftest/test”)可避免当类中方法过多审查时漏掉类上的注解@RequestMapping。

package...
import...

@Controller
//@RequestMapping("/ftest")
public class ControllerTest1 {

    @RequestMapping("/test")
    public String test(Model model){
        model.addAttribute("msg","This is controller test!");
        return "test";
    }

    @RequestMapping("/test1")
    public String test1(Model model){
        model.addAttribute("msg","This is controller test1!");
        return "test";
    }

}

6、页面跳转

页面跳转:根据ModelAndView对象中setViewName()方法所指定的view名称和视图解析器跳转到指定页面。实现页面跳转还可以使用重定向和转发。既然可以使用重定向和转发进行页面跳转那么就代表我们可以舍去视图解析器。测试前注释掉视图解析器。
运行后使用地址”/modelTest”可以正常显示test.jsp页面,且url不变,所以默认跳转方式是转发。我们也可以在跳转页面前添加 forward: 前缀来声明这是一个转发,同样的重定向也可以通过添加前缀 redirect: 来声明。
注:使用视图解析器和不使用视图解析器进行编写时注意路径问题

package...
import...

@Controller
public class ModelTest {

    @RequestMapping("/modelTest")
    public String test(Model model){
        model.addAttribute("msg","Model Test!");
        return "/test";
    }

    @RequestMapping("/modelTest1")
    public String test1(Model model){
        model.addAttribute("msg","Forward Model Test!");
        return "forward:/index.jsp";
    }

    @RequestMapping("/modelTest2")
    public String test2(){
        return "redirect:/index1.jsp";
    }
}

7、RestFul风格

RestFul是一种资源操作的风格,传统的资源操作通过不同的参数实现不同的功能;但RestFul可以使用不同的请求方式来实现不同的功能。
@PathVariable可以让方法的参数值绑定到url变量中
image.png
浏览器默认请求方式为Get,使用post请求需要其他jsp页面中转请求。@GetMapping()是一个组合注解,是@RequestMapping(value = “/test1”,method = {RequestMethod.GET})的快捷方式

package...
import...

@Controller
public class ControllerTest1 {

    @RequestMapping("/test")
    public String test(Model model){
        model.addAttribute("msg","This is controller test!");
        return "test";
    }

    @RequestMapping(value = "/test1",method = {RequestMethod.GET})
    public String test1(Model model){
        model.addAttribute("msg","This is controller test1!");
        return "test";
    }

    @GetMapping("/test2/{a}/{b}")
    public String test2(@PathVariable int a,@PathVariable int b, Model model){
        int result = a + b;
        model.addAttribute("msg","GetMapping结果为:"+result);
        return "test";
    }

    @RequestMapping(value = "/test3/{a}/{b}",method = {RequestMethod.POST})
    public String test3(@PathVariable int a, @PathVariable String b,Model model){
        String result = a + b;
        model.addAttribute("msg","RequestMapping规定Post提交结果为:"+result);
        return "test";
    }

    @PostMapping("/test4/{a}/{b}")
    public String test4(@PathVariable int a, @PathVariable String b, Model model){
        String result = a + b;
        model.addAttribute("msg","PostMapping结果为:"+result);
        return "test";
    }
}
<form action="/springmvc_03_controller_war_exploded/test4/1/1" method="post">
    <input type="submit">
</form>