Spring MVCアプリケーションにRESTfulなURLを実装しようとしています。フォーム送信の処理を除き、すべてが順調です。元のフォームまたは「成功」ページにリダイレクトする必要があります。
@Controller
@RequestMapping("/form")
public class MyController {
@RequestMapping(method = RequestMethod.GET)
public String setupForm() {
// do my stuff
return "myform";
}
@RequestMapping(method = RequestMethod.POST)
public String processForm(ModelMap model) {
// process form data
model.addAttribute("notification", "Successfully did it!");
return "redirect:/form";
}
}
ただし、 Spring documentation で読んだように、リダイレクトするとパラメータがURLに追加されます。そして、それは私にとってはうまくいきません。これを回避する最も優雅な方法は何でしょうか?
http://jira.springframework.org/browse/SPR-6464 は、Spring MVCが機能を提供するまで(おそらく3.0.2リリースで)動作させるために必要なものを提供してくれました。クラスを一時的に実装しただけですが、Webアプリケーションコンテキストにフィルターを追加しました。よく働く!
同じ問題がありました。このように解決しました:
return new ModelAndView("redirect:/user/list?success=true");
そして、私のコントローラーメソッドは次のようになります:
public ModelMap list(@RequestParam(required=false) boolean success) {
ModelMap mm = new ModelMap();
mm.put(SEARCH_MODEL_KEY, campaignService.listAllCampaigns());
if(success)
mm.put("successMessageKey", "campaign.form.msg.success");
return mm;
}
コレクションなどではなく、単純なデータを送信する場合を除き、完全に機能します。次に、セッションを使用する必要があります。
この問題は、他の人が述べているように、モデル属性がクエリ文字列に永続化されることによって引き起こされます-これは通常望ましくなく、セキュリティホールやばかげたクエリ文字列を作成するリスクがあります。私の通常の解決策は、Spring MVCでリダイレクトに文字列を使用せず、代わりにモデル属性を公開しないように構成できるRedirectViewを使用することです(参照: http://static.springsource.org/spring/docs/3.1。 x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html )
RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes)
だから私は次のような「安全なリダイレクト」を行うutilメソッドを持つ傾向があります:
public static RedirectView safeRedirect(String url) {
RedirectView rv = new RedirectView(url);
rv.setExposeModelAttributes(false);
return rv;
}
もう1つのオプションは、Bean構成XMLを使用することです。
<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView">
<property name="exposeModelAttributes" value="false" />
<property name="url" value="/myRedirect"/>
</bean>
繰り返しますが、繰り返しを避けるためにこれを独自のクラスに抽象化することができます(例:SafeRedirectView)。
「モデルのクリア」に関する注意-これは、すべての状況で「モデルを公開しない」ことと同じではありません。私が取り組んだサイトには、モデルに物事を追加する多くのフィルターがありました。これは、リダイレクトする前にモデルをクリアしても、長いクエリ文字列が妨げられないことを意味しました。また、「モデル属性を公開しない」ことは、「リダイレクトする前にモデルをクリアする」よりも意味論的なアプローチであることをお勧めします。
代わりにprocessForm()
がViewオブジェクトを返し、setExposeModelAttributes()
のパラメータを持つ具象型RedirectView
を返すことができます。
"redirect:"
というプレフィックスが付いたビュー名を返すと、Spring MVCはこれをRedirectView
オブジェクトに変換しますが、setExposeModelAttributes
をtrueに変換するだけです(デフォルトでは奇数の値だと思います)に)。
成功メッセージをURLに含めたくない場合は、1つのオプションとして、それをセッション(processFormメソッド)に入れてから、setupFormメソッドで確認(および削除)することができます。
追加して編集:これが手動で行うのが面倒な場合、「メッセージ」属性を追加し、セッションに挿入するプロセスをラップするRedirectViewのサブクラスを作成できます。ただし、セッションからメッセージを戻す簡単な方法があるかどうかはわかりません...
正直なところ、簡単な答えはないと思います。HTTPリダイレクトの性質は、状態が引き継がれないことです。とにかく状態を維持したい場合、Webアプリケーションの状態を維持するためのさまざまな通常の方法に固執しています:セッション、Cookie、クエリ文字列...
HttpServletRequestオブジェクトを使用してパラメータを送信するためにモデルを使用する代わりに、1つの簡単なことを行うことができます
HttpServletRequest request;
request.setAttribute("param", "value")
これで、パラメータがURLヘッダーに表示されなくなります。
@RequestMapping(path="/apps/add", method=RequestMethod.POST)
public String addApps(String appUrl, Model model, final RedirectAttributes redirectAttrs) {
if (!validate(appUrl)) {
redirectAttrs.addFlashAttribute("error", "Validation failed");
}
return "redirect:/apps/add"
}
@RequestMapping(path="/apps/add", method=RequestMethod.GET)
public String addAppss(Model model) {
String error = model.asMap().get("error");
}