spring的注解和配置信息(不全)


Spring配置文件详解:
在使用 <mvc:annotation-driven />标签配置时,默认配置了 RequestMappingHandlerAdapter
当两种标签都没有的时候,框架默认注册的有AnnotationMethodHandlerAdapter这个bean,所以能够处理@RequestMapping这个注解,但是只配置了<mvc:default-servlet-handler/>时所注册的三个bean都不能处理@RequestMapping注解,因此无法找到相应的Controller,进而无法进行访问路径的映射,当两种标签都有的时候,<mvc:annotation-driven/>会注册一个RequestMappingHandlerAdapter的bean,这个bean能够处理@RequestMapping这个注解。当只配置了 <mvc:annotation-driven/>时, SpringMVC会遇到静态资源无法加载的问题。 问题来源于在web.xml中的对spring的DispatcherServlet采用了如下配置,即url-pattern设置为了“/”,这样便要求SpringMVC处理所有的浏览器请求。 SpringMVC处理客户请求通常是在controller类中使用@RequestMapping注解,显然这个方法无法用于静态资源,所以就会出现静态资源无法获取的404错误。
  这种情况下浏览器的jsp请求能够成功是以为Tomcat容器默认配置了jsp Servlet,由于Tomcat的url-pattern是“.jsp”,属于扩展名匹配,优先级高于“/”匹配,所以jsp Servlet会被容器调用,不会出现jsp资源无法获取的问题。

spring <context:component-scan>使用说明(转) ———>取代 <context:annotation-config/>
   在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean
注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context: component - scan />还提供了两个子标签
1.        <context:include-filter>
2.       <context:exclude-filter>
在说明这两个子标签前,先说一下<context:component-scan>有一个use-default-filters属性,改属性默认为true,这就意味着会扫描指定包下的全部的标有@Component的类,并注册成bean.也就是@Component的子注解@Service,@Reposity等。所以如果仅仅是在配置文件中这么写
<context:component-scan base-package= "tv.huan.weisp.web" />
 Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。
 
 可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?此时子标签<context:incluce-filter>就起到了勇武之地。如下所示
<context:component-scan base-package="tv.huan.weisp.web .controller">  
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  
这样就会只扫描base-package指定下的有@Controller下的java类,并注册成bean
但是因为use-dafault-filter在上面并没有指定,默认就为true,所以当把上面的配置改成如下所示的时候,就会产生与你期望相悖的结果(注意base-package包值得变化)
<context:component-scan base-package="tv.huan.weisp.web ">  
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
</context:component-scan>  
此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类
此时指定的include-filter没有起到作用,只要把use-default-filter设置成false就可以了。这样就可以避免在base-packeage配置多个包名这种不是很优雅的方法来解决这个问题了。
另外在我参与的项目中可以发现在base-package指定的包中有的子包是不含有注解了,所以不用扫描,此时可以指定<context:exclude-filter>来进行过滤,说明此包不需要被扫描。综合以上说明
Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描

<mvc:annotation-driven />注解意义

特别是下面那段英文很重要,我就曾经遇到过加入了jackson的core和mapper包之后竟然不写配置文件也能自动转换成json,我当时很费解。原来是
<mvc:annotation-driven />这个东西在起作用。
<mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。

并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示

Spring的注解详解:

-——>@RequestMapping :

1.@RequestMapping注解是 用来处理前端请求地址映射的,注解 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

2. @RequestMapping 属性  
value:     指定请求的实际地址,指定的地址可以是URI Template 模式
method:  指定请求的method类型, GET、POST、PUT、DELETE等;
GET一般用于 获取/查询 资源信息,而POST一般用于 更新 资源信息。

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

params: 指定request中必须包含某些参数值是,才让该方法处理。

headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

详细解说:
-------> 使用 @RequestMapping 来映射 Request 请求与处理器

如:
@Controller
@RequestMapping ( "/test/{variable1}" )
public class MyController {

    @RequestMapping ( "/showView/{variable2}" )
    public ModelAndView showView( @PathVariable String variable1, @PathVariable ( "variable2" ) int variable2) {
       ModelAndView modelAndView = new ModelAndView();
       modelAndView.setViewName( "viewName" );
       modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " );
       return modelAndView;
    }
}

代码中我们定义了两个URI 变量,一个是控制器类上的variable1 ,一个是showView 方法上的variable2 ,然后在showView 方法的参数里面使用 @PathVariable  标记使用了这两个变量。所以当我们使用/test/hello/showView/2.do 来请求的时候就可以访问到MyController 的showView 方法,这个时候variable1 就被赋予值hello ,variable2 就被赋予值2 ,然后我们在showView 方法参数里面标注了参数variable1 和variable2 是来自访问路径的path 变量,这样方法参数variable1 和variable2 就被分别赋予hello 和2 。方法参数variable1 是定义为String 类型,variable2 是定义为int 类型,像这种简单类型在进行赋值的时候Spring 是会帮我们自动转换的

注: 在上面的代码中我们可以看到在标记variable1 为path 变量的时候我们使用的是@PathVariable ,而在标记variable2 的时候使用的是@PathVariable(“variable2”) 。这两者有什么区别呢? 第一种情况就默认去URI 模板中找跟参数名相同的变量,但是这种情况只有在使用debug 模式进行编译的时候才可以,而第二种情况是明确规定使用的就是URI 模板中的variable2 变量。当不是使用debug 模式进行编译,或者是所需要使用的变量名跟参数名不相同的时候,就要使用第二种方式明确指出使用的是URI 模板中的哪个变量。

----------->使用 @RequestMapping 的一些高级用法

(1) params属性
@RequestMapping (value= "testParams" , params={ "param1=value1" , "param2" , "!param3" })
    public String testParams() {
       System. out .println( "test Params..........." );
       return "testParams" ;
    }
用@RequestMapping 的params 属性指定了三个参数,这些参数都是针对请求参数而言的,它们分别表示参数param1 的值必须等于value1 ,参数param2 必须存在,值无所谓,参数param3 必须不存在,只有当请求/testParams.do 并且满足指定的三个参数条件的时候才能访问到该方法。所以当请求/testParams.do?param1=value1&param2=value2 的时候能够正确访问到该testParams 方法,当请求/testParams.do?param1=value1&param2=value2&param3=value3 的时候就不能够正常的访问到该方法,因为在@RequestMapping 的params 参数里面指定了参数param3 是不能存在的。

(2)method属性
@RequestMapping (value= "testMethod" , method= {RequestMethod. GET , RequestMethod. DELETE })
    public String testMethod() {
       return "method" ;
    }
在上面的代码中就使用method 参数限制了以GET 或DELETE 方法请求/testMethod 的时候才能访问到该Controller 的testMethod 方法。
(3)headers属性
@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })
    public String testHeaders() {
       return "headers" ;
    }
headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息,且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。

————>@Resource和@Autowired

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。 @Autowired为Spring提供的注解
经常使用的是:@Resource,它有两个重要的属性:name和type,name属性解析为bean的名字,而type属性则解析为bean的类型。


———> @ModelAttribute和 @SessionAttributes
@ModelAttribute 代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。
 @SessionAttributes即将值放到session作用域中,写在class上面。

如:

———————>使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据

SpringMVC 支持使用 @ ModelAttribute  和 @ SessionAttributes  在不同的模型(model)和控制器(Controller)之间共享数据。  @ModelAttribute  主要有两种使用方式,一种是标注在方法上,一种是标注在 Controller 方法参数上。
当 @ ModelAttribute  标记在方法上的时候,该方法将在处理器方法执行之前执行,然后把返回的对象存放在 session 或模型属性中,属性名称可以使用 @ ModelAttribute (“attributeName”) 在标记方法的时候指定,若未指定,则使用返回类型的类名称(首字母小写)作为属性名称。关于 @ModelAttribute 标记在方法上时对应的属性是存放在 session 中还是存放在模型中,我们来做一个实验,看下面一段代码。
@Controller
@RequestMapping ( "/myTest" )
public class MyController {

    @ModelAttribute ( "hello" )
    public String getModel() {
       System. out .println( "-------------Hello---------" );
       return "world" ;
    }

    @ModelAttribute ( "intValue" )
    public int getInteger() {
       System. out .println( "-------------intValue---------------" );
       return 10 ;
    }

    @RequestMapping ( "sayHello" )
    public void sayHello( @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpSession session) throws IOException {
       writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num);
       writer.write( "\r" );
       Enumeration enume = session.getAttributeNames();
       while (enume.hasMoreElements())
           writer.write(enume.nextElement() + "\r" );
    }

    @ModelAttribute ( "user2" )
    public User getUser(){
       System. out .println( "---------getUser-------------" );
       return new User(3, "user2" );
    }
}
当我们请求 /myTest/sayHello.do 的时候使用 @ModelAttribute 标记的方法会先执行,然后把它们返回的对象存放到模型中。最终访问到 sayHello 方法的时候,使用 @ModelAttribute 标记的方法参数都能被正确的注入值。执行结果如下所示:
 Hello world,Hello user210
       由执行结果我们可以看出来,此时 session 中没有包含任何属性,也就是说上面的那些对象都是存放在模型属性中,而不是存放在 session 属性中。那要如何才能存放在 session 属性中呢?这个时候我们先引入一个新的概念 @SessionAttributes ,它的用法会在讲完 @ModelAttribute 之后介绍,这里我们就先拿来用一下。我们在 MyController 类上加上 @SessionAttributes 属性标记哪些是需要存放到 session 中的。看下面的代码:
@Controller
@RequestMapping ( "/myTest" )
@SessionAttributes (value ={ "intValue" , "stringValue" }, types={User. class })
public class MyController {

    @ModelAttribute ( "hello" )
    public String getModel() {
       System. out .println( "-------------Hello---------" );
       return "world" ;
    }

    @ModelAttribute ( "intValue" )
    public int getInteger() {
       System. out .println( "-------------intValue---------------" );
       return 10 ;
    }
  
    @RequestMapping ( "sayHello" )
    public void sayHello(Map<String, Object> map, @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpServletRequest request) throws IOException {
       map.put( "stringValue" , "String" );
       writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num);
       writer.write( "\r" );
       HttpSession session = request.getSession();
       Enumeration enume = session.getAttributeNames();
       while (enume.hasMoreElements())
           writer.write(enume.nextElement() + "\r" );
       System. out .println(session);
    }

    @ModelAttribute ( "user2" )
    public User getUser() {
       System. out .println( "---------getUser-------------" );
       return new User(3, "user2" );
    }
}
在上面代码中我们指定了属性为 intValue 或 stringValue 或者类型为 User 的都会放到 Session中,利用上面的代码当我们访问 /myTest/sayHello.do 的时候,结果如下:
 Hello world,Hello user210
仍然没有打印出任何 session 属性,这是怎么回事呢?怎么定义了把模型中属性名为 intValue 的对象和类型为 User 的对象存到 session 中,而实际上没有加进去呢?难道我们错啦?我们当然没有错,只是在第一次访问 /myTest/sayHello.do 的时候 @SessionAttributes 定义了需要存放到 session 中的属性,而且这个模型中也有对应的属性,但是这个时候还没有加到 session 中,所以 session 中不会有任何属性,等处理器方法执行完成后 Spring 才会把模型中对应的属性添加到 session 中。所以当请求第二次的时候就会出现如下结果:
 Hello world,Hello user210
user2
intValue
stringValue
当 @ModelAttribute 标记在处理器方法参数上的时候,表示该参数的值将从模型或者 Session 中取对应名称的属性值,该名称可以通过 @ModelAttribute(“attributeName”) 来指定,若未指定,则使用参数类型的类名称(首字母小写)作为属性名称。

————> @PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:

@Controller 
public class TestController { 
     @RequestMapping(value ="/user/{userId}/roles/{roleId}",method = RequestMethod.GET) 
     public String getLogin(@PathVariable("userId" ) String userId, 
         @PathVariable( "roleId" ) String roleId){ 
         System.out.println( "User Id : " + userId); 
         System.out.println( "Role Id : " + roleId); 
         return "hello"
     } 
}

--------> @requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。

@RequestBody

作用: 
      i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
      ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
  •     application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
  •     multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
  •     其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);

----------> @ResponseBody
作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

------> @Component
相当于通用的注解,当不知道一些类归到哪个层时才使用,一般不建议使用。

---------> @Repository
用于注解dao层,在daoImpl类上面注解。



猜你喜欢

转载自blog.csdn.net/darrensty/article/details/78411403
今日推荐