Spring SpringMVC SpringBoot 常用注解说明

Spring SpringMVC SpringBoot 常用注解说明SpringSpring 常用注解说明 Spring 注解与 xml 配置的区别不使用注解的案例 Autowired Qualifier Resource Service 使用注解来构造 IoC 容器 Component Controller Service RepositorySp 常用注解汇总 SpringMVC Controller RequestMappi 使用

Spring

注解与xml配置的区别

Spring使用.xml配置来注入或者配置Aop,事务,主要缺点有两个:

  1. 内容都配置在.xml文件中,那么.xml文件将会十分庞大。按需求分开.xml文件,那么.xml文件又会非常多,将导致配置文件的可读性与可维护性变得很低。
  2. 在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。为了解决这两个问题,Spring引入了注解,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。

不使用注解的案例

定义老虎

 public class Tiger { 
    private String tigerName="Tiger"; public String toString(){ 
    return "TigerName:"+tigerName; } } 

定义猴子

 public class Monkey { 
    private String monkeyName = "Monkey"; public String toString(){ 
    return "MonkeyName:" + monkeyName; } } 

定义动物园

 public class Zoo { 
    private Tiger tiger; private Monkey monkey; public Tiger getTiger() { 
    return tiger; } public void setTiger(Tiger tiger) { 
    this.tiger = tiger; } public Monkey getMonkey() { 
    return monkey; } public void setMonkey(Monkey monkey) { 
    this.monkey = monkey; } public String toString(){ 
    return tiger + "\n" + monkey; } } 

Spring配置文件

 
   
   
    
     
     
    
    
    
   

测试方法(不使用注解)

public class TestAnnotation { 
    @Test public void test(){ 
    //读取配置文件 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); Zoo zoo=(Zoo) ctx.getBean("zoo"); System.out.println(zoo.toString()); } } 

@Autowired

@Autowired自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。 getter看个人需求,如果私有属性需要对外提供的话,应当予以保留
@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

因此,引入@Autowired注解,先看一下spring配置文件怎么写:

 
   
  
    //告知spring要使用注解了,spring会自动扫描com.spring路径下的注解 
    
    
    
    
   

原来zoo里面应当注入两个属性tiger、monkey,现在不需要注入了。再看下,Zoo.java也很方便,把getter/setter都可以去掉:

public class Zoo { 
    @Autowired private Tiger tiger; @Autowired private Monkey monkey; public String toString(){ 
    return tiger + "\n" + monkey; } } 

假设把xml配置中,下面两行去掉,再运行,会抛出异常:

 
   
   
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'zoo': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.spring.model.Tiger com.spring.model.Zoo.tiger; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.model.Tiger] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 

因为,@Autowired注解要去寻找的是一个Bean,Tiger和Monkey的Bean定义都给去掉了,自然就不是一个Bean了,Spring容器找不到也很好理解。那么,如果属性找不到我不想让Spring容器抛出异常,而就是显示null,可以吗?可以的,其实异常信息里面也给出了提示了,就是将==@Autowired注解的required属性设置为false即可==:

public class Zoo { 
    @Autowired(required=false) private Tiger tiger; @Autowired(required=false) private Monkey monkey; public String toString(){ 
    return tiger + "\n" + monkey; } } 

此时,找不到tiger、monkey两个属性,Spring容器不再抛出异常而是认为这两个属性为null。

@Qualifier

public interface IPhone{ 
    public String getPhoneName(); } 

两个实现类xiaomiPhone和huaweiPhone:

public class xiaomiPhone implements IPhone{ 
    public String getPhoneName(){ 
    return "xiaomi Phone"; } } 
public class huaweiPhoneimplements IPhone{ 
    public String getPhoneName(){ 
    return "huawei Phone"; } } 

再写一个PhoneFactory,引用Iphone(这里先不用@Qualifier注解):

public class CarFactory { 
    @Autowired private IPhone phone; public String toString(){ 
    return phone.getPhoneName(); } } 

配置文件:

 
   
   
    
    
    
    
    
   

测试方法:

/ * Autowired注解配合Qualifier注解 */ @Test public void test1(){ 
    //读取配置文件 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); PhoneFactory phoneFactory=(PhoneFactory) ctx.getBean("PhoneFactory"); System.out.println(phoneFactory.toString()); } 

运行一下,不用说,一定是报错的,Phone接口有两个实现类,Spring并不知道应当引用哪个实现类。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'phoneFactory': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.spring.IPhone com.spring.PhoneFactory.car; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.spring.IPhone ] is defined: expected single matching bean but found 2: [xiaomiPhone, huaweiPhone] 
public class PhoneFactory { 
    @Autowired @Qualifier("xiaomiPhone") private IPhone phone; public String toString(){ 
    return phone.getPhoneName(); } } 

@Resource

@Resource注解与@Autowired注解作用非常相似,这个就简单说了,看例子:

public class Zoo1 { 
    @Resource(name="tiger") private Tiger tiger; @Resource(type=Monkey.class) private Monkey monkey; public String toString(){ 
    return tiger + "\n" + monkey; } } 

@Resource的装配顺序:

  1. @Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
  2. 指定了name或者type则根据指定的类型去匹配bean
  3. 指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错

@Autowired和@Resource两个注解的区别:

  1. @Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配
  2. @Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了。

Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

@Service

 
   
   
    
   

以Zoo.java为例,其余的Monkey.java和Tiger.java都一样:

@Service public class Zoo { 
    @Autowired private Tiger tiger; @Autowired private Monkey monkey; public String toString(){ 
    return tiger + "\n" + monkey; } } 

Zoo.java在Spring容器中存在的形式就是”zoo”,即可以通过ApplicationContext的getBean(“zoo”)方法来得到Zoo.java。@Service注解,其实做了两件事情:

  1. 声明Zoo.java是一个bean,这点很重要,因为Zoo.java是一个bean,其他的类才可以使用@Autowired将Zoo作为一个成员变量自动注入。
  2. Zoo.java在bean中的id是”zoo”,即类名且首字母小写。

如果,我不想用这种形式怎么办,就想让Zoo.java在Spring容器中的名字叫做”Zoo”,可以的:

 @Service("Zoo") @Scope("prototype") public class Zoo { 
    @Autowired private Tiger tiger; @Autowired private Monkey monkey; public String toString(){ 
    return tiger + "\n" + monkey; } } 

这样,就可以通过ApplicationContext的getBean(“Zoo”)方法来得到Zoo.java了。

@Scope注解,应该很好理解。因为Spring默认产生的bean是单例的,假如我不想使用单例怎么办,xml文件里面可以在bean里面配置scope属性。注解也是一样,配置@Scope即可,默认是”singleton”即单例,”prototype”表示原型即每次都会new一个新的出来。

使用注解来构造IoC容器

用注解来向Spring容器注册Bean。需要在applicationContext.xml中注册

表明cn.gacl.java包及其子包中,如果某个类的头上带有特定的注解【@Component/@Repository/@Service/@Controller】,就会将这个对象作为Bean注册进Spring容器。也可以在
中指定多个包,多个包逗号隔开。如:

@Component

@Component是所有受Spring 管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。

@Controller

@Controller对应表现层的Bean,也就是Action,例如:

@Controller @Scope("prototype") public class UserAction extends BaseAction 
  
    { …… } 
  

使用@Controller注解标识UserAction之后,就表示要把UserAction交给Spring容器管理,在Spring容器中会存在一个名字为”userAction”的action,这个名字是根据UserAction类名来取的。注意:如果@Controller不指定其value【@Controller】,则默认的bean名字为这个类的类名首字母小写,如果指定value【@Controller(value=“UserAction”)】或者【@Controller(“UserAction”)】,则使用value作为bean的名字。
@Scope(“prototype”)表示将Action的范围声明为原型,可以利用容器的scope=”prototype”来保证每一个请求有一个单独的Action来处理,避免struts中Action的线程安全问题。spring 默认scope 是单例模式(scope=“singleton”),这样只会创建一个Action对象,每次访问都是同一Action对象,数据不安全,struts2 是要求每次次访问都对应不同的Action,scope=“prototype” 可以保证当有请求的时候都创建一个Action对象。

@Service

@Service对应的是业务层Bean,例如:

@Service("userService") public class UserServiceImpl implements UserService { ……… } 

@Service(“userService”)注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做”userService”,这样当Action需要使用UserServiceImpl的的实例时,就可以由Spring创建好的”userService”,然后注入给Action:在Action只需要声明一个名字叫”userService”的变量来接收由Spring注入的”userService”即可,具体代码如下:

// 注入userService @Resource(name = "userService") private UserService userService; 

注意:在Action声明的”userService”变量的类型必须是”UserServiceImpl”或者是其父类”UserService”,否则由于类型不一致而无法注入,由于Action中的声明的”userService”变量使用了@Resource注解去标注,并且指明了其name = “userService”,这就等于告诉Spring,说我Action要实例化一个”userService”,你Spring快点帮我实例化好,然后给我,当Spring看到userService变量上的@Resource的注解时,根据其指明的name属性可以知道,Action中需要用到一个UserServiceImpl的实例,此时Spring就会把自己创建好的名字叫做”userService”的UserServiceImpl的实例注入给Action中的”userService”变量,帮助Action完成userService的实例化,这样在Action中就不用通过”UserService userService = new UserServiceImpl();”这种最原始的方式去实例化userService了。如果没有Spring,那么当Action需要使用UserServiceImpl时,必须通过”UserService userService = new UserServiceImpl();”主动去创建实例对象,但使用了Spring之后,Action要使用UserServiceImpl时,就不用主动去创建UserServiceImpl的实例了,创建UserServiceImpl实例已经交给Spring来做了,Spring把创建好的UserServiceImpl实例给Action,Action拿到就可以直接用了。Action由原来的主动创建UserServiceImpl实例后就可以马上使用,变成了被动等待由Spring创建好UserServiceImpl实例之后再注入给Action,Action才能够使用。这说明Action对”UserServiceImpl”类的“控制权”已经被“反转”了,原来主动权在自己手上,自己要使用”UserServiceImpl”类的实例,自己主动去new一个出来马上就可以使用了,但现在自己不能主动去new “UserServiceImpl”类的实例,new “UserServiceImpl”类的实例的权力已经被Spring拿走了,只有Spring才能够new “UserServiceImpl”类的实例,而Action只能等Spring创建好”UserServiceImpl”类的实例后,再“恳求”Spring把创建好的”UserServiceImpl”类的实例给他,这样他才能够使用”UserServiceImpl”,这就是Spring核心思想“控制反转”,也叫“依赖注入”,“依赖注入”也很好理解,Action需要使用UserServiceImpl干活,那么就是对UserServiceImpl产生了依赖,Spring把Acion需要依赖的UserServiceImpl注入(也就是“给”)给Action,这就是所谓的“依赖注入”。对Action而言,Action依赖什么东西,就请求Spring注入给他,对Spring而言,Action需要什么,Spring就主动注入给他。

@ Repository

@Repository对应数据访问层Bean ,例如:

@Repository(value="userDao") public class UserDaoImpl extends BaseDaoImpl 
  
    { ……… } 
  

@Repository(value=“userDao”)注解是告诉Spring,让Spring创建一个名字叫”userDao”的UserDaoImpl实例。

当Service需要使用Spring创建的名字叫”userDao”的UserDaoImpl实例时,就可以使用@Resource(name = “userDao”)注解告诉Spring,Spring把创建好的userDao注入给Service即可。

// 注入userDao,从数据库中根据用户Id取出指定用户时需要用到 @Resource(name = "userDao") private BaseDao 
  
    userDao; 
  

Spring常用注解汇总

本文汇总了Spring的常用注解,以方便大家查询和使用,具体如下:

使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包)。



@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true) 表示延迟初始化
@Service用于标注业务层组件、
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Scope用于指定scope作用域的(用在类上)
@PostConstruct用于指定初始化方法(用在方法上)
@PreDestory用于指定销毁方法(用在方法上)
@DependsOn:定义Bean初始化及销毁时的顺序
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:
@Autowired @Qualifier(“personDaoBean”) 存在多个实例配合使用
@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
@PostConstruct 初始化注解
@PreDestroy 摧毁注解 默认 单例 启动就加载
@Async异步方法调用






































Spring MVC

@Controller

  1. 在SpringMVC 的配置文件中定义MyController 的bean 对象。
  2. 在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。
 
   
   
   < context:component-scan base-package = "com.host.app.web" />//路径写到controller的上一层(扫描包详解见下面浅析) 

@RequestMapping

使用 @RequestMapping 来映射 Request 请求与处理器
方式一:通过常见的类路径和方法路径结合访问controller方法

下面例子,就是因为MyController 没有被@RequestMapping 标记,所以当需要访问到里面使用了@RequestMapping 标记的showView 方法时,就是使用的绝对路径/showView请求就可以了。

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

在控制器上加了@RequestMapping 注解,所以当需要访问到里面使用了@RequestMapping 标记的方法showView() 的时候就需要使用showView 方法上@RequestMapping 相对于控制器MyController上@RequestMapping 的地址,即/test/showView

@Controller @RequestMapping ( "/test" ) public class MyController { 
    @RequestMapping ( "/showView" ) public ModelAndView showView() { 
    ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " ); return modelAndView; } } 
方式二:使用uri模板

URI 模板就是在URI 中给定一个变量,然后在映射的时候动态的给该变量赋值。如URI 模板http://localhost/app/{variable1}/index.html ,这个模板里面包含一个变量variable1 ,那么当我们请求http://localhost/app/hello/index.html 的时候,该URL 就跟模板相匹配,只是把模板中的variable1 用hello 来取代。这个变量在SpringMVC 中是使用@PathVariable 来标记的。在SpringMVC 中,我们可以使用@PathVariable 来标记一个Controller 的处理方法参数,表示该参数的值将使用URI 模板中对应的变量的值来赋值。

代码中我们定义了两个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 是会帮我们自动转换的。

@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; } } 
@Controller @RequestMapping ( "/myTest" ) public class MyController { 
    @RequestMapping ( "*/wildcard" ) public String testWildcard() { 
    System. out .println( "wildcard------------" ); return "wildcard" ; } } 

当@RequestParam中没有指定参数名称时,Spring 在代码是debug 编译的情况下会默认取更方法参数同名的参数,如果不是debug 编译的就会报错。

使用 @RequestMapping 的一些高级用法

RequestMapping注解有六个属性,下面我们把她分成三类进行说明

属性 含义
value 指定请求的实际地址,指定的地址可以是URI Template 模式
method 指定请求的method类型, GET、POST、PUT、DELETE等
属性 含义
consumes 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
属性 含义
params 指定request中必须包含某些参数值是,才让该方法处理。
headers 指定request中必须包含某些指定的header值,才能让该方法处理请求。
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 是不能存在的。

method属性
@RequestMapping (value= "testMethod" , method={ 
   RequestMethod. GET , RequestMethod. DELETE }) public String testMethod() { 
    return "method" ; } 

在上面的代码中就使用method 参数限制了以GET 或DELETE 方法请求/testMethod 的时候才能访问到该Controller 的testMethod 方法。

headers属性
@RequestMapping (value= "testHeaders" , headers={ 
    "host=localhost" , "Accept" }) public String testHeaders() { 
    return "headers" ; } 

headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息,且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。

@RequestMapping 标记的处理器方法支持的方法参数和返回类型
支持的方法参数类型
  1. HttpServlet 对象,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 对象。 这些参数Spring 在调用处理器方法的时候会自动给它们赋值,所以当在处理器方法中需要使用到这些对象的时候,可以直接在方法上给定一个方法参数的申明,然后在方法体里面直接用就可以了。但是有一点需要注意的是在使用HttpSession 对象的时候,如果此时HttpSession 对象还没有建立起来的话就会有问题。
  2. Spring 自己的WebRequest 对象。 使用该对象可以访问到存放在HttpServletRequest 和HttpSession 中的属性值。
  3. InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是针对HttpServletRequest 而言的,可以从里面取数据;OutputStream 和Writer 是针对HttpServletResponse 而言的,可以往里面写数据。
  4. 使用@PathVariable 、@RequestParam 、@CookieValue 和@RequestHeader 标记的参数。
  5. 使用@ModelAttribute 标记的参数。
  6. java.util.Map 、Spring 封装的Model 和ModelMap 。 这些都可以用来封装模型数据,用来给视图做展示。
  7. 实体类。 可以用来接收上传的参数。
  8. Spring 封装的MultipartFile 。 用来接收上传文件的。
  9. Spring 封装的Errors 和BindingResult 对象。 这两个对象参数必须紧接在需要验证的实体对象参数之后,它里面包含了实体对象的验证结果。
支持的返回类型
  1. 一个包含模型和视图的ModelAndView 对象。
  2. 一个模型对象,这主要包括Spring 封装好的Model 和ModelMap ,以及java.util.Map ,当没有视图返回的时候视图名称将由RequestToViewNameTranslator 来决定。
  3. 一个View 对象。这个时候如果在渲染视图的过程中模型的话就可以给处理器方法定义一个模型参数,然后在方法体里面往模型中添加值。
  4. 一个String 字符串。这往往代表的是一个视图名称。这个时候如果需要在渲染视图的过程中需要模型的话就可以给处理器方法一个模型参数,然后在方法体里面往模型中添加值就可以了。
  5. 返回值是void 。这种情况一般是我们直接把返回结果写到HttpServletResponse 中了,如果没有写的话,那么Spring 将会利用RequestToViewNameTranslator 来返回一个对应的视图名称。如果视图中需要模型的话,处理方法与返回字符串的情况相同。
  6. 如果处理器方法被注解@ResponseBody 标记的话,那么处理器方法的任何返回类型都会通过HttpMessageConverters 转换之后写到HttpServletResponse 中,而不会像上面的那些情况一样当做视图或者模型来处理。
  7. 除以上几种情况之外的其他任何返回类型都会被当做模型中的一个属性来处理,而返回的视图还是由RequestToViewNameTranslator 来决定,添加到模型中的属性名称可以在该方法上用@ModelAttribute(“attributeName”) 来定义,否则将使用返回类型的类名称的首字母小写形式来表示。使用@ModelAttribute 标记的方法会在@RequestMapping 标记的方法执行之前执行。

@ModelAttribute和 @SessionAttributes

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


SpringMVC 支持使用 @ModelAttribute 和 @SessionAttributes 在不同的模型(model)和控制器之间共享数据。 @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

当 @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"; } @RequestMapping(value="/product/{productId}",method = RequestMethod.GET) public String getProduct(@PathVariable("productId") String productId){ 
    System.out.println("Product Id : " + productId); return "hello"; } @RequestMapping(value="/javabeat/{regexp1:[a-z-]+}", method = RequestMethod.GET) public String getRegExp(@PathVariable("regexp1") String regexp1){ 
    System.out.println("URI Part 1 : " + regexp1); return "hello"; } } 

@requestParam

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

@ResponseBody

作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

handler method 参数绑定常用的注解

handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)

处理requet uri 部分(这里指uri template中variable,不含queryString部分)的注解:@PathVariable;

当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

@Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { 
    @RequestMapping("/pets/{petId}") public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { 
    // implementation omitted  } } 

上面代码把URI template 中变量 ownerId的值和petId的值,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable(“name”)指定uri template中的名称。

处理request header部分的注解: @RequestHeader, @CookieValue;

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。

这是一个Request 的header部分:

Host                    localhost:8080  
Accept                  text/html,application/xhtml+xml,application/xml;q=0.9  
Accept-Language         fr,en-gb;q=0.7,en;q=0.3  
Accept-Encoding         gzip,deflate  
Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7  
Keep-Alive              300  
@RequestMapping("/displayHeaderInfo.do") public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) { 
    } 
@RequestMapping("/displayHeaderInfo.do") public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) { 
    } 

即把JSESSIONID的值绑定到参数cookie上。

处理request body部分的注解:@RequestParam, @RequestBody;

@RequestParam

  1. 常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String–> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;
  2. 用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;
  3. 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;
    示例代码:

@Controller @RequestMapping("/pets") @SessionAttributes("pet") public class EditPetForm { 
    @RequestMapping(method = RequestMethod.GET) public String setupForm(@RequestParam("petId") int petId, ModelMap model) { 
    Pet pet = this.clinic.loadPet(petId); model.addAttribute("pet", pet); return "petForm"; } } 
@RequestMapping(value = "/something", method = RequestMethod.PUT) public void handle(@RequestBody String body, Writer writer) throws IOException { 
    writer.write(body); } 
处理attribute类型是注解: @SessionAttributes, @ModelAttribute;
@Controller @RequestMapping("/editPet.do") @SessionAttributes("pet") public class EditPetForm { 
    // ...  } 
  1. @SessionAttributes 启用的attribute 对象上;
  2. @ModelAttribute 用于方法上时指定的model对象;
  3. 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中。

用到方法上@ModelAttribute的示例代码:

@ModelAttribute public Account addAccount(@RequestParam String number) { 
    return accountManager.findAccount(number); } 

这种方式实际的效果就是在调用@RequestMapping的方法之前,为request对象的model里put(“account”, Account)。

用在参数上的@ModelAttribute示例代码:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) public String processSubmit(@ModelAttribute Pet pet) { 
    } 

首先查询 @SessionAttributes有无绑定的Pet对象,若没有则查询@ModelAttribute方法层面上是否绑定了Pet对象,若没有则将URI template中的值按对应的名称绑定到Pet对象的各属性上。

< context:component-scan base-package = “” />浅析


  1. //指定扫描的路径

  2. //排除扫描的路径


有一个use-default-filters属性,属性默认为true,表示会扫描指定包下的全部的标有@Component的类,并注册成bean.也就是@Component的子注解@Service,@Reposity等。

这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller或其他内容则设置use-default-filters属性为false,表示不再按照scan指定的包扫描,而是按照

指定的包扫描,示例:

 
   
   //注意后面要写.* 
   

当没有设置use-default-filters属性或者属性为true时,表示基于base-packge包下指定扫描的具体路径

 
   
    
    
    
   

效果相当于:

 
   
    
   

Spring Boot

@SpringBootApplication

@SpringBootConfiguration

@EnableAutoConfiguration

这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于 spring-boot-starter-web 添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。Starter POMs和Auto-Configuration:设计auto-configuration的目的是更好的使用”Starter POMs”,但这两个概念没有直接的联系。你可以自由地挑选starter POMs以外的jar依赖,并且Spring Boot将仍旧尽最大努力去自动配置你的应用。

如果发现应用了你不想要的特定自动配置类,你可以使用 @EnableAutoConfiguration 注解的排除属性来禁用它们。

import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.jdbc.*; import org.springframework.context.annotation.*; @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { } 

@ComponentScan

@RestController

@Target(value=TYPE) @Retention(value=RUNTIME) @Documented @Controller @ResponseBody public @interface RestController 

RequestMapping简化注解

@Profiles

Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。

 @Configuration @Profile("production") public class ProductionConfiguration { 
    // ...  } 

全局异常处理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220461.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:25
下一篇 2026年3月17日 下午8:26


相关推荐

  • N8N 工作流使用中转API 教程

    N8N 工作流使用中转API 教程

    2026年3月15日
    2
  • tracert命令的原理是什么_tracert命令的原理

    tracert命令的原理是什么_tracert命令的原理1. Tracert 命令的原理与作用Tracert命令诊断实用程序通过向目标计算机发送具有不同生存时间的ICMP数据包,来确定至目标计算机的路由,也就是说用来跟踪一个消息从一台计算机到另一台计算机所走的路径。该诊断实用程序将包含不同生存时间 (TTL

    2026年3月4日
    8
  • Linux基础命令—gunzip「建议收藏」

    Linux基础命令—gunzip「建议收藏」Linux基础命令—gunzip

    2022年4月21日
    126
  • rcep协议内容_ptp协议

    rcep协议内容_ptp协议展开全部(1)合同的含义合同是当事人或当事双方之间设立、变更、终止民事关系的协议。依法62616964757a686964616fe78988e69d8331333363373036成立的合同,受法律保护。合同具有如下法律特征:①合同是两个或两个以上的、法律地位平等的当事人意思表示一致的协议;②合同以产生、变更或终止债权债务关系为目的;③合同是一种民事法律行为。在合同中,一般用甲方、乙方来指代交易…

    2025年9月26日
    10
  • EXACT函数_excel中的exact函数

    EXACT函数_excel中的exact函数EXACT函数:EXACT函数是一个文本函数,通过这个函数可以将不同的字符串进行对比,通常用于信息核对。EXACT函数的功能:比较两个字符串是否一致,返回不同的结果。EXACT函数的语法结构:EX

    2022年8月2日
    8
  • csgo所有开箱网站_csgo国外开箱网站

    csgo所有开箱网站_csgo国外开箱网站CSGO国内开箱网站大全收录incsgo官网,skinsdog官网,coolkaixiang官网,88steam官网,Box818官网,Piggycase官网,Yskins官网incsgo国内CSGO饰品皮肤开箱网站官方链接:www.incsgo.gg注册登录自动免费获得$1.00美金取回状态:直接取回**优惠码:**csgogo(充值使用csgogo可增加5%充值金额)skinsdog狗网CSGO饰品皮肤开箱网站可直接取回官方链接:skinsdog.cc.

    2022年10月6日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号