成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

SpringMVC【校驗(yàn)器、統(tǒng)一處理異常、RESTful、攔截器】

marser / 2841人閱讀

摘要:只要有一個攔截器不放行,不能執(zhí)行完成號不放行和號不放行測試結(jié)果總結(jié)只有前邊的攔截器方法放行,下邊的攔截器的才執(zhí)行。至于他們的攔截器鏈的調(diào)用順序,和的是沒有差別的。

前言

本博文主要講解的知識點(diǎn)如下:

校驗(yàn)器

統(tǒng)一處理異常

RESTful

攔截器

Validation

在我們的Struts2中,我們是繼承ActionSupport來實(shí)現(xiàn)校驗(yàn)的...它有兩種方式來實(shí)現(xiàn)校驗(yàn)的功能

手寫代碼

XML配置

這兩種方式也是可以特定處理方法或者整個Action的

而SpringMVC使用JSR-303(javaEE6規(guī)范的一部分)校驗(yàn)規(guī)范,springmvc使用的是Hibernate Validator(和Hibernate的ORM無關(guān))

快速入門

導(dǎo)入jar包

配置校驗(yàn)器


    
    
    
        
        
        
        
    

錯誤信息的校驗(yàn)文件配置

    
    
        
        
            
                classpath:CustomValidationMessages
            
        
        
        
        
        
    

添加到自定義參數(shù)綁定的WebBindingInitializer中

    
    
        
        
    

最終添加到適配器中

    
    
        
        
    

創(chuàng)建CustomValidationMessages配置文件

定義規(guī)則

package entity;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;

public class Items {
    private Integer id;

    //商品名稱的長度請限制在1到30個字符
    @Size(min=1,max=30,message="{items.name.length.error}")
    private String name;

    private Float price;

    private String pic;

    //請輸入商品生產(chǎn)日期
    @NotNull(message="{items.createtime.is.notnull}")
    private Date createtime;

    private String detail;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic == null ? null : pic.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail == null ? null : detail.trim();
    }
}

測試:



<%--
  Created by IntelliJ IDEA.
  User: ozc
  Date: 2017/8/11
  Time: 9:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    測試文件上傳




名稱: 日期:

Controller需要在校驗(yàn)的參數(shù)上添加@Validation注解...拿到BindingResult對象...

    @RequestMapping("/validation")
    public void validation(@Validated Items items, BindingResult bindingResult) {

        List allErrors = bindingResult.getAllErrors();
        for (ObjectError allError : allErrors) {
            System.out.println(allError.getDefaultMessage());
        }

    }

由于我在測試的時候,已經(jīng)把日期轉(zhuǎn)換器關(guān)掉了,因此提示了字符串不能轉(zhuǎn)換成日期,但是名稱的校驗(yàn)已經(jīng)是出來了...

分組校驗(yàn)

分組校驗(yàn)其實(shí)就是為了我們的校驗(yàn)更加靈活,有的時候,我們并不需要把我們當(dāng)前配置的屬性都進(jìn)行校驗(yàn),而需要的是當(dāng)前的方法僅僅校驗(yàn)?zāi)承┑膶傩?/strong>。那么此時,我們就可以用到分組校驗(yàn)了...

步驟:

定義分組的接口【主要是標(biāo)識】

定于校驗(yàn)規(guī)則屬于哪一各組

在Controller方法中定義使用校驗(yàn)分組

統(tǒng)一異常處理

在我們之前SSH,使用Struts2的時候也配置過統(tǒng)一處理異常...

當(dāng)時候是這么干的:

在service層中自定義異常

在action層也自定義異常

對于Dao層的異常我們先不管【因?yàn)槲覀児懿恢?,dao層的異常太致命了】

service層拋出異常,Action把service層的異常接住,通過service拋出的異常來判斷是否讓請求通過

如果不通過,那么接著拋出Action異常

在Struts的配置文件中定義全局視圖,頁面顯示錯誤信息

詳情可看:http://blog.csdn.net/hon_3y/article/details/72772559

那么我們這次的統(tǒng)一處理異常的方案是什么呢????

我們知道Java中的異??梢苑譃閮深?/p>

編譯時期異常

運(yùn)行期異常

對于運(yùn)行期異常我們是無法掌控的,只能通過代碼質(zhì)量、在系統(tǒng)測試時詳細(xì)測試等排除運(yùn)行時異常

而對于編譯時期的異常,我們可以在代碼手動處理異??梢詔ry/catch捕獲,可以向上拋出。

我們可以換個思路,自定義一個模塊化的異常信息,比如:商品類別的異常

public class CustomException extends Exception {
    
    //異常信息
    private String message;
    
    public CustomException(String message){
        super(message);
        this.message = message;
        
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    

}

我們在查看Spring源碼的時候發(fā)現(xiàn):前端控制器DispatcherServlet在進(jìn)行HandlerMapping、調(diào)用HandlerAdapter執(zhí)行Handler過程中,如果遇到異常,在系統(tǒng)中自定義統(tǒng)一的異常處理器,寫系統(tǒng)自己的異常處理代碼。。

我們也可以學(xué)著點(diǎn),定義一個統(tǒng)一的處理器類來處理異常...

定義統(tǒng)一異常處理器類
public class CustomExceptionResolver implements HandlerExceptionResolver  {

    //前端控制器DispatcherServlet在進(jìn)行HandlerMapping、調(diào)用HandlerAdapter執(zhí)行Handler過程中,如果遇到異常就會執(zhí)行此方法
    //handler最終要執(zhí)行的Handler,它的真實(shí)身份是HandlerMethod
    //Exception ex就是接收到異常信息
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //輸出異常
        ex.printStackTrace();
        
        //統(tǒng)一異常處理代碼
        //針對系統(tǒng)自定義的CustomException異常,就可以直接從異常類中獲取異常信息,將異常處理在錯誤頁面展示
        //異常信息
        String message = null;
        CustomException customException = null;
        //如果ex是系統(tǒng) 自定義的異常,直接取出異常信息
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //針對非CustomException異常,對這類重新構(gòu)造成一個CustomException,異常信息為“未知錯誤”
            customException = new CustomException("未知錯誤");
        }

        //錯誤 信息
        message = customException.getMessage();
        
        request.setAttribute("message", message);

        
        try {
            //轉(zhuǎn)向到錯誤 頁面
            request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
        } catch (ServletException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return new ModelAndView();
    }

}
配置統(tǒng)一異常處理器
    
    

RESTful支持

我們在學(xué)習(xí)webservice的時候可能就聽過RESTful這么一個名詞,當(dāng)時候與SOAP進(jìn)行對比的...那么RESTful究竟是什么東東呢???

RESTful(Representational State Transfer)軟件開發(fā)理念,RESTful對http進(jìn)行非常好的詮釋。

如果一個架構(gòu)支持RESTful,那么就稱它為RESTful架構(gòu)...

以下的文章供我們了解:

http://www.ruanyifeng.com/blog/2011/09/restful

綜合上面的解釋,我們總結(jié)一下什么是RESTful架構(gòu):

 ?。?)每一個URI代表一種資源;

 ?。?)客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層;

  (3)客戶端通過四個HTTP動詞,對服務(wù)器端資源進(jìn)行操作,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。

關(guān)于RESTful冪等性的理解:http://www.oschina.net/translate/put-or-post

簡單來說,如果對象在請求的過程中會發(fā)生變化(以Java為例子,屬性被修改了),那么此是非冪等的。多次重復(fù)請求,結(jié)果還是不變的話,那么就是冪等的。

PUT用于冪等請求,因此在更新的時候把所有的屬性都寫完整,那么多次請求后,我們其他屬性是不會變的

在上邊的文章中,冪等被翻譯成“狀態(tài)統(tǒng)一性”。這就更好地理解了。

其實(shí)一般的架構(gòu)并不能完全支持RESTful的,因此,只要我們的系統(tǒng)支持RESTful的某些功能,我們一般就稱作為支持RESTful架構(gòu)...

url的RESTful實(shí)現(xiàn)

非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&....

RESTful的url是簡潔的:http:// localhost:8080/items/editItems/1

更改DispatcherServlet的配置

從上面我們可以發(fā)現(xiàn),url并沒有.action后綴的,因此我們要修改核心分配器的配置

    
    
        springmvc_rest
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            
            classpath:spring/springmvc.xml
        

    
    
        springmvc_rest
        
        /
    

在Controller上使用PathVariable注解來綁定對應(yīng)的參數(shù)

    //根據(jù)商品id查看商品信息rest接口
    //@RequestMapping中指定restful方式的url中的參數(shù),參數(shù)需要用{}包起來
    //@PathVariable將url中的{}包起參數(shù)和形參進(jìn)行綁定
    @RequestMapping("/viewItems/{id}")
    public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception{
        //調(diào)用 service查詢商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(id);
        
        return itemsCustom;
        
    }

當(dāng)DispatcherServlet攔截/開頭的所有請求,對靜態(tài)資源的訪問就報(bào)錯:我們需要配置對靜態(tài)資源的解析

    
    
    

/**就表示不管有多少層,都對其進(jìn)行解析,/*代表的是當(dāng)前層的所有資源..

SpringMVC攔截器

在Struts2中攔截器就是我們當(dāng)時的核心,原來在SpringMVC中也是有攔截器的

用戶請求到DispatherServlet中,DispatherServlet調(diào)用HandlerMapping查找Handler,HandlerMapping返回一個攔截的鏈兒(多個攔截),springmvc中的攔截器是通過HandlerMapping發(fā)起的。

實(shí)現(xiàn)攔截器的接口:

public class HandlerInterceptor1 implements HandlerInterceptor {

    //在執(zhí)行handler之前來執(zhí)行的
    //用于用戶認(rèn)證校驗(yàn)、用戶權(quán)限校驗(yàn)
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        System.out.println("HandlerInterceptor1...preHandle");
        
        //如果返回false表示攔截不繼續(xù)執(zhí)行handler,如果返回true表示放行
        return false;
    }
    //在執(zhí)行handler返回modelAndView之前來執(zhí)行
    //如果需要向頁面提供一些公用 的數(shù)據(jù)或配置一些視圖信息,使用此方法實(shí)現(xiàn) 從modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //執(zhí)行handler之后執(zhí)行此方法
    //作系統(tǒng) 統(tǒng)一異常處理,進(jìn)行方法執(zhí)行性能監(jiān)控,在preHandle中設(shè)置一個時間點(diǎn),在afterCompletion設(shè)置一個時間,兩個時間點(diǎn)的差就是執(zhí)行時長
    //實(shí)現(xiàn) 系統(tǒng) 統(tǒng)一日志記錄
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

配置攔截器

    
    
        
        
        
        
            
            
            
        
    
測試執(zhí)行順序

如果兩個攔截器都放行

測試結(jié)果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion

總結(jié):
執(zhí)行preHandle是順序執(zhí)行。
執(zhí)行postHandle、afterCompletion是倒序執(zhí)行

1 號放行和2號不放行

測試結(jié)果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion

總結(jié):
如果preHandle不放行,postHandle、afterCompletion都不執(zhí)行。
只要有一個攔截器不放行,controller不能執(zhí)行完成

1 號不放行和2號不放行

測試結(jié)果:
HandlerInterceptor1...preHandle
總結(jié):
只有前邊的攔截器preHandle方法放行,下邊的攔截器的preHandle才執(zhí)行。

日志攔截器或異常攔截器要求

將日志攔截器或異常攔截器放在攔截器鏈兒中第一個位置,且preHandle方法放行

攔截器應(yīng)用-身份認(rèn)證

攔截器攔截

public class LoginInterceptor implements HandlerInterceptor {

    //在執(zhí)行handler之前來執(zhí)行的
    //用于用戶認(rèn)證校驗(yàn)、用戶權(quán)限校驗(yàn)
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        //得到請求的url
        String url = request.getRequestURI();
        
        //判斷是否是公開 地址
        //實(shí)際開發(fā)中需要公開 地址配置在配置文件中
        //...
        if(url.indexOf("login.action")>=0){
            //如果是公開 地址則放行
            return true;
        }
        
        //判斷用戶身份在session中是否存在
        HttpSession session = request.getSession();
        String usercode = (String) session.getAttribute("usercode");
        //如果用戶身份在session中存在放行
        if(usercode!=null){
            return true;
        }
        //執(zhí)行到這里攔截,跳轉(zhuǎn)到登陸頁面,用戶進(jìn)行身份認(rèn)證
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        
        //如果返回false表示攔截不繼續(xù)執(zhí)行handler,如果返回true表示放行
        return false;
    }
    //在執(zhí)行handler返回modelAndView之前來執(zhí)行
    //如果需要向頁面提供一些公用 的數(shù)據(jù)或配置一些視圖信息,使用此方法實(shí)現(xiàn) 從modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //執(zhí)行handler之后執(zhí)行此方法
    //作系統(tǒng) 統(tǒng)一異常處理,進(jìn)行方法執(zhí)行性能監(jiān)控,在preHandle中設(shè)置一個時間點(diǎn),在afterCompletion設(shè)置一個時間,兩個時間點(diǎn)的差就是執(zhí)行時長
    //實(shí)現(xiàn) 系統(tǒng) 統(tǒng)一日志記錄
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

Controller

@Controller
public class LoginController {
    
    
    //用戶登陸提交方法
    @RequestMapping("/login")
    public String login(HttpSession session, String usercode,String password)throws Exception{
        
        //調(diào)用service校驗(yàn)用戶賬號和密碼的正確性
        //..
        
        //如果service校驗(yàn)通過,將用戶身份記錄到session
        session.setAttribute("usercode", usercode);
        //重定向到商品查詢頁面
        return "redirect:/items/queryItems.action";
    }
    
    //用戶退出
    @RequestMapping("/logout")
    public String logout(HttpSession session)throws Exception{
        
        //session失效
        session.invalidate();
        //重定向到商品查詢頁面
        return "redirect:/items/queryItems.action";
        
    }
    

}
總結(jié)

使用Spring的校驗(yàn)方式就是將要校驗(yàn)的屬性前邊加上注解聲明。

在Controller中的方法參數(shù)上加上@Validation注解。那么SpringMVC內(nèi)部就會幫我們對其進(jìn)行處理(創(chuàng)建對應(yīng)的bean,加載配置文件)

BindingResult可以拿到我們校驗(yàn)錯誤的提示

分組校驗(yàn)就是將讓我們的校驗(yàn)更加靈活:某方法需要校驗(yàn)這個屬性,而某方法不用校驗(yàn)該屬性。我們就可以使用分組校驗(yàn)了。

對于處理異常,SpringMVC是用一個統(tǒng)一的異常處理器類的。實(shí)現(xiàn)了HandlerExceptionResolver接口。

對模塊細(xì)分多個異常類,都交由我們的統(tǒng)一異常處理器類進(jìn)行處理。

對于RESTful規(guī)范,我們可以使用SpringMVC簡單地支持的。將SpringMVC的攔截.action改成是任意的。同時,如果是靜態(tài)的資源文件,我們應(yīng)該設(shè)置不攔截。

對于url上的參數(shù),我們可以使用@PathVariable將url中的{}包起參數(shù)和形參進(jìn)行綁定

SpringMVC的攔截器和Struts2的攔截器差不多。不過SpringMVC的攔截器配置起來比Struts2的要簡單。

至于他們的攔截器鏈的調(diào)用順序,和Filter的是沒有差別的。

如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號:Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68838.html

相關(guān)文章

  • 移動商城項(xiàng)目【總結(jié)】

    摘要:有必要建一個資源服務(wù)器存放靜態(tài)資源。一些用戶級別的數(shù)據(jù)輕量可以考慮存儲在中。存儲的是值,可以通過來對和對象之間的轉(zhuǎn)換如果我們的數(shù)據(jù)是在后臺傳過去或者轉(zhuǎn)換而成的,在前臺上并沒有做什么改變的話。 移動商城項(xiàng)目總結(jié) 移動商城項(xiàng)目是我第二個做得比較大的項(xiàng)目,該項(xiàng)目系統(tǒng)來源于傳智Java168期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號就可以直接獲取了) 通過這次的項(xiàng)目又再次開闊了我的視野,...

    BlackHole1 評論0 收藏0
  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...

    KevinYan 評論0 收藏0
  • 面試題:SpringMVC和Struts2的區(qū)別

    摘要:的入口是,而是這里要指出,和是不同的。以前認(rèn)為是的一種特殊,這就導(dǎo)致了二者的機(jī)制不同,這里就牽涉到和的區(qū)別了。開發(fā)效率和性能高于。的實(shí)現(xiàn)機(jī)制有以自己的機(jī)制,用的是獨(dú)立的方式。 1、Struts2是類級別的攔截, 一個類對應(yīng)一個request上下文,SpringMVC是方法級別的攔截,一個方法對應(yīng)一個request上下文,而方法同時又跟一個url對應(yīng),所以說從架構(gòu)本身上SpringMVC...

    isaced 評論0 收藏0
  • SpringBoot自動配置原理

    摘要:開啟自動配置功能后文詳解這個注解,學(xué)過的同學(xué)應(yīng)該對它不會陌生,就是掃描注解,默認(rèn)是掃描當(dāng)前類下的。簡單來說,這個注解可以幫助我們自動載入應(yīng)用程序所需要的所有默認(rèn)配置。簡單理解這二者掃描的對象是不一樣的。 前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 回顧前面Spring的文章(以學(xué)習(xí)...

    Rainie 評論0 收藏0
  • SpringMVC總結(jié)

    摘要:前端控制器根據(jù)返回的視圖名,選擇相應(yīng)的視圖進(jìn)行渲染,并將模型數(shù)據(jù)傳入到視圖中以便展示。前端控制器將響應(yīng)的結(jié)果返回給用戶。 SpringMVC總結(jié) 一、spring MVC的工作內(nèi)容 將URL映射到Java類或者方法 封裝用戶提交的數(shù)據(jù) 處理請求,調(diào)用相關(guān)的業(yè)務(wù)層,并封裝響應(yīng)的數(shù)據(jù) 將要響應(yīng)的數(shù)據(jù)進(jìn)行渲染 二、SpringMVC的優(yōu)點(diǎn)和特點(diǎn) 與spring無縫集成(IOC、AOP)...

    raledong 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<