gpt4 book ai didi

java - 使用一个 Controller 管理多个资源的优缺点

转载 作者:行者123 更新时间:2023-12-01 22:16:07 26 4
gpt4 key购买 nike

我们有一个 Spring MVC 应用程序,大多数 REST 操作是每个资源唯一的 GET 操作。所以目前我们有许多 Controller 只有 GET 方法,彼此没有区别(即使在 url、内容类型、参数等方面)。

为了消除这样的重复,我们的队友提出让一个 Controller 只具有 GET 操作和一个具有服务的 map (资源名称 -> 资源服务)。

但我们看到了这样的缺点,如更复杂的 Spring 注入(inject)调优,没有机会添加一些内容类型、参数的限制——一言以蔽之自定义操作。此外,还有一些资源将驻留在单独的 Controller 中。此外,我不希望至少有简单的方法以多种方式记录 Swagger 中的唯一方法(有不同的描述)。

所以对我来说,一方面是代码较少,但另一方面是操作定制、架构混合、缺乏适当的文档或至少是复杂的配置的机会有限。我不认为在这里制定一个方法是一个好方法。

我说的对吗?如果是这样,我该如何证明。如果不是为什么?感谢您的宝贵时间和想法!

最佳答案

是的,你是对的。简而言之,根据 single responsibility principle每个 Controller 应该只做一项工作(只处理一个 URL)。

您完美地描述了通用 Controller 可以处理的问题。还要考虑如果某些 Controller 现在完全符合通用规则但下个月需要特定的东西怎么办?您必须复制粘贴代码,然后添加新代码。因此,一段时间后,您会遇到大量复杂的通用 Controller 重复代码。没有人能预测它的速度有多快,因为可能会为开发团队意外添加业务需求。

另一方面,您的队友减少重复代码的愿望是正确的。至少不是所有的开发人员都愿意花时间让代码更干净。大多数人需要获得认可(确保他们的意见有值(value))。所以不要把他送走:)

我可以推荐的是:引入抽象父代并使用继承和 Template类似 Controller 的模式

/** Interface mainly works as a marker. 
At first look, interface isn't necessary but it'll improve maintainability.
Next year you say 'thank you' to yourself */
interface IController {
//some methods which will implement EACH controller even the most specific
public void doGet(params)
}
abstract class AbstractController implements IController {
/** Class implements default behavior for controllers.
Implementation written so child classes could adopt behaviour easily*/
@Override
public void doGet(params) {
// use Template pattern
doLog(params);
prepareStuff();
process();
}
// common stuff which should be done at first
protected void doLog(params) { // your favorite logger here}
// extension point for inherited classes
abstract protected void prepareStuff();
// here is the real processing for default controller
public void process() {
//implement common processing for GET request
}
// Prefer to use protected method instead of field
protected String getURL() { return DEFAULT_URL;}
}
// usual controller has nothing special
class Controller1 extends AbstractController {
@Override
protected String getURL() { return "url1";}
@Override
protected prepareStuff() {// do nothing}
}
// do some specific preparation/checks
class Controller2 extends AbstractController {
@Override
protected prepareStuff() {//preparation/checks here }
/** Note I 'forget' to override getURL() so it'll process DEFAULT_URL.
It could be useful if AbstractController calculates url dynamically and
you don't want to write boilerplate strings "/myApp/section7".
Also you could write abstract getURL()
*/
}
/** custom controller but you want to re-use some common code.
In fact I would not recommend this way as usual approach */
class Controller3 extends AbstractController {
/** Overriding this method totally discards the Template pattern.
It could (and will) lead to confusing and errors*/
@Override
public void doGet(params) { // new implementation }
@Override
protected prepareStuff() {
// you don't need it but you have to override since it abstract
}
}
// totally custom controller. Implements interface just as a marker
class SpecificController implements Controller {
// In order to support legacy code just call method wich has been already written. You even no need to rename it.
@Override
public void doGet(params) { specificMethod();}
// lagacy method which probably is used somewhere else
public void specificMethod() { // the actual logic here}
}

事实上,我认为在一个项目中有类似的解决方案。使用“引入方法”和“移至父级”等 IDE 功能,我在一天内重构了数十个类。

希望你或你的队友能在几天内实现并比较这样的想法

关于java - 使用一个 Controller 管理多个资源的优缺点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45714481/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com