wil*_*-ob 38 spring spring-mvc spring-boot
有没有理由不将控制器映射为接口?
在所有示例和问题中,我看到周围的控制器,都是具体的类.是否有一个原因?我想将请求映射与实现分开.当我试图@PathVariable在我的具体课程中获得一个参数时,我碰到了一堵墙.
我的Controller界面如下所示:
@Controller
@RequestMapping("/services/goal/")
public interface GoalService {
@RequestMapping("options/")
@ResponseBody
Map<String, Long> getGoals();
@RequestMapping(value = "{id}/", method = RequestMethod.DELETE)
@ResponseBody
void removeGoal(@PathVariable String id);
}
Run Code Online (Sandbox Code Playgroud)
而实施班:
@Component
public class GoalServiceImpl implements GoalService {
/* init code */
public Map<String, Long> getGoals() {
/* method code */
return map;
}
public void removeGoal(String id) {
Goal goal = goalDao.findByPrimaryKey(Long.parseLong(id));
goalDao.remove(goal);
}
}
Run Code Online (Sandbox Code Playgroud)
该getGoals()方法效果很好; 在removeGoal(String id)抛出一个异常
ExceptionHandlerExceptionResolver - Resolving exception from handler [public void
todo.webapp.controllers.services.GoalServiceImpl.removeGoal(java.lang.String)]:
org.springframework.web.bind.MissingServletRequestParameterException: Required
String parameter 'id' is not present
Run Code Online (Sandbox Code Playgroud)
如果我将@PathVariable注释添加到具体类中,一切都按预期工作,但为什么我必须在具体类中重新声明它?它不应该由具有@Controller注释的任何东西处理吗?
wil*_*-ob 26
显然,当请求模式通过@RequestMapping注释映射到方法时,它将映射到具体的方法实现.因此,与声明匹配的请求将GoalServiceImpl.removeGoal()直接调用,而不是最初声明@RequestMappingie 的方法GoalService.removeGoal().
由于接口,接口方法或接口方法参数上的注释不会延续到实现,因此@PathVariable除非实现类明确声明,否则Spring MVC无法将其识别为.没有它,任何以@PathVariable参数为目标的AOP建议都不会被执行.
小智 8
它适用于较新版本的Spring.
import org.springframework.web.bind.annotation.RequestMapping;
public interface TestApi {
@RequestMapping("/test")
public String test();
}
Run Code Online (Sandbox Code Playgroud)
在Controller中实现接口
@RestController
@Slf4j
public class TestApiController implements TestApi {
@Override
public String test() {
log.info("In Test");
return "Value";
}
}
Run Code Online (Sandbox Code Playgroud)
它可以用作: Rest客户端
实际上在Spring 5.1.5中已实现了在接口上定义所有绑定的功能。
请查看此问题:https : //github.com/spring-projects/spring-framework/issues/15682-这很挣扎:)
现在您可以实际执行以下操作:
@RequestMapping("/random")
public interface RandomDataController {
@RequestMapping(value = "/{type}", method = RequestMethod.GET)
@ResponseBody
RandomData getRandomData(
@PathVariable(value = "type") RandomDataType type, @RequestParam(value = "size", required = false, defaultValue = "10") int size);
}
Run Code Online (Sandbox Code Playgroud)
@Controller
public class RandomDataImpl implements RandomDataController {
@Autowired
private RandomGenerator randomGenerator;
@Override
public RandomData getPathParamRandomData(RandomDataType type, int size) {
return randomGenerator.generateRandomData(type, size);
}
}
Run Code Online (Sandbox Code Playgroud)
您甚至可以使用此库:https : //github.com/ggeorgovassilis/spring-rest-invoker
要获得基于该接口的客户端代理,类似于RestEasys客户端框架在JAX-RS领域中的工作方式。
| 归档时间: |
|
| 查看次数: |
28450 次 |
| 最近记录: |