SpringMVC 6:SpringMVC注解

※ 基于注解的SpringMVC

    1)用于支持注解的配置
        使用基于注解的配置可以省略很多操作,更方便。我们之前所看到的所有的xml配置,如果替换成基于注解只需要在spring的xml文件中做如下配置:
        <mvc:annotation-driven/>
        
        在Spring中,
        处理器列可以使用   @Controller注解
        业务逻辑层可以使用 @Service注解
        数据持久层可以使用 @Repository注解

        如果在处理器上使用 @Controller注解,那么还需要在配置文件中指定哪个包下面的类使用了该注解:
      

 <context:component-scan base-package="com.briup.web.controller"></context:component-scan>


    2)基于注解的Controller
        使用注解后,就不需要再实现特定的接口,任意一个javaBean对象都可以当做处理器对象,对象中任意一个方法都可以作为处理器方法。
        只需
            在类上加上 @Controller注解
             方法上加上 @RequestMapping注解

        即可
        例如:
        

web.xml中:
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-web-mvc.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>
        

        src下面的spring-web-mvc.xml中:
        <mvc:annotation-driven/>
        <context:component-scan base-package="com.briup.web.controller"></context:component-scan>
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
            <property name="prefix" value="/WEB-INF/jsp/"/>  
            <property name="suffix" value=".jsp"/>  
        </bean>


        自定义的Controller中:
        @Controller
        public class HomeController {
            @RequestMapping("/home")
            public ModelAndView home(){
                ModelAndView mv = new ModelAndView("index");
                return mv;
            }
        }


        如上代码,使用 @Controller表明HomeController类是一个处理器类,
        通过 @RequestMapping("/home")表明当url请求名为/home时,调用home方法执行处理,
    当处理完成之后返回ModelAndView对象。因为在spring-web-mvc.xml中配置了视图解析器的前缀和后缀,所以最后视图home.jsp被返回
    

    3)基于注解的Controller的返回值
        1.返回ModelAndView,和之前一样

        2.返回String,表示跳转的逻辑视图名字,模型可以通过参数传过来
          

            @Controller
            public class HomeController {
                @RequestMapping("/home")
                public String home(Model model){
                    model.addAttribute("msg", "hello world");
                    return "index";
                }
            }


        
        3.声明返回类型为void
            可以通过参数获取request和response,分别使用服务器内部跳转和重定向,自己来决定要跳转的位置。
          

            @Controller
            public class HomeController {
                @RequestMapping("/home")
                public void home(HttpServletRequest request,HttpServletResponse response){
                    String username = request.getParameter("username");
                    response.setContentType("text/html;charset=utf-8");
                    response.getWriter().write("hello world! "+username);
                    //或者使用servlet的方式进行跳转/重定向
                    
                }
            }
配置文件:

<?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"
      xmlns:context="http://www.springframework.org/schema/context"
      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
          ">
          <!-- 对springMVC中注解的支持
          识别注解 -->
          <mvc:annotation-driven></mvc:annotation-driven>
          <!-- 扫描注解的类有哪些 -->
          <context:component-scan 
          base-package="com.briup.web.annotation"></context:component-scan>
          <!-- 视图解析器 -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
			<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
			<property name="prefix" value="/WEB-INF/jsp/"/>  
			<property name="suffix" value=".jsp"/>  
		</bean> 
		<!-- 返回页面(视图)
		path指的是项目名字后面的资源名称
		view-name 逻辑视图名,前提:当前配置了
		视图解析器
		没有视图解析器,物理视图的路径名字
		 -->
		<mvc:view-controller path="/login" view-name="login"/>
		<!-- 对静态资源的处理 
		SpringMVC处理xx.js,xxx.css,xxx.png等资源不做
		二次拦截
		-->
		<mvc:default-servlet-handler/>
</beans>




注解Controller:

package com.briup.web.annotation;

import java.io.IOException;
import java.io.PrintWriter;

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

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/*
 * @Controller表示控制器
 */
@Controller
public class HomeController {
	//http://localhost:8888/jd1812_MVC/home
	/*@RequestMapping对应的
	 * 就是资源名称
	 */
	@RequestMapping("/home")
	public ModelAndView test(){
		ModelAndView mv=
					new ModelAndView();
		System.out.println("home.......");
		mv.setViewName("hello");
		return mv;
	}
	@RequestMapping("/home1")
	public ModelAndView test1(HttpServletRequest req,HttpServletResponse res){
		try {
			PrintWriter pw=res.getWriter();
			pw.println("test...");
			pw.flush();
			pw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	/*
	 * 方法的返回值是String类型
	 * 返回值表示视图
	 * spring文件配置视图解析器
	 * 返回视图是逻辑视图名子
	 * spring文件没有配置视图解析器
	 * 返回视图是物理视图名子
	 */
	@RequestMapping("/home2")
	public String test2(){
		return "hello";
	}
	@RequestMapping("/home3")
	public String test3(Model model){
		model.addAttribute("name", "jake...ok");
		return "hello";
	}
	@RequestMapping("/home4")
	public void test4(HttpServletResponse res){
		try {
			PrintWriter pw=
					res.getWriter();
			pw.println("tom...ok");
			pw.flush();
			pw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

※ .Spring2.5中引入注解对处理器(headler)支持


    @Controller
        用于标识是处理器类;
    @RequestMapping
        请求到处理器功能方法的映射规则;
    @RequestParam
        请求参数到处理器功能处理方法的方法参数上的绑定;
    @ModelAttribute
        请求参数到命令对象的绑定;
    @SessionAttributes
        用于声明session 级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session 中
    @InitBinder
        自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;


※.Spring3引入了更多的注解,其中包含了对RESTful架构风格的支持


    @CookieValue
        cookie数据到处理器功能处理方法的方法参数上的绑定;
    @RequestHeader
        请求头数据到处理器功能处理方法的方法参数上的绑定;
    @RequestBody
        请求的body体的绑定
    @ResponseBody
        处理器功能处理方法的返回值作为响应体
    @ResponseStatus
        定义处理器功能处理方法/异常处理器返回的状态码和原因;
    @ExceptionHandler
        注解式声明异常处理器;
    @PathVariable
        请求URI 中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI;

※ .Spring3中引入的mvc命名空间

    mvc这个命名空间是在Spring3中引入的,其作用是用来支持mvc的配置
    需要在<bean>中声明出这个命名空间及其对应的schemaLocation中的值
        <mvc:annotation-driven>
        自动注册基于注解风格的处理器和适配器:
        在spring2.5中是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter

        在spring3中是RequestMappingHandlerMapping和RequestMappingHandlerAdapter.
        同时还支持各种数据的转换器.

        <mvc:interceptors>
        配置自定义的处理器拦截器,例如:
      

        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <ref bean="handlerInterceptor1"/>
            </mvc:interceptor>
        </mvc:interceptors>

        <mvc:view-controller>
        收到相应请求后直接选择相应的视图,例如:
        

<mvc:view-controller path="/hello" view-name="test"></mvc:view-controller>

        <mvc:resources>
        逻辑静态资源路径到物理静态资源路径的对应.例如:
        

        <mvc:resources mapping="/images/**" location="/images/"/>  
        <mvc:resources mapping="/js/**" location="/js/"/>  
        <mvc:resources mapping="/css/**" location="/css/"/>

   
       <mvc:default-servlet-handler>
        当在web.xml中DispatcherServlet使用<url-pattern>/</url-pattern> 映射的时候,
    会静态资源也映射了,如果配置了这个mvc标签,那么再访问静态资源的时候就转交给默认的Servlet来响应静态文件,否则报404 找不到静态资源错误。

spring配置:

<?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"
      xmlns:context="http://www.springframework.org/schema/context"
      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
          ">
          <!-- 对springMVC中注解的支持
          识别注解 -->
          <mvc:annotation-driven></mvc:annotation-driven>
          <!-- 扫描注解的类有哪些 -->
          <context:component-scan 
          base-package="com.briup.web.annotation"></context:component-scan>
          <!-- 视图解析器 -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
			<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
			<property name="prefix" value="/WEB-INF/jsp/"/>  
			<property name="suffix" value=".jsp"/>  
		</bean> 
		<!-- 返回页面(视图)
		path指的是项目名字后面的资源名称
		view-name 逻辑视图名,前提:当前配置了
		视图解析器
		没有视图解析器,物理视图的路径名字
		 -->
		<mvc:view-controller path="/login" view-name="login"/>
		<!-- 对静态资源的处理 
		SpringMVC处理xx.js,xxx.css,xxx.png等资源不做
		二次拦截
		-->
		<mvc:default-servlet-handler/>
</beans>




※ .@Controller和@RequestMapping注解

    1) 声明处理器
    

    @Controller
    public class HelloWorldController {
        
    }

    2) 映射处理器中的【功能处理方法】
  

    @Controller
    public class HelloWorldController {
        @RequestMapping("/home")
        public ModelAndView home(){
            ModelAndView mv = new ModelAndView("index");
            return mv;
        }
    }
     
    表明该方法映射的url路径为/home

 

    3) @RequestMapping也可以写在处理器类上
  

    @RequestMapping("/test")
    @Controller
    public class HomeController {
        @RequestMapping("/home")
        public ModelAndView home(){
            ModelAndView mv = new ModelAndView("index");
            return mv;
        }
    }
    表明该方法映射的url路径为/test/home

 

    注意:功能处理方法的方法可以是String类型,表示逻辑视图的名字,可以不用返回ModelAndView对象(见上面测试)
  

 例如:
    @Controller
    public class HelloWorldController {
        @RequestMapping("/home")
        public String home(){
            return "index";
        }
    }

 

※ .请求映射

    假设浏览器发送了一个请求如下:
    -------------------------------
    POST /login    HTTP1.1
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,en;q=0.8,zh;q=0.5,en-US;q=0.3
    Connection: keep-alive
    Cookie: JSESSIONID=DBC6367DEB1C024A836F3EA35FCFD5A2
    Host: 127.0.0.1:8989
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0

    username=tom&password=123
    --------------------------------


    http协议的请求格式如下:
    ---------------------------------
    请求方法 URL 协议版本号
    请求头信息
    请求头信息
    请求头信息
    ..
    回车换行
    请求正文
    ---------------------------------

    
    从格式中我们可以看到【请求方法、URL、请求头信息、请求正文】这四部分一般是可变的,
    因此我们可以把请求中的这些信息在处理器的【功能处理方法】中进行的映射,因此请求的映射分为如下几种:
        URL路径映射
            使用URL映射到处理器的功能处理方法;
        请求方式映射限定
            例如限定功能处理方法只处理GET请求;
        请求参数映射限定
            例如限定只处理包含username参数的请求;
        请求头映射限定
            例如限定只处理"Accept=application/json"的请求。


※ .URL路径映射

    1) 普通URL路径映射
        @RequestMapping(value="/test")
        @RequestMapping("/hello")
            注解中只出现一个参数且参数名为value的话,可以将参数名去掉
        @RequestMapping(value={"/test", "/user/hello"})
            多个URL路径可以映射到同一个处理器的功能处理方法。
    
    2) URI模板模式映射
        @RequestMapping(value="/users/{userId}")
            {XXX}占位符, 请求的URL可以是"/users/123456"或"/users/abcd",之后可以通过@PathVariable可以提取URI模板模式中的{XXX}中的值
        @RequestMapping(value="/users/{userId}/create")
            这样也是可以的,请求的URL可以是"/users/123/create"
        @RequestMapping(value="/users/{userId}/topics/{topicId}")
            这样也是可以的,请求的URL可以是"/users/123/topics/123"

    3) Ant风格的URL路径映射
        @RequestMapping(value="/users/**")
            可以匹配"/users/abc/abc",但"/users/123"将会被【URI模板模式映射中的"/users/{userId}"模式优先映射到】
        @RequestMapping(value="/product/?")
            可匹配"/product/1"或"/product/a",但不匹配"/product"或"/product/aa";
            ?代表有且只有一个字符
        @RequestMapping(value="/product*")
            可匹配"/productabc"或"/product",但不匹配"/productabc/abc";
            *代表0~n个字符
        @RequestMapping(value="/product/*")
            可匹配"/product/abc",但不匹配"/productabc";
        @RequestMapping(value="/products/**/{productId}")
            可匹配"/products/abc/abc/123"或"/products/123",也就是Ant风格和URI模板变量风格可混用;
            **代表所有的子路径

    4) 正则表达式风格的URL路径映射(具体参考正则类java.util.regex.Pattern;)
        从Spring3.0 开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式},之后通过@PathVariable可以提取{XXX:正则表达式匹配的值}中的XXX这个变量的值。
        @RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")
            可以匹配"/products/123-1",但不能匹配"/products/abc-1",这样可以设计更加严格的规则。
        @RequestMapping(value="/user/{userId:^\\d{4}-[a-z]{2}$}")
            可以匹配"/user/1234-ab"
        
        注意:\d表示数字,但是\在java的字符串中是特殊字符,所以需要再加一个\进行转义即可
          

            括号:
                [abc]     查找方括号之间的任何字符。
                [^abc]     查找任何不在方括号之间的字符。
                [0-9]     查找任何从 0 至 9 的数字。
                [a-z]     查找任何从小写 a 到小写 z 的字符。
                [A-Z]     查找任何从大写 A 到大写 Z 的字符。
                [A-z]     查找任何从大写 A 到小写 z 的字符。
                
            
            元字符:
                .     查找单个任意字符,除了换行和行结束符.如果要表示.这个字符,需要转义
                \w     查找单词字符。     字母 数字 _
                \W     查找非单词字符。非 字母 数字 _
                \d     查找数字。
                \D     查找非数字字符。
                

            量词:
                n+         匹配任何包含至少一个 n 的字符串。
                n*         匹配任何包含零个或多个 n 的字符串。
                n?         匹配任何包含零个或一个 n 的字符串。
                n{X}     匹配包含 X 个 n 的序列的字符串。
                n{X,Y}     匹配包含 X 到 Y 个 n 的序列的字符串。
                n{X,}     匹配包含至少 X 个 n 的序列的字符串。
                n$         匹配任何结尾为 n 的字符串。
                ^n         匹配任何开头为 n 的字符串。


        正则表达式风格的URL路径映射是一种特殊的URI模板模式映射
        URI模板模式映射不能指定模板变量的数据类型,如是数字还是字符串;
        正则表达式风格的URL路径映射,可以指定模板变量的数据类型,可以将规则写的相当复杂。

        匹配的内容包含一个数字
        @RequestMapping("/regex/{userid:\\d}")
        匹配的内容包含至少一个数字
        @RequestMapping("/regex/{userid:\\d+}”)
        匹配的内容包含3个数字
        @RequestMapping("/regex/{userid:\\d{3}}")
        匹配的内容是开始是3个数字,中间随意的字符,最后结尾1-9中的任意两个数字
        @RequestMapping("/regex/{userid:^\\d{3}.*[1-9]{2}$}")
        匹配内容是3~5个数字
        @RequestMapping("/regex/{userid:\\d{3,5}}")

        注:userid可以看做占位,冒号后面为以后填写值的格式。

注解Controller类:

package com.briup.web.annotation;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/*
 * http://localhost:8888/jd1811_MVC/user/act
 * @RequestMapping基于功能区分用的
 */
@Controller
@RequestMapping("/user")
public class ActionController {
//	@RequestMapping("/act")
//	@RequestMapping(value="/act")
	/*
	 * 多个资源请求名字对应一个处理方法
	 */
	@RequestMapping(value={"/act","test1","test2"})
	public String test(){
		return "hello";
	}
	//http://127.0.0.1:8888/jd1812_MVC/user/user/tom
	@RequestMapping("/user/{userid}")
	public String restful( String userid){
		System.out.println(userid+"------");
		return "hello";
	}
	/*@PathVariable 将restful风格中的{}占位
	 * 中的变量代表的值赋给参数
	 * 默认,restful风格中的{}占位中的变量
	 * 和参数中表示的值的变量相同
	 * 如果restful风格中的{}占位中的变量
	 * 和参数中表示的值的变量不相同
	 * 在@PathVariable指定名字(restful风格中的{}占位中的变量名)
	 * 
	 */
	@RequestMapping("/user1/{userid}")
	public String restful1(@PathVariable("userid") String username){
		System.out.println(username+"------");
		return "hello";
	}
	@RequestMapping("/user2/{userid}")
	public String restful2(@PathVariable("userid") long username){
		System.out.println(username+"------");
		return "hello";
	}
	@RequestMapping("/user3/{userid}/{passwd}")
	public String restful4(@PathVariable("userid") long username,@PathVariable String passwd){
		System.out.println(username+"------"+passwd);
		return "hello";
	}
	//http://127.0.0.1:8888/jd1812_MVC/user/user3/1222/passwd
	//http://127.0.0.1:8888/jd1812_MVC/user/user3/1222/passwd
	@RequestMapping("/user3/{userid}/passwd")
	public String restful3(@PathVariable("userid") long username){
		System.out.println(username+"------");
		return "hello";
	}
	/*
	 * http://localhost:8888/jd1812_MVC/product/
	 * 
	 * /product/*只能统配斜杠后面没有斜杆的
	 * 资源名称
	 * /product/test
	 * /product/hello
	 * /product/test/hello
	 *   *统配0到多个字符
	 *   ** 统配内容中可以出现多个斜杆
	 *   http://localhost:8888/jd1812_MVC/
	 *   	user/product/test/hello
	 */
//	@RequestMapping("/product/*")
//	@RequestMapping("/product/**")
	/*
	 * ?位置只能出现一个字符
	 */
//	@RequestMapping("/product/?")
	//http://localhost:8888/jd1812_MVC/user/productyyyyyyy
	/*
	 * 统配以product开头的资源
	 * 当时统配内容不能有斜杆
	 */
//	@RequestMapping("/product*")
	//两个*也是表示统配内容,不能出现斜杠
//	@RequestMapping("/product**")
//	public String ant(){
//		System.out.println("ant.......");
//		return "hello";
//	}
	//http://localhost:8888/jd1812_MVC
	///user/productyyyyyyy/test
	@RequestMapping("/product**/{userid}")
	public String ant(@PathVariable String userid){
		System.out.println("ant......."+userid);
		return "hello";
	}
	//http://localhost:8888/jd1812_MVC/user/regex/
//	@RequestMapping("/regex/{userid:\\d+}")
//	public String regex(@PathVariable String userid){
//		System.out.println("regex...."+userid);
//		return "hello";
//	}
//	@RequestMapping("/regex/{userid:\\d{3}}")
//	public String regex(@PathVariable String userid){
//		System.out.println("regex...."+userid);
//		return "hello";
//	}
//	@RequestMapping("/regex/{userid:\\d{3,5}}")
//	public String regex(@PathVariable String userid){
//		System.out.println("regex...."+userid);
//		return "hello";
//	}
	//regex/123test19
//@RequestMapping("/regex/{userid:^\\d{3}.*[1-9]{2}$}")
//	public String regex(@PathVariable String userid){
//		System.out.println("regex...."+userid);
//		return "hello";
//	}
	//    3232-az
//	@RequestMapping(value="/regex/{userid:^\\d{4}-[a-z]{2}$}")
//	public String regex(@PathVariable String userid){
//	System.out.println("regex...."+userid);
//	return "hello";
//	}
	@RequestMapping("/regex/{userid:[A-z]*}")
	public String regex(@PathVariable String userid){
		System.out.println("regex...."+userid);
		return "hello";
	}
//	@RequestMapping("/test/{userid}")
	/*
	 * method属性指定提交方式
	 */
//	@RequestMapping(value="/test/{userid}"
//			,method=RequestMethod.GET)
//	@RequestMapping(value="/test/{userid}"
//	,method=RequestMethod.POST)
//	@RequestMapping(value="/test/{userid}"
//	,method={RequestMethod.POST,RequestMethod.GET})
//	public String method(@PathVariable String userid,String username){
//		System.out.println(username+"&&&"+userid);
//		return "hello";
//	}
	@RequestMapping(value="/test1"
			,method=RequestMethod.POST)
	public String method(@PathVariable String userid,String username){
		System.out.println(username+"&&&"+userid);
		return "hello";
	}
	@RequestMapping(value="/test1"
			,method=RequestMethod.GET)
	public String method1(@PathVariable String userid,String username){
		System.out.println(username+"&&&"+userid);
		return "hello";
	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值