本文最后更新于:2024年3月18日 下午
概述
容器机制
容器是Spring框架实现功能的基础,所有配置过的类都会被纳入Spring容器的管理之中。
Spring把它管理的类称为Bean,跟Java Bean相比,Spring的Bean没有什么限制,只要配置到容器中,就称为Bean
ApplicationContext接口
Spring主要通过ApplicationContext接口来实现容器API调用。主要通过三种接口实现类来获取ApplicationContext实例。
ClassPathXMLApplicationContext:从类路径加载配置文件,创建ApplicationContext实例
FileSystemXmlApplicationContext:从文件系统加载配置文件,创建ApplicationContext实例
AnnotationConfigApplicationContext:从注解中加载配置文件,创建ApplicationContext实例
简单应用
1. 引用包
将Spring依赖jar包引用到工程中。
2. 创建Bean
在bean包中创建两个Bean类,Student和Teacher。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.SpringTest .bean ;public class Student { public Student () { super (); System .out .println ("Student对象创建了" ); } private String msg = null ; public void setMsg (String msg ) { this .msg = msg; } public String getMsg ( ) { return msg; } public void study ( ) { System .out .println ("学生在学习" + msg); } } package com.SpringTest .bean ;public class Teacher { public Teacher () { super (); System .out .println ("Teacher对象创建了" ); } private String msg = null ; public void setMsg (String msg ) { this .msg = msg; } public String getMsg ( ) { return msg; } public void teach ( ) { System .out .println ("老师讲解" + msg + "知识" ); } }
3. 创建配置文件
在src目录下创建applicationContext.xml
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="student" class ="com.SpringTest.bean.Student" > <property name ="msg" > <value > Java</value > </property > </bean > <bean id ="teacher" class ="com.SpringTest.bean.Teacher" > <property name ="msg" > <value > Spring</value > </property > </bean > </beans >
在上述代码中,<bean>
元素指定了一个由Spring容器管理的Bean类,id
即为唯一标识符,class
为该Bean类的完全限定名,<property>
子元素用于指定属性名,<value>
用于指定该属性的值。在这里我们定义了两个Bean类,分别是Student和Teacher。
4. 使用Bean
在src目录下新建test.java文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.SpringTest.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.SpringTest.bean.Student;import com.SpringTest.bean.Teacher;public class TestSpring { public static void main (String[] args) throws Exception { ApplicationContext applicationContext = new ClassPathXmlApplicationContext ("applicationContext.xml" ); Student student = applicationContext.getBean ("student" ,Student.class); student.study(); Teacher teacher = applicationContext.getBean("teacher" ,Teacher.class); teacher.teach(); } }
这里通过ClassPathXmlApplicationContext
接口实现类来获取ApplicationContext实例,然后通过ApplicationContext实例的getBean()方法来获取Bean类。
输出结果:
由于在Spring容器中配置的类在容器创建时会全部实例化,所以这里可以看到Teacher类虽然在Student.study()后调用,但其构造函数的输出仍在study()之前,说明在容器创建时便已实例化。可以在xml文件中进行修改,添加lazy-init
属性,这样只有在用户第一次索取Bean类的时候才会实例化该类。
1 <bean id ="teacher" class ="com.SpringTest.bean.Teacher" lazy-init ="true" >
Bean的管理
注入方式
1. 构造器注入
被注入的类创建有参/无参构造函数,在ApplicationContext.xml文件中通过<constructor-arg>
元素为类的构造方法的参数注入值。
1 2 3 4 5 6 <bean id = "student" class = "com.SpringTest.bean.Student" > <constructor-arg name= "sid" value= "1" ></constructor-arg> <constructor-arg name= "name" value= "ZhangSan" ></constructor-arg> <constructor-arg name= "age" value= "20" ></constructor-arg> <constructor-arg name= "course" value= "Java" ></constructor-arg> </bean>
2. 属性注入
属性注入需要被注入的类提供对应的setter函数,然后再ApplicationContext.xml文件中通过<property>
元素进行注入。
1 2 3 4 <bean id= "teacher" class= "com.SpringTest.bean.Teacher" > <property name= "sid" value= "1" ></property> <property name= "name" value= "Lisi" ></property> </bean>
注入集合
设定setter函数,并配合<property>
元素来完成集合类的注入(List,Set,Map,Array等)
如下创建一个Mix类(部分代码)
1 2 3 4 5 6 private List <String > mylist;private void setMyList (List<String myList ) { this .mylist = myList; } ....
ApplicationContext.xml文件配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <bean id ="mix" class ="com.SpringTest.bean.Mix" > <property name ="mylist" > <list > <value > list1</value > <value > list2</value > </list > </property > <property name ="myMap" > <map > <entry key ="key01" value ="map01" > </entry > <entry key ="key02" value ="map02" > </entry > </map > </property > <property name ="myArray" > <array > <value > array01</value > <value > array02</value > </array > </property > </bean >
注入其他类型的Bean
通过setter函数和<property>
元素的ref
属性或ref
子元素实现
1 2 3 4 5 6 7 8 9 <bean id ="school" class ="com.SpringTest.bean.school" > <property name ="stu" > <ref bean ="student" > </ref > </property > <property name ="stu" ref ="student" > </property > </bean >
使用SpEL注入
SpEL可以实现动态赋值,由于SpEL需要获取对象的属性值,所以需要声明getter方法。
1 2 3 4 5 6 7 8 9 <bean id ="employee" class ="com.SpringTest.bean.Employee" > <property name ="sid" value ="1" > </property > <property name ="name" vlaue ="WangWu" > </property > <property name ="department" value ="研发部" > </property > </bean > <bean id ="person" class ="com.SpringTest.bean.Person" > <property name ="pid" value ="# {employee.sid} " ></property > <property name ="name" value ="# {employee.name} " ></property > </bean >
作用域和生命周期
作用域
常用的作用域有两个,分别是Singleton
和Prototype
Singleton:单例模式,默认作用域,在Spring容器中只会存在一个id相同的Bean,所有调用该id得到的Bean都是同一个共享的Bean,Spring容器可以管理该Bean的生命周期
Prototype:每次从容器中调用Bean时,都会产生一个新的Bean实例,两个实例不相同,Spring容器只负责创建Bean实例而不管理其生命周期
1 2 <bean id ="person" class ="com.SpringTest.bean.Person" scope ="prototype" />
生命周期
Bean的生命周期是指Bean实例被创建、初始化和销毁的过程。
主要关注两点,一点是Bean实例初始化之后执行指定方法,另一点是Bean实例销毁之前执行指定方法。
初始化
通过<init-method>
属性
在Java文件中定义一个方法,例如init()
1 2 3 4 public void init () { System.out .println("调用init()方法" ); }
在xml文件中设置属性
1 2 3 <bean id ="bean1" class ="com.SpringTest.bean.bean1" init-method="init" > <property .....></property > </bean>
通过实现initializingBean
接口
通过重写该接口的afterPropertiesSet()
方法,在实例初始化后会自动调用该方法,不需要在xml中设置
1 2 3 4 5 6 7 public class Bean2 implements InitializingBean { ...; @override public void afterPropertiesSet() throws Exception{ System.out .println("调用afterPropertiesSet()方法" ); } }
销毁
通过<destroy-method>
属性
同样先在Java中创建一个方法来调用,例如close()
1 2 3 4 public void close () { System.out .println("调用close()方法" ); }
在xml中设置<destroy-method>
属性
1 2 3 <bean id= "bean3" class= "com.SpringTest.bean.Bean3" destroy-method= "close" > ... </bean>
通过实现DisposableBean
接口
通过重写该接口的destory()
方法,在实例被销毁前会自动调用该方法,同样不需要配置xml文件
1 2 3 4 5 6 7 public class Bean4 implements DisposableBean { ...; @Override public void destroy () throws Exception { System.out.println("调用destroy()方法" ); } }
注解
常用注解
注解
描述
@Component
指定一个普通的Bean
@Controller
指定一个控制器组件Bean,功能上等同于@Component
@Service
指定一个业务逻辑组件Bean,功能上等同于@Component
@Repository
指定一个DAO组件Bean,功能上等同于@Component
@Scope
指定作用域
@Value
指定注入值
@Autowired
指定要自动装配的对象
@Qualifier
指定要自动装配的对象名称,与@Autowired联合使用
@PostConstruct
指定初始化后调用的方法
@PreDestroy
指定销毁前调用的方法
使用
导入spring-aop的jar包,配置applicationContext.xml文件
配置注解扫描
在applicationContext.xml的<beans>
元素中添加配置信息
1 <context :component -scan base-package ="com.SpringTest.bean" />
即扫描bean包下所有类的注解
新建类,例如Sch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Component ("sth" )@Scope (scopeName = "singleton" ) public class Sch{ @Value ("005" ) private int sid; @Autowired @Qualifier ("stu" ) private Stu stu; ....; @PostConstruct public void init () { System .out .println ("调用init()方法" ); } @PreDestroy public void close () { System .out .println ("调用close()方法" ); } }
以上代码中,@Component注解将Sch类注册为Spring容器中的Bean,@Scope注解指定Sch类的作用域,@Value注解为Sch类的sid属性注入值,@Autowired和@Qualifier注解为Sch类的stu属性注入另一个Bean实例。@PostConstruct注解指完成实例化后调用的方法,@PreDestroy注解指销毁前调用的方法。
AOP
概念
AOP——面向切面编程
连接点(Joinpoint):
程序执行过程中某个特定的节点,例如某个类的初始化完成后、某个方法执行前等。
通知(Advice):
通知是在目标类连接点上执行的一段代码,有如下几种方式。
通知类型
描述
前置通知(Before)
在目标方法被调用之前调用通知
后置通知(After)
在目标方法被调用之后调用通知
返回通知(After-returning)
在目标方法成功执行之后调用通知
异常通知(After-throwing)
在目标方法抛出异常之后调用通知
环绕通知(Around)
在目标方法调用前和调用后调用通知
切点(Pointcut):
匹配连接点的断言,AOP通过切点来定位特定的连接点。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如执行某个特定名称的方法)
目标对象(Target):
通知所作用的目标类。
引介(Introduction):
是一种特殊的通知,它可以为类添加一些属性和方法。
切面(Aspect):
对系统中的横切关注点逻辑进行模块化封装的AOP概念实体。
织入(Weaving):
织入是将通知添加到目标类具体连接点的过程。
代理(Proxy):
目标类被AOP织入增强后产生的一个结果类,这个结果类融合了原类和增强的逻辑。
实现机制
JDK动态代理
在Spring中,AOP代理由IOC容器负责创建,依赖关系也由IOC容器管理,因此AOP可以直接将IOC容器中的其他类作为目标对象。在默认情况下Spring AOP使用JDK动态代理,当目标对象是一个类并且这个类没有实现接口的时候,切换到CGLib代理。
JDK动态代理涉及到两个API:InvocationHandler和Proxy。
InvocationHandler是一个接口,代理类通过实现该接口来定义横切逻辑。
Proxy利用InvocationHandler动态生成目标类的代理对象。
示例:
新建四个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public interface LoginService { public void login (); }public class LoginServiceImpl implements LoginService { @Override public void login ( ) { System .out .println ("执行login()方法" ); } }public class PerformHandler implements InvocationHandler { private Object target; public PerformHandler (Object target){ this .target =target; } @Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable { System .out .println ("方法开始执行" ); Object invoke = method.invoke (target, args); System .out .println ("方法执行完毕" ); } }public class Test { public static void main (String [] args ){ LoginService loginService = new LoginServiceImpl (); PerformHandler performHandler = new PerformHandler (loginService); loginService = (LoginService ) Proxy .newProxyInstance (loginService.getClass ().getClassLoader (), LoginService .getClass ().getInterfaces ().performHandler ); loginService.login (); } }
最后得到结果
方法开始执行
执行login()方法
方法执行完毕
CGLib动态代理
JDK动态代理只能为接口创建代理,而CGLib可以为类创建代理。
CGLib动态代理依赖Enhancer类创建代理实例,依靠MethodInterceptor接口织入要增强的方法。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class CgLibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer (); public Object getProxy (Class clazz ){ enhancer.setSuperClass (clazz); enhancer.setCallback (this ); return enhancer.create (); } @Override public Object intercept (Object obj, Method method, Object [] objects, MethodProxy methodProxy) throws Throwable { System .out .println ("CGLib代理之前" ); Object invoke = methodProxy.invokeSuper (obj,objects); System .out .println ("CGLib代理之后" ); return invoke; } }public class TestCGLib { public static void main (String [] args ){ CgLibProxy cglibProxy = new CgLibProxy (); LoginServiceImpl userService = (LoginServiceImpl ) cglibProxy.getProxy (LoginServiceImpl .class ); userService.login (); } }
得到结果:
CGLib代理之前
执行Login()方法
CGLib代理之后
开发方法
基于XML开发
XML中配置AOP的元素:
示例:
首先在applicationContext.xml中引入AOP,略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.qfedu.demo02;public interface UserService { void insert () ; void delete () ; void update () ; void select () ; } package com.qfedu.demo02;public class UserServiceImpl implements UserService { @Override public void insert () { System.out .println("添加用户信息" ); } @Override public void delete () { System.out .println("删除用户信息" ); } @Override public void update () { System.out .println("更新用户信息" ); } @Override public void select () { System.out .println("查询用户信息" ); } }
创建类XmlAdvice用于定义通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.qfedu.demo02;public class XmlAdvice{ //前置通知 public void before (){ System .out .println("这是前置通知"); } public void after (){ System .out .println("这是后置通知"); } public Object around(ProceddingJoinPoint point ) throws Throwable{ System .out .println("这是环绕通知之前的部分"); ///调用目标方法 Object object = point .proceed(); System .out .println("这是环绕通知之后的部分"); return object ; } public void afterReturning(){ System .out .println("这是返回通知(方法不出现异常时调用)"); } public void afterException(){ System .out .println("这是异常通知"); } }
在applicationContext.xml的<bean>
元素中添加配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <bean name ="userService" class ="com.qfedu.demo02.UserServiceImpl" /> <bean name ="xmlAdvice" class ="com.qfedu.demo02.XmlAdvice" /> <aop:config > <aop:pointcut id ="pointcut" expression ="execution(* com.qfedu.demo02.UserServiceImpl. *(..))" /> <aop:aspect ref ="xmlAdvice" > <aop:before method ="before" pointcut-ref ="pointcut" /> <aop:after-returning method ="afterReturning" pointcut-ref ="pointcut" /> <aop:around mehtod ="around" pointcut-ref ="pointcut" /> <aop:after-throwing method ="afterException" pointcut-ref ="pointcut" /> <aop:after method ="after" pointcut-ref ="pointcut" /> </aop:aspect > </aop:config >
测试类
1 2 3 4 5 6 7 8 package com.qfdeu.demo02;public class TestXml { public static void mian (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext ("applicationContext.xml" ); UserService userService = context.getBean("userService" ,UserService.class); userService.delete(); } }
得到结果:
这是前置通知
这是环绕通知之前的部分
删除用户信息
这是后置通知
这是环绕通知之后的部分
这是返回通知(方法不出现异常时调用)
基于注解开发
支持的注解类型如下:
注解名称
描述
@Aspect
指定切面
@Pointcut
指定切点
@Before
指定前置通知
@After
指定后置通知
@Around
指定环绕通知
@AfterReturning
指定返回通知
@AfterThrowing
指定异常通知
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.qfedu.demo02;@Aspect public class AnnoAdvice { @Pointcut("execution(* com.qfedu.demo02.UserServiceImpl.* (..))") public void pointcut () { } @Before("pointcut()") public void before () { System.out.println("这是前置通知" ); } @After("pointcut()") public void after () { System.out.println("这是后置通知" ); } @Around("pointcut()") public Object around (ProceedingJoinPoint point) throws Throwable{ System.out.println("这是环绕通知之前的部分" ); Object object = point.proceed(); System.out.println("这是环绕通知之后的部分" ); return object; } @AfterReturning("pointcut()") public void afterReturning () { System.out.println("这是返回通知" ); } @AfterThrowing("pointcut()") { System.out.println("这是异常通知" ); } }
配置applicationContext.xml文件
1 2 3 4 5 <bean name ="userService" class ="com.qfedu.demo02.UserServiceImpl" /> <bean name ="annoAdvice" class ="com.qfedu.demo02.AnnoAdvice" /> <aop:aspectj-autoproxy />
测试如上
多个切面优先级
基于注解配置
只需要添加@Order
注解即可
1 2 3 4 5 6 7 8 9 10 11 @Aspect @Order (1 ) public class aspect1{ }@Aspect @Order (0 ) public class aspect2{ }
Order注解中的值越小,优先级越高,所以aspect2会优先于aspect1
基于Ordered接口配置
Ordered接口提供了一个getOrder()方法来设置优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class aspect1 implements Ordered { ....; @Override public int getOrder(){ return 1 ; } }public class aspect2 implements Ordered { ....; @Override public int getOrder(){ return 0 ; } }
同样,值越小,优先级越高,所有Aspect2的优先级大于Aspect1
基于XML配置
主要通过<aop:aspect>
元素的<order>
元素实现,在配置切面时添加Order属性
1 2 3 4 5 6 7 8 9 ....<aop:aspect ref ="aspect1" order ="1" > ....;</aop:aspect > <aop:aspect ref ="aspect2" order ="0" > ....;</aop:aspect >
同样,这里也是Aspect2的优先级大于Aspect1
Spring MVC基础
概念
功能组件
DIspatcherServlet(前端控制器)
前端控制器负责拦截客户端请求并分发给其他组件,它是整个流程控制的中心。
HandlerMapping(处理器映射器)
处理器映射器负责根据客户端请求的URL寻找处理器。
Handler(处理器)
处理器负责对客户端的请求进行处理,编写的业务逻辑写在这里。
HandlerAdapter(处理器适配器)
处理器适配器负责根据特定的规则对处理器进行执行。
ViewResolver(视图解析器)
视图解析器负责视图解析,它将处理结果生成View并展示给用户。关于视图相关的代码在这里编写。
工作流程
用户—>DispatcherServlet
客户端发出一个HTTP请求,服务器接收请求,根据DispatcherServlet的映射路径,将请求交予DispatcherServlet处理
DIspatcherServlet—>Handler
DispatcherServlet根据URL、方法、报文头和参数在内的请求信息以及HandlerMapping的配置解析得到Handler
DispatcherServlet—>HandlerAdapter
解析出Handler后调用HandlerAdapter来调用Handler并完成业务逻辑的处理。
HandlerAdapter—>DispatcherServlet
完成业务逻辑处理后,将处理结果,即ModelAndView返回给DispatcherServlet
DispatcherServlet—>VIewResolver
通过ViewResolver完成逻辑视图名到真实View对象的解析,并通过View对象对数据模型进行视图渲染。
DispatcherServlet—>用户
DispatcherServlet将最终的View对象返回给客户端,呈现给用户。
简单应用
先在web.xml中配置DispatcherServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <servlet > <servlet-name > springMVC</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > /WEB-INF/springMVC-config.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 >
contextConfigLocation表示引入springMVC配置文件所在位置
<load-on-startup>
表示优先级
<url-pattern>
元素的值为”/”,表示将所有的请求都映射到DispatcherSevelet
XML实现
在WebContent/WEB-INF目录下新建spring-MVC的配置文件springMVC-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?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: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/context http://www.springframework.org/schema/context/spring-context.xsd" > <bean name ="/controller01" class ="com.qfedu.controller.MyController01" /> <bean class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <bean class ="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" /> </beans >
在src中新建com.qfedu.controller包,新建MyController01类
1 2 3 4 5 6 7 8 9 public class MyController01 implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{ ModelAndView mv = new ModelAndView (); mv.addObject("msg" ,"Hello World" ); mv.setViewName("/WEB-INF/page/page01/jsp" ); return mv; } }
handlerRequest()方法用于处理客户端请求,其中先新建了一个ModelAndView对象,然后为ModelAndView对象设置模型数据和View名称,最后将该对象返回。
在WebContent/WEB-INF/page/page01.jsp中通过下述代码调用程序
1 2 3 <body > $ {requestScope.msg} </body >
注解实现
新建类MyController02
1 2 3 4 5 6 7 8 9 10 11 package com.qfedu.controller;@Controller public class MyController02 { @RequestMapping ("/execute" ) public ModelAndView execute(){ ModelAndView mv = new ModelAndView (); mv.addObject("msg" ,"Hello World" ); mv.setViewName("page01" ); return mv; } }
@Controller注解将类作为一个Controller类配置到Spring容器中,@RequestMapping注解指定了execute()方法的映射路径。
修改springMVC-config.xml配置文件
1 2 3 4 5 6 7 <context:component-scan base-package ="com.qfedu.controller" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/page/" /> <property name ="suffix" value =".jsp" /> </bean >
prefix用于指定View名称的前缀,suffix用于指定View名称的后缀
常用注解
除了上述使用到的@Controller,还有一些常用的注解
@RequestMapping
@RequestMapping注解用于处理请求地址映射,示例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Controller public class MyController03 { @RequestMapping(value="/toWelcome") public ModelAndView toWelcome () { ModelAndView mv = new ModelAndView (); mv.setViewName("page02" ); return mv; } @RequestMapping(value="/welcome", method=RequestMethod.POST) public ModelAndView welcome () { ModelAndView mv = new ModelAndView (); mv.addObject("msg" ,"Hello World" ); mv.setViewName("page01" ); return mv; } }
上述代码中,第一个@RequestMapping注解的value值为”/toWelcome”,表明访问路径为“/toWelcome”的请求将由toWelcome()方法处理,处理完成后请求被转发到page02.jsp。
第二个@RequestMapping注解的value值为”/welcome”,methdo属性值为”RequestMethod.POST“,表明访问路径为”/welcome“,并且访问方式为”POST“的请求将由welcome()方法处理,处理完成后请求被转发到page01.jsp。
@RequestParam
@RequestParam注解用于获取请求参数的值,将请求参数赋值给方法中的形参。
1 2 3 4 5 6 @RequestMapping (value="/login" ) public ModelAndView login (@RequestParam (value="username" , defaultValue="xiaofeng" ) String username, @ReqeustParam (value="password" , defaultValue="123abc" ) String password){ System .out .println ("用户名:" + username); System .out .println ("密码:" + password); return null ; }
上述代码中,第一个@RequestParam注解的value属性值为username,defaultValue为xiaofeng,即将请求参数username的值赋值给login()方法中的形参username,当请求参数没有提交值时,采用默认值”xiaofeng“,password同理。
@PathVariable
@PathVariable注解用于获取URL中的动态参数
1 2 3 4 5 6 7 8 9 10 11 package com .qfedu .comtroller ; @Controller @RequestMapping (value="/claList/{cid}" )public class MyController05 { @RequestMapping (value="/stuList/{sid}" ) public String findStudent (@PathVariable (value="cid" ) Integer cid, @PathVariable (value="sid" ) Integer sid){ System .out .println ("班级ID为:" + cid); System .out .println ("学生ID为:" + sid); return null ; } }
@RequestMapping注解的value属性使用的为动态参数,@PathVariable注解将动态参数cid,sid映射为findStudent()方法中的形参cid,sid。