springboot通过注解实现多线程

1、springboot启动类中添加 @EnableAsync
 

package com.zr.gktjweb;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class GktjwebApplication {

    public static void main(String[] args) {

        SpringApplication.run(GktjwebApplication.class, args);
    }

}

2、在调用类之外的另一个类方法中添加:


package com.zr.gktjweb.aspect;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

//@Component
public class AsyThread {
//    @Override
    @Async
    public void run() {
        System.out.println("---------异步线程---------"+Thread.currentThread().getName());
    }
}

3、在另一个类中调用此方法:

package com.zr.gktjweb.controller.login;

import com.zr.gktjweb.aspect.AsyThread;
import com.zr.gktjweb.common.HttpClientUtil;
import com.zr.gktjweb.common.ResponseBean;
import com.zr.gktjweb.constant.SysCode;
import com.zr.gktjweb.model.SysUser;
import com.zr.gktjweb.util.ComUtil;
import com.zr.gktjweb.util.JSONUtils;
import com.zr.gktjweb.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "登录")
@Controller
public class LoginController {
    @Value("${baseurl}")
    private String baseurl;
    @Value("${login_url}")
    private String loginUrl;
    @Value("${logout_url}")
    private String logoutUrl;
    @Value("${syslogin_url}")
    private String sysloginUrl;
    @Value("${updateUserSessionByusername_url}")
    private String updateUserSessionByusernameUrl;
    @Value("${updatePass_url}")
    private String updatePassUrl;
    private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);

    @ApiOperation(value = "登录", notes = "登录验证")
    @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "姓名", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String")
    })
    @RequestMapping(value = "/login.do", method = RequestMethod.POST)
    @ResponseBody
    public ResponseBean login(String username, String password) {
        String url = baseurl + loginUrl;
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        String result = "";
        new AsyThread().run();
        System.out.println("--------当前线程--------"+Thread.currentThread().getName());
        //请求服务失败
        try {
            result = HttpClientUtil.doPost(url, map);
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("用户登录", e);
            return new ResponseBean(SysCode.errCode, "系统异常,请联系管理员", "");
        }
        JSONObject json = JSONObject.fromObject(result);
        //登录验证未通过
        if (!json.getString("code").equals(SysCode.successCode + "")) {
            ResponseBean responseBean = JSONUtils.jsonToObject(ResponseBean.class, result);
            return responseBean;
        }
        //验证通过,在session中设置token
        JSONObject dataJson = (JSONObject) json.get("data");
        String userJson = dataJson.getString("user");
        SysUser sysUser = JSONUtils.jsonToObject(SysUser.class, userJson);
        JSONObject tokenJson = (JSONObject) dataJson.get("token");
        String token = tokenJson.getString("token");
        UserUtil.setToken(token);
        UserUtil.setUserSession(sysUser);
        //第一次登陆修改密码
        if(ComUtil.isEmpty(sysUser.getLastlogindate())){
            return new ResponseBean(SysCode.retPwdCode, "", "");
        }
        String url1 = "/index.html";
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("url", url1);
        return new ResponseBean(SysCode.successCode, "登录成功", resMap);
    }

    /**
     * 注销登录
     *
     * @param request
     * @return
     */
    @RequestMapping("/loginout.do")
    public String loginOut(HttpServletRequest request) {
        request.getSession().invalidate();
        String url=baseurl+logoutUrl;
        HttpClientUtil.doGet(url);
        return "redirect:/";
    }

    @PostMapping("/users/updatePass.do")
    @ApiOperation(value = "修改密码")
    @ResponseBody
    public ResponseBean changePassword(String username, String oldPassword, String newPassword) {
        String url = baseurl + updatePassUrl;
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("oldPassword", oldPassword);
        map.put("newPassword", newPassword);
        String result = HttpClientUtil.doPost(url, map);
        ResponseBean responseBean = JSONUtils.jsonToObject(ResponseBean.class, result);
        //修改密码后重新登录
        ResponseBean loginResult=login(username,newPassword);
        //登录验证未通过
        if (!loginResult.getCode().toString().equals(SysCode.successCode + "")) {
            return loginResult;
        }
        return responseBean;
    }

    @ApiOperation(value = "当前登录用户")
    @GetMapping("/sys/login.do")
    @ResponseBody
    public SysUser getLoginInfo() {
        return UserUtil.getCurrentUser();
    }
}

调用controller层后结果如下:

实现异步失败。
5、后改为将实现异步的类,注入到controller层。通过spring生成的bean来调用异步方法:

package com.zr.gktjweb.aspect;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class AsyThread {
//    @Override
    @Async
    public void run() {
        System.out.println("---------异步线程---------"+Thread.currentThread().getName());
    }
}

package com.zr.gktjweb.controller.login;

import com.zr.gktjweb.aspect.AsyThread;
import com.zr.gktjweb.common.HttpClientUtil;
import com.zr.gktjweb.common.ResponseBean;
import com.zr.gktjweb.constant.SysCode;
import com.zr.gktjweb.model.SysUser;
import com.zr.gktjweb.util.ComUtil;
import com.zr.gktjweb.util.JSONUtils;
import com.zr.gktjweb.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "登录")
@Controller
public class LoginController {
    @Value("${baseurl}")
    private String baseurl;
    @Value("${login_url}")
    private String loginUrl;
    @Value("${logout_url}")
    private String logoutUrl;
    @Value("${syslogin_url}")
    private String sysloginUrl;
    @Value("${updateUserSessionByusername_url}")
    private String updateUserSessionByusernameUrl;
    @Value("${updatePass_url}")
    private String updatePassUrl;
    private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    AsyThread asyThread;


    @ApiOperation(value = "登录", notes = "登录验证")
    @ApiImplicitParams({@ApiImplicitParam(name = "username", value = "姓名", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String")
    })
    @RequestMapping(value = "/login.do", method = RequestMethod.POST)
    @ResponseBody
    public ResponseBean login(String username, String password) {
        String url = baseurl + loginUrl;
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        String result = "";
        asyThread.run();
        System.out.println("--------当前线程--------"+Thread.currentThread().getName());
        //请求服务失败
        try {
            result = HttpClientUtil.doPost(url, map);
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("用户登录", e);
            return new ResponseBean(SysCode.errCode, "系统异常,请联系管理员", "");
        }
        JSONObject json = JSONObject.fromObject(result);
        //登录验证未通过
        if (!json.getString("code").equals(SysCode.successCode + "")) {
            ResponseBean responseBean = JSONUtils.jsonToObject(ResponseBean.class, result);
            return responseBean;
        }
        //验证通过,在session中设置token
        JSONObject dataJson = (JSONObject) json.get("data");
        String userJson = dataJson.getString("user");
        SysUser sysUser = JSONUtils.jsonToObject(SysUser.class, userJson);
        JSONObject tokenJson = (JSONObject) dataJson.get("token");
        String token = tokenJson.getString("token");
        UserUtil.setToken(token);
        UserUtil.setUserSession(sysUser);
        //第一次登陆修改密码
        if(ComUtil.isEmpty(sysUser.getLastlogindate())){
            return new ResponseBean(SysCode.retPwdCode, "", "");
        }
        String url1 = "/index.html";
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("url", url1);
        return new ResponseBean(SysCode.successCode, "登录成功", resMap);
    }

    /**
     * 注销登录
     *
     * @param request
     * @return
     */
    @RequestMapping("/loginout.do")
    public String loginOut(HttpServletRequest request) {
        request.getSession().invalidate();
        String url=baseurl+logoutUrl;
        HttpClientUtil.doGet(url);
        return "redirect:/";
    }

    @PostMapping("/users/updatePass.do")
    @ApiOperation(value = "修改密码")
    @ResponseBody
    public ResponseBean changePassword(String username, String oldPassword, String newPassword) {
        String url = baseurl + updatePassUrl;
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("oldPassword", oldPassword);
        map.put("newPassword", newPassword);
        String result = HttpClientUtil.doPost(url, map);
        ResponseBean responseBean = JSONUtils.jsonToObject(ResponseBean.class, result);
        //修改密码后重新登录
        ResponseBean loginResult=login(username,newPassword);
        //登录验证未通过
        if (!loginResult.getCode().toString().equals(SysCode.successCode + "")) {
            return loginResult;
        }
        return responseBean;
    }

    @ApiOperation(value = "当前登录用户")
    @GetMapping("/sys/login.do")
    @ResponseBody
    public SysUser getLoginInfo() {
        return UserUtil.getCurrentUser();
    }
}

访问contrller层后,结果如下:

成功实现异步。

在Spring Boot中,我们可以通过注解实现多数据源切换。具体步骤如下: 1. 配置多个数据源 在application.properties文件中配置多个数据源,例如: ``` # 主数据源 spring.datasource.url=jdbc:mysql://localhost:3306/db1 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver # 从数据源 spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2 spring.datasource.secondary.username=root spring.datasource.secondary.password=123456 spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver ``` 2. 创建数据源配置类 创建两个数据源配置类,用于配置不同的数据源,例如: ``` @Configuration @MapperScan(basePackages = "com.example.demo.mapper.primary", sqlSessionTemplateRef = "primarySqlSessionTemplate") public class PrimaryDataSourceConfig { @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "primarySqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); } @Bean(name = "primarySqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } @Configuration @MapperScan(basePackages = "com.example.demo.mapper.secondary", sqlSessionTemplateRef = "secondarySqlSessionTemplate") public class SecondaryDataSourceConfig { @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondarySqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean.getObject(); } @Bean(name = "secondarySqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } ``` 其中,@MapperScan注解用于扫描Mapper接口,sqlSessionTemplateRef属性指定使用的SqlSessionTemplate。 3. 创建数据源切换注解 创建一个数据源切换注解,用于动态切换数据源,例如: ``` @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String value() default "primary"; } ``` 其中,value属性指定使用的数据源,默认为主数据源。 4. 创建数据源切换切面 创建一个数据源切换切面,用于根据注解动态切换数据源,例如: ``` @Aspect @Component public class DataSourceAspect { @Pointcut("@annotation(com.example.demo.annotation.DataSource)") public void dataSourcePointCut() { } @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); DataSource dataSource = signature.getMethod().getAnnotation(DataSource.class); if (dataSource != null) { DataSourceContextHolder.setDataSource(dataSource.value()); } } @After("dataSourcePointCut()") public void after(JoinPoint joinPoint) { DataSourceContextHolder.clearDataSource(); } } ``` 其中,@Pointcut注解用于定义切点,@Before注解用于在切点方法执行之前切换数据源,@After注解用于在切点方法执行之后清除数据源。 5. 创建数据源上下文 创建一个数据源上下文,用于保存当前线程使用的数据源,例如: ``` public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSource(String dataSource) { contextHolder.set(dataSource); } public static String getDataSource() { return contextHolder.get(); } public static void clearDataSource() { contextHolder.remove(); } } ``` 6. 使用注解切换数据源 在需要切换数据源的方法或类上加上@DataSource注解,例如: ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @DataSource("primary") public List<User> getPrimaryUsers() { return userMapper.selectAll(); } @Override @DataSource("secondary") public List<User> getSecondaryUsers() { return userMapper.selectAll(); } } ``` 在方法上加上@DataSource注解,指定使用的数据源。 以上就是通过注解实现多数据源切换的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值