@Configuration
这个注解的意思,就是告诉spring这是一个配置类,当我们使用注解类作为配置文件之后我们在测试的时候加载配置文件:
AnnotationConfigApplicationContext
ComponentScan(value=" ",includeFilters={},excludeFilters={},useDefaultFilters)扫描组件的配置
参数解析:
value=“ ”这里面我们写的是扫描的路径,
includeFilters={}这里面写的是@ComponentScan.Filter(type = ,classes = {})
指定我们在扫描的时候只扫描哪些组件,
type=“”指定按扫描扫描,
FilterType.ANNOTATION 按照注解加载 ,后面的classes = {Controller.class})
FilterType. ASPECTJ 使用ASPECTJ表达式
FilterType. ASSIGNABLE_TYPE 按照给定的类型
FilterType. REGEX 使用正则指定
FilterType.CUSTOM使用自定义规则。
FilterType.CUSTOM使用自定义规则,这个我们要拿出来单独说
如果想要使用自定义规则,我们需要创建一个类,并让这个类去实现接口TypeFilter里面的
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
方法
metadataReader:读取到当前正在扫描的类信息
metadataReaderFactory:可以获取到其他任何类信息
excludeFilters={}用法和上面includeFilters相同只是意思正好相反excludeFilters={}意思是指定 扫描的时候按什么规则排除那些组件。
useDefaultFilters的意思就是:关闭组件的默认扫描
@Scope()指定范围,调整作用域
**里面有两个参数:
propotype:多实列(ioc容器启动并不会去调用方法创建对象放在容器中,每次获取的时候去创建)
singleton: 单实例 (ioc容器启动会调用方法创建对象放到ioc容器中)
**
@lazy懒加载
这个懒加载只会对我们的单实例有用,在外面配置了懒加载了之后:容器启动不创建对象,第一次使用bean创建对象并初始化,只会创建第一次使用的时候,后面使用的时候都不会去创建
@Conditional:按照一定的条件进行判断之后,满足了才会注入到容器中
这里面的参数是:Condition数组
用法可以写在Bean方法上面,也可以直接写在类上面
解释一下:我们写在类上面的话,我们在进行bean配置导入IOC容器中的时候,我们不会直接的去导入,而是会下去执行注解@Conditional里面的方法进行判断如果为true则注入,如果为false那么久不会注入到容器中
**用法详细介绍:**我们这个注解里面写的是一个类类型,所以我们在执行这个类的时候我们需要先去创建一个类,让这个类去实现接口Condition中的方法public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
这个方法中的参数:
ConditionContext:判断条件能够使用上下文
AnnotatedTypeMetadata:注释信息
@import注解,给容器中导入一个组件,id默认是组件全类名
方法1:@import(xx.class)直接写要导入容器的组件
方法2: @Import({xx.class})还可以去写一个类让这个类去实现接口ImportSelector里面的
public String[] selectImports(AnnotationMetadata importingClassMetadata)
方法
这个方法返回的值就是我们需要导入组件的全类名
方法三** @Import({xx.class})创建一个类,实现接口ImportBeanDefinitionRegistrar里面的**
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
;
解析一下里面的方法:
registry.containsBeanDefinition()的意思就是判断bean是否存在IOC容器中
registry.registerBeanDefinition(beanname(指定bean的名字),rootBeanDefinition(类型))创建bean
**
方法四 使用spring提供的FactoryBean工厂
(1)默认工厂获取的是工厂bean调用getobject创建的对象
(2)要获取工厂bean本身,我们就需要给id前面加&
**
使用方法:创建一个类去实现接口FactoryBean<>中的三个方法
getObject() 返回一个对象添加到容器中
getObjectType()返回类型
isSingleton() 是否为单例
bean的生命周期
(1).bean创建——>初始化——>销毁
当我们的bean在初始化的时候,自定义初始化
当我们的bean在销毁的时候,也可以自定义销毁
这里我们要注意一下,在单实例的情况下:容器会管理这个bean,在多实列的情况下:容器不会去管理这个bean
第一种方法我们在写注解@Bean的时候在里面写上@Bean(initMethod = “init(方法名字)”,destroyMethod = “destory(方法名字)”)
第二种方法 我们可以直接写一个类,让类去实现接口InitializingBean和DisposableBean里面的destroy()和afterPropertiesSet()方法
第三种方法可以使用注解的方式来实现使用
@PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化
@PreDestroy:在容器销毁之前,通知我们进行清理工作
bean的后置处理器
我们只需要去创建一个类,让他去实现接口BeanPostProcessor中的
public Object postProcessBeforeInitialization(Object bean, String beanName)
在初始化之前执行
public Object postProcessAfterInitialization(Object bean, String beanName)
在初始化之后执行
我们写好这个类之后要在类上面,添加一个注解@Component标识为普通组件,然后我们在配置文件中通过注解@ComponentScan(value = “”)添加进去
@Value属性赋值
在属性赋值的时候,最后一种赋值方式**${}** 是取出配置文件中的值(配置文件时.properties文件)
在使用这个的时候我们先要去写一个文件
在文件中写
之后我们需要在配置文件中使用一个注解 @PropertySource 加载外部配置文件
之后我们我们使用 ${}获取值就可以了
自动装配@AutoWired
(1)默认优先按照类型去容器中找对应的组件
(2)如果找到了多个相同类型的组件,再将属性名称作为ID去查找
(3)我们可以使用注解@Qualifier(“bookDao”),使用Qualifier指定需要装配的组件id,而不是使用属性名
(4)自动装配默认一定要将属性赋值好,没有就会报错
(5)可以使用@Autowired(required=false)里面的参数required=false;就算为空也可以装配
(6)@AutoWired:可以写在构造器,参数,方法,属性上
@Primary
1.让spring进行装配的时候默认为首选bean
@Resource 和@Inject
(1).@Resource 也是自动装配,默认是按照属性名装配,也可以使用@Resoucename=“bookDao2”
(2)@Inject也是自动装配
(3)这个两个注解都是自动装配
自定义组件
(1)自定义组件想要使用spring容器在底层的一些组件
(2)想要实现自定义组件:需要去实现xxxAWare在创建对象的时候,会调用接口规定的方法注入相关组件
(3)把spring底层一些组件注入到自定义的Bean中
xxxAware----——》xxxprocessor
@Profile
注解的解析:spring为我们提供的可以根据当前环境,动态的激活和切换一系列的组件功能,标识类和方法上
(1)指定组件在哪个环境的情况下才能被注册到容器中。
(2)加了环境标识的Bean,只有环境都被激活的时候才能被注册到容器中,默认是default,没有被环境标识的Bean,容器初始化就会被加入进去。
(3)@Profile的默认环境是default。
怎么切换 环境:
(1)使用命令行参数的方式:在Run configuration里面的VM optins直接修改参数为:-Dspring.profiles.active=dev
(2)使用代码的方式创建修改环境变量
@Test
public void test1(){
//1.创建一个applicationContext对象
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
//2.设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test","dev","prod");
//注册主配类
applicationContext.register(MainConfig6.class);
//启动刷新容器
applicationContext.refresh();
//打印当前容器中的bena名字
String[] definitionNames=applicationContext.getBeanDefinitionNames();
for (String name:definitionNames){
System.out.println(name);
}
}
注意注意没有标识环境的bean,在任何环境下都是直接加载的
AOP注解开发
解析:aop是指在程序运行期间动态的将某段代码切入到指定位置进行运行的编程方式
准备工作:
(1)导入依赖
(2)定义一个业务逻辑类
(3)定义一个日志切面
通知注解解析:
@Before 前置通知:在目标运行之前运行
@After 后置通知:在目标运行之后运行(无论异常结束还是正常结束都会执行)
@AfterReturning 返回通知:只有在正常结束的时候才会运行
@AfterThrowing 异常通知:在目标方法异常之后运行
@Around 环绕通知:动态代理,手动的推荐目标方法运行
(4)给切面目标方法标注何时运行(通知注解)
(5)给切面类和业务逻辑类都添加到容器中
(6)必须告诉spring哪个是切面类,(给切面类上面加上一个注解@Aspect)
(7)给配置类上面加上一个注解@EnableAspectJAutoProxy 意思是告诉spring开启注解aop模式
1.创建业务逻辑类
package com.xiaoran.spring.aop;
public class MathCalcl {
public int chu(int i ,int j){
System.out.println("当前正在调用的是 ---------------chu()这个方法");
return i/j;
}
}
2.创建aop切面类
这里面有两个注解可以说一下:
value=“”这里面写的是切入点表达式,returning =“”用来接返回值
@AfterReturning(value=“pointcat()”,returning = “result”)
value=“”这里面写的是切入点表达式,throwing =“”用来接返回值
@AfterThrowing(value = “pointcat()”,throwing = “exception”)
package com.xiaoran.spring.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import java.lang.reflect.Array;
import java.util.Arrays;
//告诉spring当前类是一个切面类
@Aspect
public class Aop {
//抽取公共的切入点表达式
@Pointcut("execution(* com.xiaoran.spring.aop.MathCalcl.*(..))")
public void pointcat(){}
@Before("pointcat()")
public void logStart(JoinPoint joinPoint){
Object[] args=joinPoint.getArgs();
System.out.println(joinPoint.getSignature().getName()+"除法运行。。。。。参数列表{"+Arrays.toString(args) +"}");
}
@After("pointcat()")
public void logEnd(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName()+"除法结束。。。。");
}
@AfterReturning(value="pointcat()",returning = "result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(joinPoint.getSignature().getName()+"除法正常返回。。。。运行结果是:{"+result+"}");
}
@AfterThrowing(value = "pointcat()",throwing = "exception")
public void logExction(JoinPoint joinPoint,Exception exception){
System.out.println(joinPoint.getSignature().getName()+"除法异常结束。。。。异常信息:{"+exception+"}");
}
}
在配置类中写
package com.xiaoran.spring.config;
import com.xiaoran.spring.aop.Aop;
import com.xiaoran.spring.aop.MathCalcl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@Configuration
public class MainConfig7 {
//添加业务逻辑类
@Bean
public MathCalcl mathCalcl(){
return new MathCalcl();
}
//添加类加入到容器中
@Bean
public Aop aop(){
return new Aop();
}
}
事务
1.导入依赖
2.配置数据源,和jdbcTemplate操作数据
3.给方法添加事务注解,标识事务 @Transactional在方法上
4.@EnableTransactionManagement开启基于注解的事务管理,在配置类中
5.配置事务管理器来控制事务,注册事务管理器在容器中
//注册事务管理器
@Bean
public PlatformTransactionManager transactionManager()throws Exception{
return new DataSourceTransactionManager(dataSourceTest());
}
(1)写一个dao
package com.xiaoran.spring.shiwu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.UUID;
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(){
String sql="insert into tbl_User(username,age) values(?,?)";
String username=UUID.randomUUID().toString().substring(0,5);
jdbcTemplate.update(sql,username,19);
}
}
2.创建一个service
package com.xiaoran.spring.shiwu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UseService {
@Autowired
private UserDao userDao;
@Transactional
public void inseruser(){
userDao.insert();
System.out.println("家人们插入完成了");
int i=1/0;
}
}
3.在配置类中写
package com.xiaoran.spring.shiwu;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringValueResolver;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/*
原理:
[1].@EnableTransactionManagement利用TransactionManagementConfigurationSelector给容器中导入组件
*/
@EnableTransactionManagement
@ComponentScan("com.xiaoran.spring.shiwu")
@Configuration
public class MainConfig8 {
//注册我们的数据源
@Bean
public DataSource dataSourceTest() throws PropertyVetoException {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("mysql123456");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test1");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception{//用来简化增删改查的操作
//spring对@Configuration类会特殊处理,给容器中加组件的方法,多次调用都只是从容器中找组件
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSourceTest());
return jdbcTemplate ;
}
//注册事务管理器
@Bean
public PlatformTransactionManager transactionManager()throws Exception{
return new DataSourceTransactionManager(dataSourceTest());
}
}
servlet
(1)在写了一个jsp页面,我们写了一个Helloservlet.java继承了Httpservice,如果是以前我们需要service用xml的方式在配置web.xml方式配置,现在只需要在类上使用注解@Webservice(“/xx”)拦截路径
1.创建一个HelloService
package com.xiaoran.spring.service;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/hello")
public class HelloService extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doGet(req, resp);
resp.getWriter().write("hello.....");
}
}
在写一个html
<%--
Created by IntelliJ IDEA.
User: kkdjk
Date: 2021/10/21
Time: 10:37
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<a href="hello">hello</a>
</body>
</html>
共享库(shared libraries)和runtimes pluggability(运行时插件)
1.service容器启动的时候会去扫描,当前应用里面的每一个jar包里面的
/META-INF/services下面的javax.servlet.ServletContainerInitializer这个包创建的位置我们必须创建到resources里面,如果写在我们的话,Ij无法加载到
2.我们创建一个类MyServletContainerInitializer,实现接口 ServletContainerInitializer中的onstartup()方法,
3.我们在/META-INF/services/javax.servlet.ServletContainerInitializer里面写入我们MyServletContainerInitializer的具体位置。
(1).创建MyServletContainerInitializer.java类:
package com.xiaoran.spring.service;
import com.xiaoran.spring.user.UserFilter;
import com.xiaoran.spring.user.UserListener;
import com.xiaoran.spring.user.UserServlet;
import org.springframework.beans.factory.DisposableBean;
import javax.servlet.*;
import javax.servlet.annotation.HandlesTypes;
import java.util.EnumSet;
import java.util.Set;
@HandlesTypes(value = HelloServlet.class)//这里面传入的是我们感兴趣的类型
public class MyServletContainerInitializer implements ServletContainerInitializer {
//Set<Class<?>> set:传入感兴趣的所有后代类型
//ServletContext:代表当前web应用的servletContext应用,一个web应用对应一个servletContext
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
System.out.println("******************************************");
//for (Class<?> name:set){
// System.out.println(name);
//}
//注册组件Service
ServletRegistration.Dynamic servlet= servletContext.addServlet("UserServlet",new UserServlet());
//配置servlet的映射信息
servlet.addMapping("/User");
//注册list
servletContext.addListener(UserListener.class);
//注册组件Filter
FilterRegistration.Dynamic filter= servletContext.addFilter("UserFilter",UserFilter.class);
//配置映射信息
//addMappingForUrlPatterns(拦截的类型,true,拦截的路径)
filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"/*");
}
}
定制spring MVC
1.@EnableWebMvc:开启SpringMVC定制配置功能
2.配置组件:视图解析器,视图映射,静态资源映射,
(1)实现接口 webMvcConfigurer或者继承 WebMvcConfigurueAdapter
(1)创建一个类MyWebappInit.java继承AbstractAnnotationConfigDispatcherServletInitializer类里面的方法
import com.xiaoran.spring.config.AppConfig;
import com.xiaoran.spring.config.RootConfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
//web容器启动的时候创建对象,调用方法来初始化容器和前端控制器
public class MyWebappInit extends AbstractAnnotationConfigDispatcherServletInitializer {
//获取根容器的配置类(Spring的配置文件)父容器
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfig.class};
}
//获取web容器的配置类(SpringMVC配置文件)子容器
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{AppConfig.class};
}
//获取DispatcherServlet的映射信息
// /:拦截所有请求包括静态资源 ,不包括xx.Jsp
// /*:拦截所有的请求,包括*.jsp页面都拦截
protected String[] getServletMappings() {
return new String[]{"/" };
}
}
2.创建一个类父容器。RootConfig.java
(1)spring的容器不扫描controller,父容器,
(2) 这里一定一定不能写seDefaultFilters = false 如果写了的话就不会加载其他组件了懂吗
//spring的容器不扫描controller,父容器,
// 这里一定一定不能写seDefaultFilters = false 如果写了的话就不会加载其他组件了懂吗
@ComponentScan(value = "com.xiaoran.spring",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
})
public class RootConfig {
}
3.创建一个子容器:AppConfig.java只扫描controller
(1)让这个类去实现一个接口WebMvcConfigurer里面的方法。如配置视图解析器,配置静态资源的访问,配置拦截器
package com.xiaoran.spring.config;
import com.xiaoran.spring.Fister.Myfirst;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.*;
//springMvc只扫描Controller:子容器
@ComponentScan(value = "com.xiaoran.spring",useDefaultFilters = false,includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
})
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
//配置视图解析器
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
//配置静态资源的访问
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//配置拦截器
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Myfirst()).addPathPatterns("/**");
}
}
4.创建一个success.jsp
<%--
Created by IntelliJ IDEA.
User: kkdjk
Date: 2021/10/21
Time: 17:49
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1> 在多说几次分开的话</h1>
<img src="../../4.jpg" alt="">
</body>
</html>
5.写一个service
package com.xiaoran.spring.service;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public String sayHello(String name){
return "hello"+name;
}
}
6.写一个controller
package com.xiaoran.spring.controoler;
import com.xiaoran.spring.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@Autowired
private HelloService helloService;
@RequestMapping("/")
public String success(){
return "success";
}
}
配置拦截器
package com.xiaoran.spring.Fister;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Myfirst implements HandlerInterceptor {
//目标方法之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle....................");
return true;
}
//在目标方法执行正确之后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...............");
}
//页面响应以后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
异步请求—servlet
package com.xiaoran.spring.service;
import org.springframework.web.context.request.async.AsyncWebRequest;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//1.支持异步处理asyncSupported = true
@WebServlet(value = "/user",asyncSupported = true)
public class UserService extends HttpServlet {
@Override
protected void doGet( HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//2.支持异步处理
System.out.println("主线程开始。。。。"+Thread.currentThread()+"....."+System.currentTimeMillis());
final AsyncContext startAsy=req.startAsync();
//3.业务逻辑进行异步处理;开始异步处理
startAsy.start(new Runnable() {
public void run() {
try {
System.out.println("副线程开始。。。。"+Thread.currentThread()+"....."+System.currentTimeMillis());
sayHello();
startAsy.complete(); //调用完了
ServletResponse response=startAsy.getResponse();//获取到异步的上下文,获取响应
response.getWriter().write("hello......asyanncontext");
System.out.println("副线程结束。。。。"+Thread.currentThread()+"....."+System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
});
System.out.println("主线程结束。。。。"+Thread.currentThread()+"....."+System.currentTimeMillis());
}
public void sayHello()throws Exception{
System.out.println(Thread.currentThread()+"processing***********");
Thread.sleep(3000);
}
}
异步请求----SpringMVC
1.方法返回值写成:Callable<String》
package com.xiaoran.spring.controoler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.concurrent.Callable;
@Controller
public class userController {
@ResponseBody
@RequestMapping("/async01")
public Callable<String> async01(){
System.out.println("主线程结束。。。"+Thread.currentThread()+"==>>"+System.currentTimeMillis());
Callable<String> callable=new Callable<String>() {
public String call() throws Exception {
System.out.println("副线程开始。。。"+Thread.currentThread()+"==>>"+System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("副线程结束。。。"+Thread.currentThread()+"==>>"+System.currentTimeMillis());
return " Callable<String> async01() ";
}
};
System.out.println("主线程结束。。。"+Thread.currentThread()+"==>>"+System.currentTimeMillis());
return callable;
}
}
2.方法返回值写成DeferredResult<Object>
(1)创建一个类Deferred.java用于保存进程
package com.xiaoran.spring.controoler;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Deferred {
private static Queue<DeferredResult<Object>> queue=new ConcurrentLinkedQueue<DeferredResult<Object>>();
//保存进来
public static void save(DeferredResult<Object> deferredResult){
queue.add(deferredResult);
}
//返回出去
public static DeferredResult<Object> get(){
return queue.poll();
}
}
(2).创建一个AsycController.java
package com.xiaoran.spring.controoler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.UUID;
@Controller
public class AsycController {
@ResponseBody
@RequestMapping("/t1")
public DeferredResult<Object> create(){
DeferredResult<Object> deferredResult=new DeferredResult<Object>((long)3000,"create fine.......");
//临时保存
Deferred.save(deferredResult);
return deferredResult;
}
@ResponseBody
@RequestMapping("/t2")
public String creat1(){
//创建订单
String order=UUID.randomUUID().toString();
DeferredResult<Object> deferredResult=Deferred.get();
//只有setResult执行程序就会返回结果,然后结束
deferredResult.setResult(order);
return "success ..."+order;
}
}