我已经使用Spring MVC三个月了.我正在考虑一种动态添加RequestMapping的好方法.这需要将控制器部件放入库中,然后以动态方式添加它们.无论如何,我能想到的唯一方法就是声明一个这样的控制器:
@Controller
@RequestMapping("/mypage")
public class MyController {
@RequestMapping(method = RequestMethod.GET)
public ModelAndView mainHandler(HttpServletRequest req) {
return handleTheRest(req);
}
}
Run Code Online (Sandbox Code Playgroud)
哪个不好,因为基本上我没有使用Spring.然后我不能使用表单绑定,注释等.我想将requestMappings动态添加到可以像通常的MVC控制器一样注释的类的方法,并使用自动绑定,这样我就可以避免手动处理HttpServletRequest.
有任何想法吗?}
ska*_*man 24
Spring MVC使用HandlerMapping接口的实现来执行URL映射.通常开箱即用的那些是默认的实现,即SimpleUrlHandlerMapping,BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping.
如果你想实现自己的映射机制,这很容易做到 - 只需实现该接口(或者,更有可能,扩展AbstractUrlHandlerMapping),在上下文中将类声明为bean,并DispatcherServlet在请求时查阅它需要映射.
请注意,您可以HandlerMapping在一个上下文中拥有任意数量的实现.他们将被轮流咨询,直到其中一人有比赛.
我知道这真的很旧,但我想我会扔掉这个以防万一其他人有同样的粗略经历,我试图使这项工作成功。我最终利用了 Spring 的两个特性:在上下文启动后动态注册 bean 的能力和对象afterPropertiesSet()上的方法RequestMappingHandlerMapping。
当RequestMappingHandlerMapping初始化时,它会扫描环境和创建地图所有的@RequestMappings表示它需要服务(大概是因为性能原因)。如果您动态注册带有 注释的 bean @Controller,它们将不会被选中。要重新触发此扫描,您只需afterPropertiesSet()在添加 bean 后调用。
在我的特定用例中,我@Controller在单独的 Spring 上下文中实例化了新对象,并需要将它们连接到我的 WebMvc 上下文中。对象的细节对此无关紧要,您只需要一个对象引用:
//register all @Controller beans from separateContext into webappContext
separateContext.getBeansWithAnnotation(Controller.class)
.forEach((k, v) -> webappContext.getBeanFactory().registerSingleton(k, v));
//find all RequestMappingHandlerMappings in webappContext and refresh them
webappContext.getBeansOfType(RequestMappingHandlerMapping.class)
.forEach((k, v) -> v.afterPropertiesSet());
Run Code Online (Sandbox Code Playgroud)
例如,您还可以这样做:
//class annotated with @Controller
MyController controller = new MyController
//register new controller object
webappContext.getBeanFactory().registerSingleton("myController", controller);
//find all RequestMappingHandlerMappings in webappContext and refresh them
webappContext.getBeansOfType(RequestMappingHandlerMapping.class)
.forEach((k, v) -> v.afterPropertiesSet());
Run Code Online (Sandbox Code Playgroud)
以下构造在单个类中配置和实现处理程序方法。
它是动态的和静态映射的组合-所有MVC注释可用于像 @RequestParam, @PathVariable,@RequestBody等。
顺便说一句:@RestController注释从类中创建 bean 并添加@ResponseBody到每个处理程序方法中,因此不必手动完成。
@RestController
public class MyController {
@Inject
private RequestMappingHandlerMapping handlerMapping;
/***
* Register controller methods to various URLs.
*/
@PostConstruct
public void init() throws NoSuchMethodException {
/**
* When "GET /simpleHandler" is called, invoke, parametrizedHandler(String,
* HttpServletRequest) method.
*/
handlerMapping.registerMapping(
RequestMappingInfo.paths("/simpleHandler").methods(RequestMethod.GET)
.produces(MediaType.APPLICATION_JSON_VALUE).build(),
this,
// Method to be executed when above conditions apply, i.e.: when HTTP
// method and URL are called)
MyController.class.getDeclaredMethod("simpleHandler"));
/**
* When "GET /x/y/z/parametrizedHandler" is called invoke
* parametrizedHandler(String, HttpServletRequest) method.
*/
handlerMapping.registerMapping(
RequestMappingInfo.paths("/x/y/z/parametrizedHandler").methods(RequestMethod.GET)
.produces(MediaType.APPLICATION_JSON_VALUE).build(),
this,
// Method to be executed when above conditions apply, i.e.: when HTTP
// method and URL are called)
MyController.class.getDeclaredMethod("parametrizedHandler", String.class, HttpServletRequest.class));
}
// GET /simpleHandler
public List<String> simpleHandler() {
return Arrays.asList("simpleHandler called");
}
// GET /x/y/z/parametrizedHandler
public ResponseEntity<List<String>> parametrizedHandler(
@RequestParam(value = "param1", required = false) String param1,
HttpServletRequest servletRequest) {
return ResponseEntity.ok(Arrays.asList("parametrizedHandler called", param1));
}
}
Run Code Online (Sandbox Code Playgroud)
请看我的解决方案。它不会@RequestMapping在您的代码中创建动态,但提供了一个处理所有请求的HandlerMapping和。Controller如果运行该应用程序,您将收到 json 格式的 hello world 消息。
应用类:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MyCustomHandler myCustomHandler(MyCustomController myCustomController) {
MyCustomHandler myCustomHandler = new MyCustomHandler(myCustomController);
myCustomHandler.setOrder(Ordered.HIGHEST_PRECEDENCE);
return myCustomHandler;
}
}
Run Code Online (Sandbox Code Playgroud)
我的自定义控制器
@Component
public class MyCustomController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().println("{\"hello\":\"world\"}");
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我的自定义处理程序
public class MyCustomHandler extends AbstractHandlerMapping {
private MyCustomController myCustomController;
public MyCustomHandler(MyCustomController myCustomController) {
this.myCustomController = myCustomController;
}
@Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
return myCustomController;
}
}
Run Code Online (Sandbox Code Playgroud)
https://github.com/nowszy94/spring-mvc-dynamic-controller
我花了很长时间尝试使它起作用,但最终设法找到一个返回a ResponseEntity而不是较旧的解决方案ModelAndView。此解决方案还具有避免与进行任何显式交互的附加好处Application Context。
终端服务
@Service
public class EndpointService {
@Autowired
private QueryController queryController;
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
public void addMapping(String urlPath) throws NoSuchMethodException {
RequestMappingInfo requestMappingInfo = RequestMappingInfo
.paths(urlPath)
.methods(RequestMethod.GET)
.produces(MediaType.APPLICATION_JSON_VALUE)
.build();
requestMappingHandlerMapping.
registerMapping(requestMappingInfo, queryController,
QueryController.class.getDeclaredMethod("handleRequests")
);
}
}
Run Code Online (Sandbox Code Playgroud)
控制器处理新映射的请求
@Controller
public class QueryController {
public ResponseEntity<String> handleRequests() throws Exception {
//Do clever stuff here
return new ResponseEntity<>(HttpStatus.OK);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14650 次 |
| 最近记录: |