前提・実現したいこと
Spring-Bootを使用したCMSの開発を行っています。
プログラムからrequestやresponse、sessionの情報にアクセスする場合、
0. RequestMappingされた関数(メソッド)の引数として受け取る
0. 使用するBeanにDIする
の2つの方法がとれると思いますが、これらの動作上の相違点はありますでしょうか?
開発中のシステムの特性上、できれば後者の方法を取りたいのですが、社内に後者の方法をとった事例がなく、注意点などあればご教示いただきたいです。
kotlin
1@Controller 2class PageController { 3 4 // RequestMappingされた関数(メソッド)の引数として受け取る 5 @RequestMapping("/page") 6 fun getPage( 7 request: HttpServletRequest, 8 response: HttpServletResponse, 9 session: HttpSession 10 ): ModelAndView? { 11 12 // 以下略
kotlin
1@Controller 2class PageController( 3 // 使用するBeanにDIする 4 var request: HttpServletRequest, 5 var response: HttpServletResponse, 6 var session : HttpSession 7) { 8 9 // 以下略
なお、後者の方法を取りたい理由は、システムの特性上ControllerだけでなくService等のbeanからもrequest/response/sessionにアクセスしたいケースが多く、Controllerで取得した情報を各beanに引き回すことを避けるためです。
試したこと
一応、上記両方の方法で動作することを確認しています。
後者の方法では、
・RequestContextHolder.currentRequestAttributes().getRequest()
・RequestContextHolder.currentRequestAttributes().getResponse()
で取得したrequest/responseを使っていて、それが前者の方法で引数から受け取ったオブジェクトと同じものであることはわかりましたが、どこの設定でそのような動作になるのかまでは突き止めていません。
試したこと(追記)
「同時アクセスしたらわかるのではないか」と指摘をいただきましたので、実験してみました。
kotlin
1package test 2 3import org.springframework.stereotype.Controller 4import org.springframework.web.bind.annotation.RequestMapping 5import java.util.* 6import javax.servlet.http.HttpServletRequest 7 8@Controller 9class PageController(val requestD: HttpServletRequest) { 10 11 @RequestMapping("/page") 12 fun getPage(requestA: HttpServletRequest): String? { 13 14 // ランダム値とハッシュコード 15 val hashCode = this.hashCode() 16 val uuid = UUID.randomUUID().toString() 17 println("初期:$uuid hashCode:$hashCode") 18 19 // ランダム値をsessionに格納 20 requestA.session.setAttribute("test", uuid) 21 22 // 1000ミリ秒間隔で一致確認 23 for (i in 1..5) { 24 Thread.sleep(1000) 25 val a = requestA.session.getAttribute("test") as String 26 val d = requestD.session.getAttribute("test") as String 27 val compare = if (a == d) "一致" else "不一致" 28 println("引数:$a DI: $d $compare") 29 } 30 return null 31 } 32}
以下、二つのブラウザからなるべく同時にアクセスした際のコンソールです。
初期:1bc4c09e-383b-4b4f-a029-ce6e42c971cb hashCode:81445899 初期:231966be-a4c7-4451-9550-f75ad637782e hashCode:81445899 引数:1bc4c09e-383b-4b4f-a029-ce6e42c971cb DI: 1bc4c09e-383b-4b4f-a029-ce6e42c971cb 一致 引数:231966be-a4c7-4451-9550-f75ad637782e DI: 231966be-a4c7-4451-9550-f75ad637782e 一致 引数:1bc4c09e-383b-4b4f-a029-ce6e42c971cb DI: 1bc4c09e-383b-4b4f-a029-ce6e42c971cb 一致 引数:231966be-a4c7-4451-9550-f75ad637782e DI: 231966be-a4c7-4451-9550-f75ad637782e 一致 引数:1bc4c09e-383b-4b4f-a029-ce6e42c971cb DI: 1bc4c09e-383b-4b4f-a029-ce6e42c971cb 一致 引数:231966be-a4c7-4451-9550-f75ad637782e DI: 231966be-a4c7-4451-9550-f75ad637782e 一致 引数:1bc4c09e-383b-4b4f-a029-ce6e42c971cb DI: 1bc4c09e-383b-4b4f-a029-ce6e42c971cb 一致 引数:231966be-a4c7-4451-9550-f75ad637782e DI: 231966be-a4c7-4451-9550-f75ad637782e 一致 引数:1bc4c09e-383b-4b4f-a029-ce6e42c971cb DI: 1bc4c09e-383b-4b4f-a029-ce6e42c971cb 一致 引数:231966be-a4c7-4451-9550-f75ad637782e DI: 231966be-a4c7-4451-9550-f75ad637782e 一致
引数のリクエスト(requestA)から取得したセッションの値と、DI(コンストラクタインジェクション)したリクエスト(requestD)から取得したセッションの値が常に一致していますので、DIされたHttpServletRequestはスレッドセーフであることがわかりました。
補足情報(FW/ツールのバージョンなど)
spring-boot:ver 2.1.7
Kotlin:ver 1.3.50
回答2件
あなたの回答
tips
プレビュー