Java 基于 Spring MVC 的站点(注解控制器)上的状态消息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2704099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:02:08  来源:igfitidea点击:

Status messages on the Spring MVC-based site (annotation controller)

javaspring-mvccontrollerannotations

提问by olegflo

What is the best way to organize status messages ("Your data has been successfully saved/added/deleted") on the Spring MVC-based site using annotation controller?

使用注释控制器在基于 Spring MVC 的站点上组织状态消息(“您的数据已成功保存/添加/删除”)的最佳方法是什么?

So, the issue is in the way of sending the message from POST-method in contoller.

因此,问题在于从控制器中的 POST 方法发送消息的方式。

采纳答案by krishnakumarp

As mentioned by muanis, since spring 3.1, the best approach would be to use RedirectAttributes. I added i18n to the sample given in the blog. So this would be a complete sample.

正如 muanis 所提到的,从 spring 3.1 开始,最好的方法是使用 RedirectAttributes。我在博客中给出的示例中添加了 i18n。所以这将是一个完整的样本。

@RequestMapping("/users")
@Controller
public class UsersController {

            @Autowired
            private MessageSource messageSource;

            @RequestMapping(method = RequestMethod.POST, produces = "text/html")
            public String create(@Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, Locale locale, RedirectAttributes redirectAttributes) {
                ...
                ...
                redirectAttributes.addFlashAttribute("SUCCESS_MESSAGE", messageSource.getMessage("label_user_saved_successfully", new String[] {user.getUserId()}, locale));
                return "redirect:/users/" + encodeUrlPathSegment("" + user.getId(), httpServletRequest);
            }
    ...
    ...
}

Add appropriate message in your message bundle, say messages.properties.

在您的消息包中添加适当的消息,例如 messages.properties。

label_user_saved_successfully=Successfully saved user: {0}

Edit your jspx file to use the relevant attribute

编辑您的 jspx 文件以使用相关属性

<c:if test="${SUCCESS_MESSAGE != null}">
  <div id="status_message">${SUCCESS_MESSAGE}</div>
</c:if> 

回答by Robby Pond

You should keep it simple and use the specific HTTP 1.1 Status codes. So for a successful call you would return a 200 OK. And on the client side if you want to show a specific message to the user when the controller returns a 200, then you show it there.

您应该保持简单并使用特定的 HTTP 1.1 状态代码。因此,对于成功调用,您将返回 200 OK。在客户端,如果您想在控制器返回 200 时向用户显示特定消息,则可以在此处显示。

回答by Leonid

If you mean that the page is reloaded after some POST, you can include a flag in you view (JSP or velocity or whatever you use). E.g. something like this

如果您的意思是在某些 POST 后重新加载页面,您可以在视图中包含一个标志(JSP 或 Velocity 或您使用的任何东西)。例如这样的事情

<c:if test="${not empty resultMessage}">
 <spring:message code="${resultMessage}" />
</c:if>

And your message bundle should contain a message for that code.

并且您的消息包应包含该代码的消息。

If you do an AJAX POST to submit some data (i.e. page is not reloaded and you need to show a message) you could

如果您执行 AJAX POST 以提交一些数据(即页面未重新加载并且您需要显示一条消息),您可以

1) make you JS files dynamic (JSP or Velocity, again) and insert <spring:message>tags there (I don't really like this option)

1)让你的JS文件动态(JSP或Velocity,再次)并在<spring:message>那里插入标签(我真的不喜欢这个选项)

or

或者

2) follow the advice from this linkand use @ResponseBodyto return a status object to your JS. Inside the object you mark as @ResponseBodyyou can put both status and messages. E.g. using your message bundles as in this case.

2)按照此链接中的建议并使用@ResponseBody将状态对象返回给您的 JS。在您标记的对象内,@ResponseBody您可以放置​​状态和消息。例如,在这种情况下使用您的消息包。

回答by DwB

The simplest means of displaying messages on your JSP is to have a scoped (maybe session, maybe request) object that contains the messages that you want to display. For example you could do the following:

在 JSP 上显示消息的最简单方法是拥有一个包含要显示的消息的范围(可能是会话,可能是请求)对象。例如,您可以执行以下操作:

... java stuff ...
List messages = new ArrayList();
messages.add("some message");
messages.add("some other message");
request.addAttribute("NotableMessages", messages);
... java stuff ...

... jsp and JSTL stuff ...
<c:if test="not empty NotableMessages">
<ul>
<c:forEach items="${NotableMessages}" var="item">
<li>${item}</li>
</c:forEach>
</ul>
</c:if>
... jsp stuff ...

回答by AHungerArtist

Along with an appropriate status code, you could always set a header with the specific message you want. Of course, this is really only a good idea if you have control over how the controller will be used (ie, no third parties).

除了适当的状态代码外,您始终可以使用所需的特定消息设置标题。当然,如果您可以控制控制器的使用方式(即没有第三方),这实际上只是一个好主意。

回答by Philipp Jardas

A proven approach is to use a special flash scope for messages that should be retained until the next GET request.

一种行之有效的方法是对应该保留到下一个 GET 请求的消息使用特殊的 flash 作用域。

I like to use a session scoped flash object:

我喜欢使用会话范围的 flash 对象:

public interface Flash {
    void info(String message, Serializable... arguments);
    void error(String message, Serializable... arguments);
    Map<String, MessageSourceResolvable> getMessages();
    void reset();
}

@Component("flash")
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public class FlashImpl implements Flash {
    ...
}

A special MVC interceptor will read the flash values from the flash object and place them in the request scope:

一个特殊的 MVC 拦截器将从 flash 对象中读取 flash 值并将它们放在请求范围内:

public class FlashInterceptor implements WebRequestInterceptor {
    @Autowired
    private Flash flash;

    @Override
    public void preHandle(WebRequest request) {
        final Map<String, ?> messages = flash.getMessages();
        request.setAttribute("flash", messages, RequestAttributes.SCOPE_REQUEST);

        for (Map.Entry<String, ?> entry : messages.entrySet()) {
            final String key = "flash" + entry.getKey();
            request.setAttribute(key, entry.getValue(), RequestAttributes.SCOPE_REQUEST);
        }

        flash.reset();
    }

    ...
}

Now in your controller you can simply place messages in "flash scope":

现在在您的控制器中,您可以简单地将消息放在“闪存范围”中:

@Conteroller
public class ... {
    @Autowired
    private Flash flash;

    @RequestMapping(...)
    public void doSomething(...) {
        // do some stuff...
        flash.info("your.message.key", arg0, arg1, ...);
    }
}

In your view you iterate over the flash messages:

在您的视图中,您遍历 flash 消息:

<c:forEach var="entry" items="${flash}">
    <div class="flash" id="flash-${entry.key}">
        <spring:message message="${entry.value}" />
    </div>
</c:forEach>

I hope this helps you.

我希望这可以帮助你。

回答by Jose Muanis

After banging my head agains this for a while, I finally made it work.

在再次敲打我的头一段时间后,我终于让它起作用了。

I'm using spring 3.1 and it has support for requestFlashAttributes that are passed across redirects.

我正在使用 spring 3.1,它支持跨重定向传递的 requestFlashAttributes。

The key for solving my problem was to change the return types to strings and not ModelAndView objects.

解决我的问题的关键是将返回类型更改为字符串而不是 ModelAndView 对象。

This guy made an excellent post about using flash messages with spring (http://www.tikalk.com/java/redirectattributes-new-feature-spring-mvc-31)

这家伙发表了一篇关于在 spring 中使用 Flash 消息的出色帖子 (http://www.tikalk.com/java/redirectattributes-new-feature-spring-mvc-31)