Spring Boot-基于数据库的请求映射

时间:2018-10-30 12:15:16

标签: spring spring-mvc spring-boot

使用Spring Boot 2,我想创建一个基于数据库的请求映射。我的意思是,我不想在控制器上使用数百个@RequestMapping注释,而是希望将映射存储在数据库表中。 每个控制器都实现一个具有execute方法的接口,因此我只需在数据库中搜索相关控制器并在其上调用execute方法即可。

目前,我有一个CustomController和一个@RequestMapping("*"),并且此控制器找到了真实的控制器并调用了execute方法。它可以工作,但不是一个好的解决方案。例如,在拦截器级别,处理程序对象是CustomController,而不是真正的控制器。

可能我应该像这样使用SimpleUrlHandlerMapping

@Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
    SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();

    Map<String, Object> urlMap = new HashMap<>();
    urlMap.put("/dashboard", __???__);
    simpleUrlHandlerMapping.setUrlMap(urlMap);

    return simpleUrlHandlerMapping;
}

但是在这种情况下,我不知道如何在urlMap中填充bean值。例如,在“ / dashboard”的情况下,如何放置DashboardController.execute()

也许有更好的解决方案?

更新1

我已经这样创建了SimpleUrlHandlerMapping

@Configuration
public class SimpleUrlHandlerMappingConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        Map<String, Object> urlMap = new HashMap<>();

        String path = "/dashboard";
        String controllerName = "dashboardController";

        Object myController = context.getBean(controllerName);

        urlMap.put(path, myController);
        simpleUrlHandlerMapping.setUrlMap(urlMap);

        return simpleUrlHandlerMapping;
    }

}

还有一个CustomHandlerAdapter为:

@Configuration
public class CustomHandlerAdapter implements HandlerAdapter {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public boolean supports(Object handler) {
        logger.debug("Test handler: " + handler);
        if (handler instanceof PageController) {
            return true;
        }
        return false;
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.debug("Custom handle");
        ModelAndView mv = new ModelAndView();
        String viewName = ((PageController)handler).execute2(request, response);
        mv.setViewName(viewName);
        return mv;
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return -1;
    }
}   

但是根据日志,看来SimpleUrlHandlerMapping不能正常工作:

- DispatcherServlet with name 'dispatcherServlet' processing GET request for [/dashboard]
- Looking up handler method for path /dashboard
- Did not find handler method for [/dashboard]
- Matching patterns for request [/dashboard] are [/**]
- URI Template variables for request [/dashboard] are {}
- Mapping [/dashboard] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@4bc6044e]]] and 1 interceptor
- Test handler: ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@4bc6044e]]
- Last-Modified value for [/dashboard] is: -1   

更新2

感谢@M. Deinum,我已经更新了代码并提供了可行的解决方案。 请注意,引入了@EnableWebMvc,以后可能会引起其他副作用。

SimpleUrlHandlerMappingConfig:

@Configuration()
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleUrlHandlerMappingConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        Map<String, Object> urlMap = new HashMap<>();

        String path = "/dashboard";
        String controllerName = "dashboardController";

        Object myController = context.getBean(controllerName);

        urlMap.put(path, myController);
        simpleUrlHandlerMapping.setUrlMap(urlMap);

        return simpleUrlHandlerMapping;
    }

}

CustomHandlerAdapter:

@Component
public class CustomHandlerAdapter implements HandlerAdapter {

    @Override
    public boolean supports(Object handler) {
        if (handler instanceof PageController) {
            return true;
        }
        return false;
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ModelAndView mv = new ModelAndView();
        String viewName = ((PageController)handler).execute2(request, response);
        mv.setViewName(viewName);
        return mv;
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return -1;
    }
}   

和WebConfig:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/style/**")
                .addResourceLocations("classpath:" + "/static/style/");
        registry.addResourceHandler("/js/**")
                .addResourceLocations("classpath:" + "/static/js/");

    }
}   

2 个答案:

答案 0 :(得分:0)

如果我理解正确,那么您想摆脱简单的操作(get / post / put / delete),这些操作仅从存储库中调用save / find / delete方法。 如果是这种情况,我建议使用Spring Data REST

答案 1 :(得分:0)

我在此发布最终解决方案(感谢M. Deinum)。

所以我只使用HandlerMapping创建了一个SimpleUrlHandlerMapping

@Configuration()
public class SimpleUrlHandlerMappingConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        Map<String, Object> urlMap = new HashMap<>();

        String path = "/dashboard";
        String controllerName = "dashboardController";

        Object myController = context.getBean(controllerName);

        urlMap.put(path, myController);
        simpleUrlHandlerMapping.setUrlMap(urlMap);

        simpleUrlHandlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);

        return simpleUrlHandlerMapping;
    }

}

还有一个自定义的HandlerAdapter

@Component
public class CustomHandlerAdapter implements HandlerAdapter {

    @Override
    public boolean supports(Object handler) {
        if (handler instanceof PageController) {
            return true;
        }
        return false;
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ModelAndView mv = new ModelAndView();
        String viewName = ((PageController)handler).execute2(request, response);
        mv.setViewName(viewName);
        return mv;
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return -1;
    }
}

请注意,此示例仅演示了概念,没有适​​当的错误处理和实际的数据库访问。