SpringMVC整理

SpringMVC優勢

1、清晰的角色劃分:
前端控制器(DispatcherServlet)
處理器映射器(HandlerMapping)
處理器適配器(HandlerAdapter)
視圖解析器(ViewResolver)
處理器或頁面控制器(Controller)
驗證器( Validator)
命令對象(Command 請求參數綁定到的對象就叫命令對象)
表單對象(Form Object 提供給表單展示和提交到的對象就叫表單對象)。
2、分工明確,而且擴展點相當靈活,可以很容易擴展,雖然幾乎不需要。
3、由於命令對象就是一個 POJO,無需繼承框架特定 API,可以使用命令對象直接作爲業務對象。
4、和 Spring 其他框架無縫集成,是其它 Web 框架所不具備的。
5、可適配,通過 HandlerAdapter 可以支持任意的類作爲處理器。
6、可定製性,HandlerMapping、ViewResolver 等能夠非常簡單的定製。
7、功能強大的數據驗證、格式化、綁定機制。
8、利用 Spring 提供的 Mock 對象能夠非常簡單的進行 Web 層單元測試。
9、本地化、主題的解析的支持,使我們更容易進行國際化和主題的切換。
10、強大的 JSP 標籤庫,使 JSP 編寫更容易。
………………還有比如RESTful風格的支·持、簡單的文件上傳、約定大於配置的契約式編程支持、基於註解的零配置支持等等。

SpringMVC對比structs2

共同點:
1.它們都是表現層框架,都是基於 MVC 模型編寫的。
2.它們的底層都離不開原始 ServletAPI。
3.它們處理請求的機制都是一個核心控制器。
區別:
1.Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
2.Spring MVC 是基於方法設計的,而 Struts2 是基於類,Struts2 每次執行都會創建一個動作類。
3.Struct2是多例,SpringMVC是單例。
4.Struct2每次執行都要新建對象,而SpringMVC直接調用方法。所以 Spring MVC 會稍微比 Struts2 快些。
5.Spring MVC 使用更加簡潔,同時還支持 JSR303, 處理 ajax 的請求更方便
6.Struts2 的 OGNL 表達式使頁面的開發效率相比 Spring MVC 更高些,但執行效率並沒有比 JSTL 提升,尤其是 struts2 的表單標籤,遠沒有 html 執行效率高。

SpringMVC組件

1.前端控制器:DispatcherServlet
2.處理器映射器:HandlerMapping
3…處理器:Handler
4.處理器適配器:HandlAdapter
5.視圖解析器:View Resolver
6.視圖: View
SpringMVC 的三大組件
處理器映射器、處理器適配器、視圖解析器

 <mvc:annotation-driven> 自 動加載 RequestMappingHandlerMapping (處理映射器) 和
RequestMappingHandlerAdapter ( 處 理 適 配 器 )

 <!-- 視圖解析器對象 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/student/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

SpringMVC簡單案例

web.xml配置前端控制器和解決亂碼

<!--配置前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--配置解決中文亂碼的過濾器-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

SpringMVC.xml開啓註解掃描,處理器映射器,處理器適配器和視圖解析對象

 <!-- 開啓註解掃描 -->
    <context:component-scan base-package="home.sise.cn"/>

    <!-- 視圖解析器對象 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

 <!--前端控制器,哪些靜態資源不攔截-->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>
    
    <!--  自 動加載 RequestMappingHandlerMapping (處理映射器) 和
RequestMappingHandlerAdapter ( 處 理 適 配 器 ) -->
    <mvc:annotation-driven conversion-service="conversionService"/>

前臺請求jsp頁面

  <a href="user/hello">入門程序</a>

success.jsp頁面

<h3>入門成功</h3>

控制器類
// 控制器類

@Controller
@RequestMapping(path="/user")
public class HelloController {

    /**
     * 入門案例
     * @return
     */
    @RequestMapping(path="/hello")
    public String sayHello(){
        System.out.println("Hello StringMVC");
        return "success";
    }}

運行結果:
在這裏插入圖片描述
點擊超鏈接後
在這裏插入圖片描述
運行邏輯:
在這裏插入圖片描述
客戶端請求點擊超鏈接,先進入web.xml的前端控制器DispatcherServlet,然後前端控制器會去找處理器映射器HandlerMapping,找到/user/hello對應的控制器類。找到後,返回一個執行鏈給前端控制器,前端控制器再去請求處理器適配器HandlerAdapter執行,處理器適配器會去找處理器Handler執行,Handler會執行對應/user/hello請求路徑下的方法sayHello()。然後返回ModelAndView對象回處理器適配器再回前端控制器。ModelAndView對象裏面包含了將要返回的地址success。前端控制器會根據返回的ModelAndView對象去請求視圖解析器ViewResolver進行解析,解析後返回View回前端控制器,前端控制器最終會將View渲染後放入request請求域,返回給客戶端,在瀏覽器解析並顯示。

方法參數

可以把基本類型和String,對象,集合,ServlletAPI作爲方法參數,由於SpringMVC底層封裝,所以只需要在超鏈接的參數裏的參數名和方法參數名一樣,即可傳入方法中,或表單的元素的屬性name的值和方法參數名一樣。若不一樣,則可以使用註解RequestParam

常用註解

RequestMapping

作用在類上,請求 URL 的第一級訪問目錄
作用在方法上,請求 URL 的第二級訪問目錄
屬性
value:用於指定請求的 URL。它和 path 屬性的作用是一樣的。
method:用於指定請求的方式。
params:用於指定限制請求參數的條件。它支持簡單的表達式。要求請求參數的 key 和 value 必須和
配置的一模一樣。


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}
public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;
    private RequestMethod() {
    }
}

RequestParam

作用:
把請求中指定名稱的參數給控制器中的形參賦值。
屬性:
value:請求參數中的名稱。
required:請求參數中是否必須提供此參數。默認值:true。表示必須提供,如果不提供將報錯。

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

RequestBody

作用:
用於獲取請求體內容。直接使用得到是 key=value&key=value…結構的數據。
get 請求方式不適用。因爲get方式沒有請求體。
屬性:
required:是否必須有請求體。默認值是:true。當取值爲 true 時,get 請求方式會報錯。如果取值
爲 false,get 請求得到是 null。

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
    boolean required() default true;
}

ModelAttribute

作用:
出現在方法上,表示當前方法會在控制器的方法執行之前,先執行。它可以修飾沒有返回值的方法,也可
以修飾有具體返回值的方法。
出現在參數上,獲取指定的數據給參數賦值。
屬性:
value:用於獲取數據的 key。key 可以是 POJO 的屬性名稱,也可以是 map 結構的 key。

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean binding() default true;
}

PathVaribale

作用:
用於綁定 url 中的佔位符。例如:請求 url 中 /delete/{id},這個{id}就是 url 佔位符。
springmvc 支持 rest 風格 URL 的一個重要標誌。
屬性:
value:用於指定 url 中佔位符名稱。
required:是否必須提供佔位符。

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;
}
 @RequestMapping(value="/testPathVariable/{sid}")
    public String testPathVariable(@PathVariable(name="sid") String id){
        System.out.println("執行了...");
        System.out.println(id);
        return "success";
    }

SessionAttribute

作用:
用於多次執行控制器方法間的參數共享。
屬性:
value:用於指定存入的屬性名稱
type:用於指定存入的數據類型。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface SessionAttributes {
    @AliasFor("names")
    String[] value() default {};

    @AliasFor("value")
    String[] names() default {};

    Class<?>[] types() default {};
}
@SessionAttributes(value={"msg"})  到session域對中
public class AnnoController {
/*
設置值
*/
 @RequestMapping(value="/testSessionAttributes")
    public String testSessionAttributes(Model model){
      System.out.println("testSessionAttributes...");
        // 底層會存儲到request域對象中
        model.addAttribute("msg","美美");
        return "success";
    }

    /**
     * 獲取值
     */
    @RequestMapping(value="/getSessionAttributes")
    public String getSessionAttributes(ModelMap modelMap){
        System.out.println("getSessionAttributes...");
        String msg = (String) modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }

    /**
     * 清除
     */
    @RequestMapping(value="/delSessionAttributes")
    public String delSessionAttributes(SessionStatus status){
        System.out.println("delSessionAttributes...");
        status.setComplete();
        return "success";
    }

RequestHeader

作用:
用於獲取請求消息頭。
屬性:
value:提供消息頭名稱
required:是否必須有此消息頭

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

CookieValue

作用:
用於把指定 cookie 名稱的值傳入控制器方法參數。
屬性:
value:指定 cookie 的名稱。
required:是否必須有此 cookie

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CookieValue {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

SpingMVC的不同返回值

返回String

@RequestMapping("/testString")
    public String testString(Model model){
        System.out.println("testString方法執行了...");     
        return "success";
    }

無返回值void,可以通過原始的請求轉發和重定向方式。
注意其中的路徑。

@RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("testVoid方法執行了...");
        // 編寫請求轉發的程序
        // request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
        
        // 重定向
        // response.sendRedirect(request.getContextPath()+"/index.jsp");

        // 設置中文亂碼
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        // 直接會進行響應
        response.getWriter().print("你好");
        return;
    }

返回ModelAndView,這個也是底層的返回方式

 @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView(){
        // 創建ModelAndView對象
        ModelAndView mv = new ModelAndView();
        System.out.println("testModelAndView方法執行了...");
        // 模擬從數據庫中查詢出User對象
        User user = new User();
        user.setUsername("小妹妹");
        user.setPassword("123");
        user.setAge(30);
        // 把user對象存儲到mv對象中,也會把user對象存入到request對象
        mv.addObject("user",user);
        // 跳轉到哪個頁面
        mv.setViewName("success");
        return mv;
    }

使用關鍵字的方式進行轉發或者重定向
注意:
1.關鍵字forward它於“request.getRequestDispatcher(“url”).forward(request,response)”。使用請求轉發,既可以轉發到 jsp,也可以轉發到其他的控制器方法。
2.關鍵字redirect它相當於“response.sendRedirect(url)”。如果是重定向到 jsp 頁面,則 jsp 頁面不能寫在 WEB-INF 目錄中,否則無法找到。

@RequestMapping("/testForwardOrRedirect")
    public String testForwardOrRedirect(){
        System.out.println("testForwardOrRedirect方法執行了...");

        // 請求的轉發
        return "forward:/WEB-INF/pages/success.jsp";

        // 重定向
        return "redirect:/index.jsp";
    }

SpringMVC的ajax異步處理

需要jar包
在這裏插入圖片描述
請求jsp頁面

<html>
<head>
    <title>Title</title>
    <script src="js/jquery.min.js"></script>
    <script>
        // 頁面加載,綁定單擊事件
        $(function(){
            $("#btn").click(function(){
                // alert("hello btn");
                // 發送ajax請求
                $.ajax({
                    // 編寫json格式,設置屬性和值
                    url:"user/testAjax",
                    contentType:"application/json;charset=UTF-8",
                    data:'{"username":"hehe","password":"123","age":30}',
                    dataType:"json",
                    type:"post",
                    success:function(data){
                        // data服務器端響應的json的數據,進行解析
                        alert(data);
                        alert(data.username);
                        alert(data.password);
                        alert(data.age);
                    }
                });

            });
        });
    </script>
</head>
<body>
    <button id="btn">發送ajax的請求</button>
</body>
</html>

控制器類
@RequestBody註解負責將請求的json數據類型轉化成對應的java對象類型
@ResponseBody註解負責將返回的java對象類型轉換成json數據類型

@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testAjax")
    public @ResponseBody User testAjax(@RequestBody User user){
        System.out.println("testAjax方法執行了...");
        // 客戶端發送ajax的請求,傳的是json字符串,後端把json字符串封裝到user對象中
        System.out.println(user);
        // 做響應,模擬查詢數據庫
        user.setUsername("haha");
        user.setAge(40);
        // 做響應
        return user;
    }}

SpringMVC的攔截器

pring MVC 的處理器攔截器類似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。
攔截器和過濾器的區別
1.過濾器的使用範圍是javaweb工程,攔截器的使用範圍是SpringMVC框架本身
2.過濾器在 url-pattern 中配置了/*之後,可以對所有要訪問的資源攔截。而攔截器它是隻會攔截訪問控制器中的方法, jsp,html,css,image 或者 js等都不會攔截。
3.過濾器在web.xml中配置,且順序跟配置順序有關。攔截器在SpringMVC.xml中配置,順序也跟配置順序有關。
攔截器也是 AOP 思想的具體應用。
我們要想自定義攔截器, 要求必須實現:HandlerInterceptor 接口。

自定義攔截器

步驟
1.編寫請求頁面和成功頁面
2.編寫控制器類。
3.編寫攔截器類,要實現HandlerInterceptor接口。
4.在SpringMVC.xml上配置攔截器類,並設置攔截的方法範圍。以及攔截器的順序。

請求jsp頁面

<a href="user/testInterceptor" >攔截器</a>

success.jsp頁面

 <h3>執行成功</h3>
    <% System.out.println("success.jsp執行了..."); %>

控制器類

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
        System.out.println("testInterceptor執行了...");
        return "success";
    }
}

攔截器類
實現了HandlerInterceptor 後,可以重寫的三個方法。(接口已自己實現)
preHandle:controller方法執行前,返回true代表放行,false代表攔截
可用於判斷用戶是否登錄
postHandle:controller方法執行後,success.jsp執行之前
可用於下個頁面顯示前將需要的數據從數據庫查詢出來
afterCompletion:success.jsp頁面執行後
可用於釋放資源

public class MyInterceptor1 implements HandlerInterceptor{

    /**
     * 預處理,controller方法執行前
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1執行了...前1111");
         //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }
    /**
     * 後處理方法,controller方法執行後,success.jsp執行之前
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1執行了...後1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }
    /**
     * success.jsp頁面執行後,該方法會執行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1執行了...最後1111");
    }
}
public class MyInterceptor2 implements HandlerInterceptor{
   /**
     * 預處理,controller方法執行前
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1執行了...前2222");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }
    /**
     * 後處理方法,controller方法執行後,success.jsp執行之前
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1執行了...後2222");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }
    /**
     * success.jsp頁面執行後,該方法會執行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1執行了...最後2222");
    }
}

SpringMVC.xml配置文件

<!--配置攔截器-->
    <mvc:interceptors>
        <!--配置攔截器-->
        <mvc:interceptor>
            <!--要攔截的具體的方法-->
            <mvc:mapping path="/user/*"/>
            <!--不要攔截的方法
            <mvc:exclude-mapping path=""/>
            -->
            <!--配置攔截器對象-->
            <bean class="home.sise.cn.interceptor.MyInterceptor1" />
        </mvc:interceptor>

        <!--配置第二個攔截器-->
        <mvc:interceptor>
            <!--要攔截的具體的方法-->
            <mvc:mapping path="/**"/>
            <!--不要攔截的方法
            <mvc:exclude-mapping path=""/>
            -->
            <!--配置攔截器對象-->
            <bean class="home.sise.cn.interceptor.MyInterceptor2" />
        </mvc:interceptor>
    </mvc:interceptors>

運行結果
在這裏插入圖片描述
點擊後
在這裏插入圖片描述
控制檯:
在這裏插入圖片描述

SpringMVC的文件上傳

前提限制
1.請求方式要post,因爲get沒有請求體
2.form表單的enctype取值必須是:multipart/form-data
3.提供一個文件選擇域 < input type=“file”/ >

請求jsp頁面

<h3>Springmvc文件上傳</h3>
    <form action="/user/fileupload2" method="post" enctype="multipart/form-data">
        選擇文件:<input type="file" name="upload" /><br/>
        <input type="submit" value="上傳" />
    </form>

控制器

@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/fileupload2")
    public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception {
        System.out.println("springmvc文件上傳...");
        // 使用fileupload組件完成文件上傳
        // 上傳的位置
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        // 判斷,該路徑是否存在
        File file = new File(path);
        if(!file.exists()){
            // 創建該文件夾
            file.mkdirs();
        }
        // 說明上傳文件項
        // 獲取上傳文件的名稱
        String filename = upload.getOriginalFilename();
        // 把文件的名稱設置唯一值,uuid
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;
        // 完成文件上傳
        upload.transferTo(new File(path,filename));
      return "success";
    }}

SpringMVC.xml配置文件
注意:文件上傳的解析器 id 是固定的,不能起別的名稱,否則無法實現請求參數的綁定。

 <!--配置文件解析器對象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760" />
    </bean>

跨服務器的文件上傳方式

請求jsp頁面

 <h3>跨服務器文件上傳</h3>
    <form action="/user/fileupload3" method="post" enctype="multipart/form-data">
        選擇文件:<input type="file" name="upload" /><br/>
        <input type="submit" value="上傳" />
    </form>

控制器

@Controller
@RequestMapping("/user")
public class UserController {
    /**
     * 跨服務器文件上傳
     */
    @RequestMapping("/fileupload3")
    public String fileuoload3(MultipartFile upload) throws Exception {
        System.out.println("跨服務器文件上傳...");
        // 定義上傳文件服務器路徑
        String path = "http://localhost:9084/uploads/";
        // 說明上傳文件項
        // 獲取上傳文件的名稱
        String filename = upload.getOriginalFilename();
        // 把文件的名稱設置唯一值,uuid
        String uuid = UUID.randomUUID().toString().replace("-", "");
        filename = uuid+"_"+filename;
        // 創建客戶端的對象
        Client client = Client.create();
        // 和圖片服務器進行連接
        WebResource webResource = client.resource(path + filename);
        // 上傳文件
        webResource.put(upload.getBytes());
        return "success";
    }}

注意:需要把要連接的服務器開啓,而且要在tomcat安裝路徑\conf\web.xml中配置權限。
在這裏插入圖片描述
SpringMVC.xml配置文件

 <!--配置文件解析器對象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760" />
    </bean>

SpringMVC的異常處理

默認情況下,如果出了異常。dao層會拋給service層,service層會拋給控制器層,控制器層會拋到客戶端顯示。

1.jsp請求頁面
在這裏插入圖片描述
2.error.jsp頁面
在這裏插入圖片描述
3.控制器類

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testException")
    public String testException() throws SysException{
        System.out.println("testException執行了...");
        try {
            // 模擬異常
            int a = 10/0;
        } catch (Exception e) {
            // 打印異常信息
            e.printStackTrace();
            // 拋出自定義異常信息
            throw new SysException("查詢所有用戶出現錯誤了...");
        }
        return "success";}
}

4.自定義異常類(存儲異常信息)

public class SysException extends Exception{
   // 存儲提示信息的
    private String message;
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
  public SysException(String message) {
        this.message = message;
    }
}

5.定義異常處理類,實現接口HandlerExceptionResolver

public class SysExceptionResolver implements HandlerExceptionResolver{
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 獲取到異常對象
        SysException e = null;
        if(ex instanceof SysException){
            e = (SysException)ex;
        }else{
            e = new SysException("系統正在維護....");
        }
        // 創建ModelAndView對象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        mv.setViewName("error");
        return mv;   }
}

6.需要在SpringMVC.xml中配置處理器類。

 <!--配置異常處理器-->
    <bean id="sysExceptionResolver" class="home.sise.cn.exception.SysExceptionResolver"/>
    <!-- 視圖解析器對象 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

運行結果:
在這裏插入圖片描述
點擊後
在這裏插入圖片描述

自定義轉換器

第一步:定義一個類,實現 Converter 接口,該接口有兩個泛型。

public interface Converter<S, T> {//S:表示接受的類型,T:表示目標類型
@Nullable
T convert(S source);
}
public class StringToDateConverter implements Converter<String, Date> {
/**
* 用於把 String 類型轉成日期類型
*/
@Override
public Date convert(String source) {
DateFormat format = null;
try {
if(StringUtils.isEmpty(source)) {
throw new NullPointerException("請輸入要轉換的日期");
}
format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("輸入日期有誤");
}
}

第二步:在 spring 配置文件中配置類型轉換器。

<!-- 配置類型轉換器工廠 -->
<bean id="converterService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 給工廠注入一個新的類型轉換器 -->
<property name="converters">
<array>
<!-- 配置自定義類型轉換器 -->
<bean class="home.sise.cn.web.converter.StringToDateConverter"></bean>
</array>
</property>
</bean>

第三步:在 annotation-driven 標籤中引用配置的類型轉換服務

<!-- 引用自定義類型轉換器 -->
<mvc:annotation-driven
conversion-service="converterService"></mvc:annotation-driven>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章