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

谁说胖子不能爱 提交于 2019-12-03 06:42:07

问题


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?

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


回答1:


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.

@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.

label_user_saved_successfully=Successfully saved user: {0}

Edit your jspx file to use the relevant attribute

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



回答2:


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

I like to use a session scoped flash object:

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:

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:

<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.




回答3:


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.

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

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




回答4:


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.




回答5:


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

<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

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

or

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




回答6:


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:

... 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 ...



回答7:


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).



来源:https://stackoverflow.com/questions/2704099/status-messages-on-the-spring-mvc-based-site-annotation-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!