Spring MVCの高度な技術

19756 ワード

一、multipart形式のデータを処理する
1、multipart解析器の配置
Springに内蔵されている2つの解析器:
  • CommonsMultipartResolver:Jakarta Commons FileUpload解析
  • を使用
  • StandardServletMultipartResolver:Multipart要求に対するサーブレット3.0のサポートに依存(Spring 3.1から)
  • StandardServiceletMultipartResolver multipart解析器の構成
    構成StandardServletMultipartResolverは、ファイルがアップロードする一時ディレクトリ、すなわちwebでなければならないことを指定しなければならない.xmlまたはサーブレット初期化クラスでは、Multipartの詳細をDispatcherサーブレット構成の一部とします.
    DispatcherServiceletを構成するサーブレット初期化クラスがWebApplicationInitializerを実装している場合、setMultipartConfig()メソッドをサーブレットregistrationで呼び出し、MultipartConfig - Elementインスタンスを送信することができる.
       @Override
       public void onStartup(ServletContext servletContext) throws ServletException {
       
           DispatcherServlet dispatcherServlet = new DispatcherServlet();
           ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServler", ds);
           registration.addMapping("/");
           registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));
       }
    

    初期化クラスがAbstractAnnotationConfigDispatcherServletInitializerまたはAbstractDispatcherServletInitializerを継承している場合、multopartの具体的な詳細は、customizeRegistration()を再ロードすることによって構成することができる.
       @Override
       protected void customizeRegistration(ServletRegistration.Dynamic registration) {
           registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));
       }
    

    xml構成
     <servlet>
           <servlet-name>springDispatcherServletservlet-name>
           <servlet-class>org.springframework.web.servlet.DispatcherServlet
           servlet-class>
           <load-on-startup>1load-on-startup>
           <multipart-config>
               <location>/tmp/uploadslocation>
               <max-file-size>2097152max-file-size>
               <max-request-size>4194304max-request-size>
           multipart-config>
       servlet>
    

    CommonsMultipartResolver multipart解析器の構成
    通常、StandardServletMultipartResolverが最適ですが、アプリケーションがサーブレット3.0以外のコンテナに配備されている場合は、この代わりに使用できます.CommonsMultipartResolver一時ファイルパスは強制的に設定されず、デフォルトの一時ファイルパスはサーブレットコンテナの一時ディレクトリです.
    	/**
         *    multipart    
         */
        @Bean
        public MultipartResolver multipartResolver() throws IOException {
            CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
            //          Servlet        
            commonsMultipartResolver.setUploadTempDir(new FileSystemResource("/temp/uploads"));
            commonsMultipartResolver.setMaxUploadSize(2097152);
            commonsMultipartResolver.setMaxInMemorySize(0);
            return commonsMultipartResolver;
        }
    

    2、Multipart要求の処理
    MultipartFile Springを受け入れるとMultipartFileインタフェースが提供され、アップロードファイルbyteだけでなく、元のファイル名、サイズ、ファイル内容も取得できます.InputStreamも提供され、ファイルをストリームで読み取ることができます.これに加えて、アップロードされたファイルをファイルシステムに書き込むことができるtransferTo()の方法も提供される.
    myFile.transferTo(new File("/file/uploads/" +myFile.getOriginalFilename()));
    

    Part形式でアップロードを受け付けているファイルはコントローラ作成時にPartパラメータ形式でファイルアップロードを受け付けていればMultipartResolverを構成する必要はなく、MultipartFileを使用している場合のみ構成する必要があります.
    二、処理異常
    Springでは、例外を応答に変換する方法がいくつかあります.
  • 特定のSpring異常は、指定されたHttpステータスコードに自動的にマッピングされます.
  • 異常には、@ResponseStatus注記を追加して、Httpステータスコードにマッピングすることができる.
  • は、方法上、@ExceptionHandler注釈を追加して、異常を処理するために使用することができる.

  • 1、異常をHttp状態コードにマッピングする
    Springに組み込まれているマッピングに加えて、注釈マッピングなどを使用できます.
    @ResponseStatus(value = HttpStatus.NOT_FOUND,reason = "user not found")
    public class UserNotFoundException extends RuntimeException{
    }
    
    UserNotFoundException異常が放出されると、応答は404ステータスコードを有する.
    2、異常処理の作成方法
    応答に発生したエラーを含める必要がある場合は,異常をHTTPエラーと見なすのではなく,処理要求に応じて異常を処理する必要がある.
    	@ExceptionHandler({UserNotFoundException.class})
        @ResponseBody
        public String handleUserNotFound(){
            return  "user not found";
        }
    
    @ExceptionHandler注記表示されたメソッドは、同じコントローラ内のすべてのプロセッサメソッドが放出する指定された例外を処理できます.
    3、コントローラに通知を追加する
    複数のコントローラから特定の例外が投げ出される場合は、すべてのコントローラで同じ@ExceptionHandlerメソッドを繰り返すか、重複を避けるためにベースコントローラクラスを作成し、クラスを継承する必要があります.Spring 3.2では、コントローラ通知という新しいソリューションが導入されました.コントローラ通知は、@ControllerAdvice注記のある任意のクラスであり、このクラスには次のようなタイプのメソッドが1つ以上含まれる.
  • @ExceptionHandler注記表記の方法
  • @InitBinder表記の方法
  • @ModelAttribute表記の方法.以上の方法は、アプリケーション全体のすべてのコントローラに@RequestMapping注記がある方法に適用されます.@ControllerAdvice自体はすでに@Component注釈を使用しており、自動的にスキャンされます.最も実用的なシーンは、統合例外処理であり、@ExceptionHandlerのすべての方法を1つのクラスに収集する
  • である.
    @ControllerAdvice
    public class AppWideExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public String hasException(){
            return  "has exception";
        }
    }
    

    4、リダイレクト要求にまたがってデータを転送する
    コントローラが返すString値がredirect:で始まると、このStringはビューを検索するのではなく、ブラウザにリダイレクト操作を指導するために使用されます.リダイレクト機能を開始する方法リダイレクトのターゲットメソッドにデータを送信する方法一般に、プロセッサメソッドが完了すると、メソッドで指定したモデルデータがリクエストにコピーされ、リクエストのプロパティとしてビューに転送されてレンダリングされます.しかし、コントローラの結果がリダイレクトされると、元のリクエストは終了し、新しいGETリクエストが開始されます.元のリクエストに含まれるモデルデータも消滅します.リダイレクト・モデルでは、データを転送するために使用できません.他のスキームでは、データを転送できます.
  • URLテンプレートを使用して、パス変数および/またはクエリーパラメータとしてデータを渡す.
  • は、flashプロパティを介してデータを送信します.

  • URLテンプレートでリダイレクトを行うには、直接Stringを接続することができます.URLやSQLクエリー文を構築する場合、String接続を使用するのは危険です.return "redirect:/user/" + user.getUseName;に加えて、Springはテンプレートを使用してリダイレクトを定義するURLも提供します.例:
    //        
    model.addAttribute("userid",user.getUserId());
    return "redirect:/user/{username}";
    

    usernameは、直接文字列をつなぐのではなく、プレースホルダとしてURLテンプレートに埋め込まれるため、usernameのすべての不安全な文字がエスケープされ、より安全になります.model.addAttribute("username",user.getUserName());が追加されたが、URLに一致するプレースホルダがない場合、リダイレクトURLにクエリーパラメータが自動的に添付されます.たとえばusernameがcedarの場合、リダイレクトurlパスは/user/cedar?id=1です.flashプロパティを使用して、特定のプロパティではなくオブジェクト全体を渡す場合は、オブジェクトをセッションに配置し、リダイレクトしてクリーンアップします.Springは、これらのデータを自分で管理することなく、flashプロパティにデータを送信する機能を提供します.falshプロパティは、次のリクエストまでデータを携帯し、自動的に消えます.Springは、RedirectAttributesaddFlashAttribute()メソッドでモデルにオブジェクトを追加します.
        @RequestMapping(value = "/userInfo" , method = RequestMethod.GET)
        public String  userInfo(String userId, RedirectAttributes model){
            User user = userService.getUserById(userId);
            model.addAttribute("userid",user.getId());
            //  user         ,    key             
            model.addFlashAttribute("user",user);
            return  "redirect:/user/{userid}";
        }
        
        /**
         *    flash       
         * @param username
         * @param model
         * @return
         */
        @RequestMapping(value = "/showProfile" , method = RequestMethod.GET)
        public  String showProfile(@PathVariable String userid, Model model){
            if (!model.containsAttribute("user")){
                model.addAttribute(userService.getUserById(userid));
            }
            return "profile";
        }