Spring MVC インターセプター
今回はインターセプターをやります。これを使うことでリクエストの前後に処理を追加できます。これとセッションを利用してログイン制御処理を作ってみます。
前回をベースに修正を加えていきます。
設定ファイル
applicationContext.xml
Spring設定ファイルでインターセプターの対象となるパスとインターセプトするクラスを宣言します。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<context:component-scan base-package="spring.test.controller" />
<context:component-scan base-package="spring.test.dao" />
<context:component-scan base-package="spring.test.service" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="username" value="postgres" />
<property name="password" value="ps" />
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<mvc:annotation-driven />
<mvc:resources mapping="/image/**" location="/WEB-INF/image/" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="spring.test.Interceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
pom.xmlは前回と同様で、web.xmlは初回と同様です。
クラス
インターセプタークラス
リクエストの前後に呼ばれます。
package spring.test;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String contextPath = request.getContextPath();
if (!request.getRequestURI().equals(contextPath + "/login")) {
UserModel userData = (UserModel) request.getSession().getAttribute("LOGIN");
if (userData == null) {
request.setAttribute("msg", "セッションが切れました。再度ログインして下さい。");
RequestDispatcher dispatch = request.getRequestDispatcher("/login");
dispatch.forward(request, response);
return false;
}
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
}
preHandleは処理前、afterCompletion、postHandleは処理後に呼ばれます。処理前にログインチェックを行うので、preHandleに処理を入れます。
/login以外にアクセスされた場合、セッションにログイン情報が存在しなければ /login に戻されセッション切れのメッセージが表示されます。
ログインコントローラ
前回とほぼ同様ですが、前回からログイン情報を保持する処理を追加しています。
package spring.test.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import spring.test.LoginService;
import spring.test.UserModel;
@Controller
@RequestMapping(value = "/login")
public class LoginControler {
@Autowired
private LoginService loginService;
@ModelAttribute("UM")
public UserModel init() {
return new UserModel();
}
@RequestMapping(method = RequestMethod.GET)
public String loginGet(HttpServletRequest request) {
request.getSession().invalidate();
return "login";
}
@RequestMapping(method = RequestMethod.POST)
public ModelAndView loginPost(@ModelAttribute("UM") UserModel userModel, HttpServletRequest request) {
ModelAndView mv = new ModelAndView("login");
if (loginService.checkLogin(userModel)) {
request.getSession().setAttribute("LOGIN", userModel);
mv = new ModelAndView("redirect:menu");
} else {
mv.addObject("msg", "ログイン失敗");
}
return mv;
}
}
GETでアクセスされたらセッションを破棄し、POSTでアクセスされ認証チェックに通ったらログイン情報をセッションに保持しています。 メニューコントローラ
今回新しく追加しました。実際は、メニュー毎に処理を振り分けますが、今回はメニューを省略してログアウトのみ処理します。
package spring.test.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping(value = "/menu")
public class MenuControler {
@RequestMapping(method = RequestMethod.GET)
public String menuGet(@RequestParam(value = "id", defaultValue = "") String id, HttpServletRequest request) {
if ("logout".equals(id)) {
return "redirect:login";
}
return "menu";
}
}
ログアウトが選択された場合、ログイン画面にリダイレクトさせます。この場合、ログイン画面がGETで呼ばれるので、セッション情報が破棄されます。
Jsp
login.jsp
前回とほぼ同様です。
<%@page import="spring.test.controller.LoginControler"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<title>ログイン</title>
</head>
<body>
<spring:url value="/login" var="url" htmlEscape="true" />
<form:form action="${url}" method="POST" modelAttribute="UM">
ID:<form:input path="id" />
<BR />
<input type="submit" value="ログイン" />
<BR />
</form:form>
${msg}
</body>
</html>
menu.jsp
今回新しく追加しました。実際は、メニューを表示させますが、今回はメニューを省略してログアウトのみ表示しています。
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<title>メニュー</title>
</head>
<body>
<h1>メニュー</h1>
工事中・・・
<br />
<a href="menu?id=logout">ログアウト</a>
</body>
</html>
実際に作るときは工事中・・・の箇所にメニュー情報を出力して下さい。
実行
初期表示
ログインに成功するとメニューが表示されます。

ログインしていない状態でメニューにアクセスするとログイン画面に戻されます。

ページのトップへ戻る