一个controller调用根据不同业务分发不同service

在一个项目中需要写很多的controller去调用不同的service,而写一个网关可以省去写controller层的痛苦。

下面开始介绍可以分发不同service。

1.因为service在项目启动时就已全部注入到spring容器中,所以我们需要写一个工具类,可以从spring上下文(applicationContext)中获取到对应service

@Component
public class SpringUtil implements ApplicationContextAware {

    @Autowired
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
        System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtil.getAppContext()获取applicationContext对象,applicationContext=" + SpringUtil.applicationContext + "========");
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static  T getBean(Class clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static  T getBean(String name, Class clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

2.上面的SpringUtil我们已经可以在上下文中直接取到对于的service了,下面就开始编写controller进行请求的分发(我称之为网关)。首先我们需要先写一个抽象类,来定义service,这样接下来的sevice只需要继承这个抽象类即可(我们还可以写一些时间统计,交易流水入库等。。自我感觉很大的用处)。

public abstract class RootService {

    private Logger logger = LoggerFactory.getLogger(RootService.class);

    private long beforeTime;

    private long endTime;


    private void before (String action) {
        beforeTime = System.currentTimeMillis();
        logger.info("交易:" + action + "开始时间:" + beforeTime);
    }

    private void end (String action) {
        endTime = System.currentTimeMillis();
        long time = endTime - beforeTime;
        logger.info("交易:" + action + "结束时间:" + endTime);
        logger.info("交易:" + action + "耗时:" + time);
    }

    public JSONObject execute(String actionName,Map map) {
        before(actionName);
        JSONObject jsonObject = doNext(map);
        end(actionName);
        return jsonObject;
    }

    private JSONObject doNext(Map map) {
        try {
            return doAction(map);
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject js = new JSONObject();
            js.put("retCode","000000");
            js.put("retMsg","程序报错");
            return js;
        }
    }


    protected abstract JSONObject doAction(Map map);



}

3.一切准备就绪,我们可以开始编写contrconoller了(网关) 

@Controller
@RequestMapping("/root")
public class RootController {

    @ResponseBody
    @RequestMapping(value = "/h5.do",produces = {"application/json;charset=UTF-8"},method = RequestMethod.POST)
    public JSONObject root(@RequestBody Map map, HttpServletRequest httpServletRequest){
        String service = (String) map.get("service");

        JSONObject js = new JSONObject();
        RootService rootService = (RootService) SpringUtil.getBean(service);

        return rootService.execute(service,map);
    }

}

到这里一个网关就写好了,然后我们写一个service进行测试一下(对应的Dao层我就不现丑了,相信大家都会)

@Service
public class UserServiceImpl extends RootService{
    private Logger logger = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private UserDao userDao;

    @Override
    protected JSONObject doAction(Map map) {
        JSONObject js = new JSONObject();
        String id = (String) map.get("id");
        User user = userDao.getUser(id);
        js.put("user",user);
        logger.info("进入了UserService");
        return js;
    }
}

 下面我们用postman测试一下测试报文为:

{
  "id":"1",
  "service":"userServiceImpl"
}

控制台打印为:

2019-10-18 17:24:41.089  INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService           : 交易:userService开始时间:1571390681089
2019-10-18 17:24:41.138  INFO 6452 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2019-10-18 17:24:41.227  INFO 6452 --- [nio-8080-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2019-10-18 17:24:41.255  INFO 6452 --- [nio-8080-exec-2] c.s.s.service.impl.UserService           : 进入了UserService
2019-10-18 17:24:41.256  INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService           : 交易:userService结束时间:1571390681256
2019-10-18 17:24:41.256  INFO 6452 --- [nio-8080-exec-2] c.s.s.service.util.RootService           : 交易:userService耗时:167

返回为:

{
  "user": {
    "user_id": "1",
    "password": "123456",
    "user_name": "张三"
  }
}

总结:这样写法的好处在于 1.有一个统一的入口,不需要在编写controller, 可以专注于业务(service)2.可以在公共入口做公共处理。

以上为我的一些拙见

 

 

 

 

你可能感兴趣的:(spring,spring,网关)