在服务中引发异常时在何处加载grails消息
如果grails服务抛出异常,UI消息元素的分离应该在哪里?消息应该由服务加载并通过异常传递给控制器,还是控制器应该根据抛出的异常类型加载消息?这假设消息将有一些需要填写的参数值 这里有一个例外:在服务中引发异常时在何处加载grails消息,grails,Grails,如果grails服务抛出异常,UI消息元素的分离应该在哪里?消息应该由服务加载并通过异常传递给控制器,还是控制器应该根据抛出的异常类型加载消息?这假设消息将有一些需要填写的参数值 这里有一个例外: class CustomException extends RuntimeException { String message } class MyService { void doSomething() { ... if (somethingBad)
class CustomException extends RuntimeException {
String message
}
class MyService {
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(value)
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
render view:'some_gsp'
}
...
}
}
class MyService {
def messageSource
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(messageSource.getMessage('thread.inactive.user', [value]))
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = e.message
render view:'some_gsp'
}
...
}
}
捕获异常后从控制器加载消息源:
class CustomException extends RuntimeException {
String message
}
class MyService {
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(value)
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
render view:'some_gsp'
}
...
}
}
class MyService {
def messageSource
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(messageSource.getMessage('thread.inactive.user', [value]))
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = e.message
render view:'some_gsp'
}
...
}
}
从控制器从异常中提取消息字符串的服务中的消息源加载错误:
class CustomException extends RuntimeException {
String message
}
class MyService {
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(value)
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
render view:'some_gsp'
}
...
}
}
class MyService {
def messageSource
void doSomething() {
...
if (somethingBad) {
String value = 'Mary Smith'
throw new CustomException(messageSource.getMessage('thread.inactive.user', [value]))
}
...
}
}
class MyController {
def myService
void processRequest() {
try {
myService.doSomething()
}
catch (CustomException e) {
flash.error = e.message
render view:'some_gsp'
}
...
}
}
坦率地说,这两个地方都不需要翻译 关注点分离
控制器应该只关心HTTP方法及其委托。
服务应该负责事务和底层业务逻辑 声明性错误处理
对于
2.0.*
及以上版本,Grails为您提供了处理错误的最佳选择。你猜怎么着
所有与异常相关的代码都会转移到一个单独的控制器(内部),在那里它们会得到正确的处理,从而保持您的业务控制器和服务干净,并从锅炉板代码中抽象出来
对于Grails2.3.*
,控制器本身中有一个,但大多数锅炉板(try-catch)都是从控制器实现中抽象出来的
结论如果您使用的是
v2.0.*
及更高版本,那么您的控制器看起来像:
class MyController {
def myService
def processRequest() {
myService.doSomething()
...
}
}
//URL Mapping
static mappings = {
"500"(controller: "errors", action: "customException",
exception: CustomException)
}
//Error Controller
class ErrorsController {
def customException() {
def exception = request.exception
// perform desired processing to handle the exception
}
}
class MyController {
def myService
def processRequest() {
myService.doSomething()
...
}
def handleCustomException(CustomException e) {
//Move this translation to src/groovy/utility if feasible
flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
render view:'some_gsp'
}
}
如果需要,您可以将错误处理逻辑移动到单独的插件,以处理各种错误/异常和不愉快路径。把这件事分开是很优雅的
如果您使用的是v2.3.*
,则控制器的外观如下:
class MyController {
def myService
def processRequest() {
myService.doSomething()
...
}
}
//URL Mapping
static mappings = {
"500"(controller: "errors", action: "customException",
exception: CustomException)
}
//Error Controller
class ErrorsController {
def customException() {
def exception = request.exception
// perform desired processing to handle the exception
}
}
class MyController {
def myService
def processRequest() {
myService.doSomething()
...
}
def handleCustomException(CustomException e) {
//Move this translation to src/groovy/utility if feasible
flash.error = g.message(code:'user.input.error', args:'[${e.value}]')
render view:'some_gsp'
}
}
在这种情况下,也不需要从服务中进行处理,您只需要经历该异常
我想如果您环顾四周并对使用此模式感兴趣,您也会从各种来源获得更多的输入 视情况而定。这在控制器中更常见,因为这是基于UI的职责。此外,使用服务中的异常来控制事务提交/回滚会对性能造成影响(您真的需要它在每次抛出该异常或任何其他异常时填充整个堆栈吗?记住Grails每次都要填充一个巨大的堆栈…)。例外情况应为例外情况,而非预期情况。