我正在使用现有的代码库,并且在所有控制器方法中都看到了这种模式。开头声明了相同的变量,并将代码放置在try catch块中,所有方法中的代码也相同。我想知道是否有一种方法可以在BaseController中的方法之间推送通用代码。这样我就不必在每个方法中都声明公共变量,并且try catch块功能也可以委托给其他地方。
首先,我创建了一个BaseController类,并用@Controller注释了它,并将我的控制器扩展为其子类。然后,我将所有公共变量移至BaseController。问题是,一旦在控制器的方法中修改了这些变量,即使在下一个有问题的请求中,它们也会保留其值。
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ResponseEntity delete(@PathVariable("id") Integer id)
{
HashMap response = new HashMap();
boolean success = false;
List errors = new ArrayList();
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
String message = "";
try
{
purchaseInvoiceService.delete(id);
success = true;
message = "Purchase Invoice Deleted";
httpStatus = HttpStatus.OK;
} catch (Exception e)
{
errors.add(new ErrorMessage("error", e.getMessage()));
e.printStackTrace();
}
response.put("success", success);
response.put("errors", errors);
response.put("message", message);
return new ResponseEntity(response, httpStatus);
}
我想重构此模式,以便在每种方法中,我只需要仅包含对服务的调用,并有条件地设置成功和httpstatus变量(存在于BaseController中),然后使用存在于其中的response()方法返回响应添加数据变量的BaseController,其返回类型为ResponseEntity。
编辑1: 该端点当前返回所有购买发票的列表,它仅返回HashMap,后者已转换为JSON。我要说明的是,这些响应,成功,错误,httpStatus变量和将所有这些变量放入响应的部分HashMap()是每个控制器内部每个方法的一部分,我也想将它们重构为类似于ResponseFactory的东西。因此,我正在考虑将List传递给ResponseFactory,然后它将构造所有响应并以ResponseEntity的形式返回。只想知道我是否做对了。
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity getAll() {
HashMap response = new HashMap();
boolean success = false;
List errors = new ArrayList();
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
String message = "";
Map data = new HashMap();
try {
List<PurchaseInvoice> purchaseInvoices = purchaseInvoiceService.getAll();
data.put("purchaseInvoices", purchaseInvoices);
success = true;
message = "Purchase Invoice List";
httpStatus = httpStatus.OK;
} catch (Exception e) {
errors.add(new ErrorMessage("error", e.getMessage()));
e.printStackTrace();
}
response.put("success", success);
response.put("errors", errors);
response.put("message", message);
response.put("data", data);
return new ResponseEntity(response, httpStatus);
}
答案 0 :(得分:0)
您的短语:“然后我将所有公共变量移至BaseController” 听起来令人困惑。
spring的控制器只是一个Singleton,由spring提供一个附加的“功能”:它作为Web端点公开(与您的特定问题无关)。
成为Singleton意味着ApplicationContext中有一个实例。
因此,如果变量是这样移动的:
class BaseController {
protected Field1 field1;
protected Field2 field2;
....
}
那么肯定存在问题,您实际上已经向控制器引入了一种状态,并且该状态在所有请求中共享。
长话短说,不要创建有状态的控制器
说重构的想法很好。重构的方式可能是错误的:
相反,我建议考虑以下重构:
使用一些静态方法创建类responseFactory:
class ResponseFactory {
public static ResponseEntity success(String message) {
here prepare the map with boolean success and everything
}
}
现在控制器变为:
class Controller {
public ResponseEntity delete(@PathVariable("id") Integer id) {
purchaseInvoiceService.delete(id); // I'll talk about exceptions later
return ResponseEntityFactory.success("Purchase Invoice Deleted");
}
}
现在关于异常-这有点令人困惑-代码基本上说响应会成功尽管错误。 因此,如果您必须这样处理,则ResponseEntityFactory也必须获取错误列表或其他内容,但总的来说,Spring具有强大的异常处理机制来映射在后端(服务,DAO,有意义的非200响应。