SpringMVC文件上傳

必要前提

  1. form表單的enctype取值必須是:multipart/form-data (默認(rèn)值是:application/x-www-form-urlencoded) enctype:是表單請(qǐng)求正文的類型
  2. method屬性取值必須是Post
  3. 提供一個(gè)文件選擇域<input type="file" />

環(huán)境搭建

創(chuàng)建maven項(xiàng)目

導(dǎo)入相關(guān)依賴

pom.xml中導(dǎo)入相關(guān)依賴

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <!--spring版本鎖定-->
  <spring.version>5.0.2.RELEASE</spring.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-api</artifactId>
    <version>7.0.47</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper-el</artifactId>
    <version>7.0.47</version>
  </dependency>
  <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
  </dependency>
</dependencies>

配置核心控制器

web.xml中配置SpringMVC核心控制器

<web-app>

  <!--配置SpringMVC核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!-- 配置Servlet的初始化參數(shù)钻心,讀取springmvc的配置文件翁逞,創(chuàng)建spring容器 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>

    <!-- 配置servlet啟動(dòng)時(shí)加載對(duì)象 -->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!--配置springmvc過(guò)請(qǐng)求過(guò)濾器套才,/表示所有請(qǐng)求都經(jīng)過(guò)springmvc處理-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

編寫核心配置文件

編寫SpringMVC核心配置文件springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置創(chuàng)建spring容器要掃描的包 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--SpringMVC注解驅(qū)動(dòng)-->
    <mvc:annotation-driven></mvc:annotation-driven>

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

</beans>

單文件上傳

配置文件解析器

springmvc.xml中配置文件解析器

<!--
    配置文件上傳解析器
    id的值是固定的
    class的值也是固定的
 -->
<beanid="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--上傳文件總大小-->
  <property name="maxUploadSize" value="5242800"/>
  <!--上傳單個(gè)文件的大小-->
  <property name="maxUploadSizePerFile"value="5242800"/>
  <!--上傳文件的編碼類型-->
  <property name="defaultEncoding" value="UTF-8"/>
</bean>

編寫文件上傳頁(yè)面

編寫文件上傳頁(yè)面upload.jsp

<h1>SpringMVC方式文件上傳</h1>
<form action="${pageContext.request.contextPath }/file/upload2" method="post" enctype="multipart/form-data" >
    文件描述:<input type="text" name="desc"><br>
    文件上傳:<input type="file" name="file"><br>
    <input type="submit" value="開(kāi)始上傳">
</form>

編寫控制層代碼

編寫控制層代碼FileController

@RequestMapping(path="/upload2",method = RequestMethod.POST)
public String upload2(MultipartFile file) throws Exception {
    //1. 獲取一個(gè)文件輸出的磁盤路徑
    String path = "C:\\Users\\Administrator\\Desktop\\upload";
    File dir = new File(path);
    if(!dir.exists()){
        dir.mkdir();
    }

    //2. 獲取文件名稱
    String filename = file.getOriginalFilename();

    //3. 獲取文件內(nèi)容
    InputStream is = file.getInputStream();//獲取文件內(nèi)容

    //4. 創(chuàng)建輸出流
    OutputStream os = new FileOutputStream(path + "/" + filename);

    //5. 將文件內(nèi)容通過(guò)輸出流寫到磁盤文件中
    int i = 0;
    byte[] bys = new byte[1024];

    while ((i = is.read()) != -1) {
        os.write(bys, 0, i);
    }
    os.close();

    return "success";
}

多文件上傳

編寫文件上傳頁(yè)面

編寫文件上傳頁(yè)面upload.jsp

<h1>SpringMVC方式多選文件上傳</h1>
<form action="${pageContext.request.contextPath }/file/multi" method="post" enctype="multipart/form-data" >
    文件描述:<input type="text" name="desc"><br>
    文件上傳:<input type="file" name="files"><br>
    文件上傳:<input type="file" name="files"><br>
    <input type="submit" value="開(kāi)始上傳">
</form>

編寫控制層代碼

編寫控制層代碼FileController

@RequestMapping(path="/multi",method = RequestMethod.POST)
public String upload3(MultipartFile[] files) throws Exception {

    //1. 獲取一個(gè)文件輸出的磁盤路徑
    String path = "C:\\Users\\Administrator\\Desktop\\upload";
    File dir = new File(path);
    if(!dir.exists()){
        dir.mkdir();
    }

    //遍歷文件集合
    for (MultipartFile file : files) {
        //2. 獲取文件名稱
        String filename = file.getOriginalFilename();
        //3. 獲取文件內(nèi)容
        InputStream is = file.getInputStream();//獲取文件內(nèi)容

        //4. 創(chuàng)建輸出流
        OutputStream os = new FileOutputStream(path + "/" + filename);

        //5. 將文件內(nèi)容通過(guò)輸出流寫到磁盤文件中
        int i = 0;
        byte[] bys = new byte[1024];

        while ((i = is.read()) != -1) {
            os.write(bys, 0, i);
        }
        os.close();
    }

    return "success";
}

SpringMVC攔截器

1. SpringMVC框架中的攔截器用于對(duì)處理器進(jìn)行預(yù)處理和后處理的技術(shù)羔味。
2. 可以定義攔截器鏈泡挺,連接器鏈就是將攔截器按著一定的順序結(jié)成一條鏈桶唐,在訪問(wèn)被攔截的方法時(shí),攔截器鏈中的攔截器會(huì)按著定義的順序執(zhí)行。
3. 攔截器和過(guò)濾器的功能比較類似绍填,有區(qū)別
    1. 過(guò)濾器是Servlet規(guī)范的一部分,任何框架都可以使用過(guò)濾器技術(shù)凹联。
    2. 攔截器是SpringMVC框架獨(dú)有的沐兰。
    3. 過(guò)濾器配置了/*,可以攔截任何資源蔽挠。
    4. 攔截器只會(huì)對(duì)控制器中的方法進(jìn)行攔截住闯。
4. 攔截器也是AOP思想的一種實(shí)現(xiàn)方式
5. 想要自定義攔截器,需要實(shí)現(xiàn)HandlerInterceptor接口澳淑。

環(huán)境搭建

創(chuàng)建maven項(xiàng)目

導(dǎo)入相關(guān)依賴

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <!--spring版本鎖定-->
  <spring.version>5.0.2.RELEASE</spring.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-api</artifactId>
    <version>7.0.47</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper-el</artifactId>
    <version>7.0.47</version>
  </dependency>
</dependencies>
</project>

編寫核心控制器

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <!--配置SpringMVC核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!-- 配置Servlet的初始化參數(shù)比原,讀取springmvc的配置文件,創(chuàng)建spring容器 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>

    <!-- 配置servlet啟動(dòng)時(shí)加載對(duì)象 -->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!--配置springmvc過(guò)請(qǐng)求過(guò)濾器杠巡,/表示所有請(qǐng)求都經(jīng)過(guò)springmvc處理-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

編寫核心配置文件

編寫核心配置文件springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置創(chuàng)建spring容器要掃描的包 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--SpringMVC注解驅(qū)動(dòng)-->
    <mvc:annotation-driven></mvc:annotation-driven>

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

編寫頁(yè)面代碼

編寫頁(yè)面代碼index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<title>SpringMVC攔截器</title>
</head>
<body>
<h1>SpringMVC攔截器</h1>
<a href="${pageContext.request.contextPath}/user/add">添加用戶</a>
</body>
</html>

編寫控制層代碼

package com.itheima.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/add")
    public String add(){
        System.out.println("控制層add方法執(zhí)行了.....");
        return "success";
    }
}

自定義攔截器

創(chuàng)建攔截器

編寫一個(gè)普通類實(shí)現(xiàn)HandlerInterceptor接口

package com.itheima.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor1 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle攔截器執(zhí)行了.....");
        return true;
    }
}

配置攔截器

springmvc.xml中配置攔截器(掌握)

<!-- 配置攔截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!--
            配置攔截器攔截的方法
            /** 代表攔截所有方法
            /user/* 代表攔截/user路徑下的所有方法
        -->
        <mvc:mapping path="/user/*"/>
        <!--配置不攔截的方法
        <mvc:exclude-mapping path="" />
        -->
        <bean id="myInterceptor1" class="com.itheima.interceptor.MyInterceptor1"></bean>
    </mvc:interceptor>
</mvc:interceptors>

攔截器的細(xì)節(jié)

攔截器的放行

放行的含義是指量窘,如果有下一個(gè)攔截器就執(zhí)行下一個(gè),如果該攔截器處于攔截器鏈的最后一個(gè)氢拥,則執(zhí)行控制器中的方法蚌铜。



攔截器中方法的說(shuō)明

方法名 說(shuō)明
preHandle() 方法將在請(qǐng)求處理之前進(jìn)行調(diào)用, 該方法的返回值是布爾值Boolean類型的嫩海,當(dāng)它返回為false時(shí)冬殃, 表示請(qǐng)求結(jié)束, 后續(xù)的Interceptor和Controller都不會(huì)再執(zhí)行叁怪; 當(dāng)返回值為true時(shí)就會(huì)繼續(xù)調(diào)用下一個(gè)Interceptor的preHandle方法
postHandle() 該方法是在當(dāng)前請(qǐng)求進(jìn)行處理之后被調(diào)用审葬, 前提是preHandle方法的返回值為true時(shí)才能被調(diào)用, 且它會(huì)在DispatcherServlet進(jìn)行視圖返回渲染之前被調(diào)用奕谭, 所以我們可以在這個(gè)方法中對(duì)Controller處理之后的ModelAndView對(duì)象進(jìn)行操作
afterCompletion() 該方法將在整個(gè)請(qǐng)求結(jié)束之后涣觉, 也就是在Dispatcher Servlet渲染了對(duì)應(yīng)的視圖之后執(zhí)行, 前提是preHandle方法的返回值為true時(shí)才能被調(diào)用血柳,常用于接口返回修改
1. `preHandle()`是controller方法執(zhí)行前攔截的方法
    1. 可以使用request或者response跳轉(zhuǎn)到指定的頁(yè)面
    2. return true放行官册,執(zhí)行下一個(gè)攔截器,如果沒(méi)有攔截器混驰,執(zhí)行controller中的方法攀隔。
    3. return false不放行皂贩,不會(huì)執(zhí)行controller中的方法栖榨。

2. `postHandle()`是controller方法執(zhí)行后執(zhí)行的方法昆汹,在JSP視圖執(zhí)行前。
    1. 可以使用request或者response跳轉(zhuǎn)到指定的頁(yè)面
    2. 如果指定了跳轉(zhuǎn)的頁(yè)面婴栽,那么controller方法跳轉(zhuǎn)的頁(yè)面將不會(huì)顯示满粗。

3. `afterCompletion()`方法是在JSP執(zhí)行后執(zhí)行
    1. request或者response不能再跳轉(zhuǎn)頁(yè)面了

攔截器的作用路徑

<mvc:interceptor>
    <!--
        配置攔截器攔截的方法
        /** 代表攔截所有方法
        /user/* 代表攔截/user路徑下的所有方法
    -->
    <mvc:mapping path="/user/*"/>
    <!--配置不攔截的方法
    <mvc:exclude-mapping path="" />
    -->
    <bean id="myInterceptor1" class="com.itheima.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>

多個(gè)攔截器配置

<!-- 配置攔截器 -->
<mvc:interceptors>
   <mvc:interceptor>

       <mvc:mapping path="/user/*"/>

       <bean id="myInterceptor1" class="com.itheima.interceptor.MyInterceptor1"></bean>
   </mvc:interceptor>

   <mvc:interceptor>
       <mvc:mapping path="/user/*"/>
       <bean id="myInterceptor2" class="com.itheima.interceptor.MyInterceptor2"></bean>
   </mvc:interceptor>
</mvc:interceptors>

攔截器實(shí)現(xiàn)權(quán)限控制

登錄代碼編寫

在登陸頁(yè)面輸入用戶名密碼,點(diǎn)擊登陸愚争,通過(guò)用戶名密碼進(jìn)行查詢映皆,如果登陸成功,則將用戶信息實(shí)體存入session轰枝,然后跳轉(zhuǎn)到首頁(yè)捅彻,如果登陸失敗則繼續(xù)回到登陸頁(yè)面

表現(xiàn)層

package com.itheima.web;

import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * @Author 王磊
 * @Date 2019/11/1/001
 */
@Controller
@RequestMapping(path = "/user")
public class UserController {

    @RequestMapping(path = "/login")
    public String login(@RequestParam(name="user") String username , String password , Model model , HttpSession session){
        //用戶登錄
        User user = userService.login(username, password);
        //判斷是否登錄成功 , 響應(yīng)頁(yè)面
        //用戶登錄失敗
        if(user==null){
            model.addAttribute("msg","用戶名或密碼錯(cuò)誤");
            return "login";
        }

        //登錄成功 , 跳轉(zhuǎn)到用戶列表頁(yè)面
        //保存到Session域?qū)ο?        session.setAttribute("user",user);
        //頁(yè)面跳轉(zhuǎn) , 注意不能直接跳轉(zhuǎn)到list.jsp頁(yè)面
        return "redirect:/user/findAll";
    }
}

業(yè)務(wù)層

package com.itheima.service;

import com.itheima.pojo.User;

import java.util.List;

/**
 * @Author 王磊
 * @Date 2019/11/1/001
 */
public interface UserService {

    /**
     * 用戶登錄
     * @return
     */
    public User login(String username , String password);

}

package com.itheima.service.impl;

import com.itheima.dao.UserDao;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author 王磊
 * @Date 2019/11/1/001
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao ;

    @Override
    public User login(String username, String password) {
        return userDao.findByUsernameAndPassword(username,password);
    }

}

數(shù)據(jù)訪問(wèn)層

package com.itheima.dao;

import com.itheima.pojo.User;

import java.util.List;

/**
 * @Author 王磊
 * @Date 2019/11/1/001
 */
public interface UserDao {

    /**
     * 根據(jù)用戶名或密碼查詢用戶數(shù)據(jù)
     * @param username
     * @param password
     * @return
     */

    public User findByUsernameAndPassword(String username , String password);

}
package com.itheima.dao.impl;

import com.itheima.dao.UserDao;
import com.itheima.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author 王磊
 * @Date 2019/11/1/001
 */
@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate ;

    @Override
    public User findByUsernameAndPassword(String username, String password) {
        try {
            //queryForObject如果查詢到數(shù)據(jù)會(huì)封裝返回 , 如果查詢不到數(shù)據(jù)拋出異常
            String sql = select * from tb_user where username=? and password = ?";
            return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),username,password);
        } catch (DataAccessException e) {
            e.printStackTrace();
            return null ;
        }
    }
}

配置文件

druid.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/springmvc_02
jdbc.username=root
jdbc.password=zl

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--開(kāi)啟組件掃描-->
    <context:component-scan base-package="com.itheima"> </context:component-scan>

    <!--加載屬性配置文件-->
    <context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>

    <!--配置數(shù)據(jù)庫(kù)連接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--配置jdbcTemplate對(duì)象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--開(kāi)啟注解驅(qū)動(dòng)-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!--釋放靜態(tài)資源-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

    <!--配置視圖解析器  list  /list.jsp-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

    <!--配置字符串編碼過(guò)濾器-->
    <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>

    <!--配置前端控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--加載SpringMVC配置文件-->
        <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>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/js/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/fonts/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/css/*</url-pattern>
    </servlet-mapping>

</web-app>

定義攔截器

package com.itheima.interceptor;

import com.itheima.pojo.User;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author 黑馬程序員
 */
public class PrivilegeInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判斷用戶是否登錄
        //1. 獲取session中保存的用戶信息
        User user = (User) request.getSession().getAttribute("user");
        //2. 判斷用戶信息是否為null
        if (user == null) {
            //3. 如果為null代表用戶為登錄, 返回到登錄頁(yè)面
            request.setAttribute("msg", "權(quán)限不足 , 請(qǐng)登錄!!");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return false;
        }

        //4. 如果不為null代表用戶登錄成功 ,放行
        return true;
    }
}

配置攔截器

此時(shí)仍然登陸不上,因?yàn)槲覀冃枰獙⒌顷懻?qǐng)求url讓攔截器放行,添加資源排除的配置

<!--配置攔截器信息-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--配置哪些請(qǐng)求需要攔截-->
        <mvc:mapping path="/**"/>
        <!--配置哪些請(qǐng)求不需要攔截-->
        <mvc:exclude-mapping path="/user/login"></mvc:exclude-mapping>
        <mvc:exclude-mapping path="/js/**"></mvc:exclude-mapping>
        <mvc:exclude-mapping path="/fonts/**"></mvc:exclude-mapping>
        <mvc:exclude-mapping path="/css/**"></mvc:exclude-mapping>
        <bean class="com.itheima.interceptor.PrivilegeInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

SpringMVC異常處理

系統(tǒng)中異常包括兩類:預(yù)期異常和運(yùn)行時(shí)異常RuntimeException鞍陨,前者通過(guò)捕獲異常從而獲取異常信息步淹,后者主要通過(guò)規(guī)范代碼開(kāi)發(fā)、測(cè)試通過(guò)手段減少運(yùn)行時(shí)異常的發(fā)生诚撵。

系統(tǒng)的dao缭裆、service、controller出現(xiàn)都通過(guò)throws Exception向上拋出寿烟,最后由springmvc前端控制器交由異常處理器進(jìn)行異常處理澈驼,如下圖:


異常環(huán)境搭建

導(dǎo)入相關(guān)依賴

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <!--spring版本鎖定-->
  <spring.version>5.0.2.RELEASE</spring.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-api</artifactId>
    <version>7.0.47</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper-el</artifactId>
    <version>7.0.47</version>
  </dependency>
</dependencies>
</project>

編寫核心控制器

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <!--配置SpringMVC核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!-- 配置Servlet的初始化參數(shù),讀取springmvc的配置文件筛武,創(chuàng)建spring容器 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>

    <!-- 配置servlet啟動(dòng)時(shí)加載對(duì)象 -->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!--配置springmvc過(guò)請(qǐng)求過(guò)濾器缝其,/表示所有請(qǐng)求都經(jīng)過(guò)springmvc處理-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

編寫核心配置文件

編寫核心配置文件springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置創(chuàng)建spring容器要掃描的包 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--SpringMVC注解驅(qū)動(dòng)-->
    <mvc:annotation-driven></mvc:annotation-driven>

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


</beans>

編寫前端頁(yè)面

編寫前端頁(yè)面index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>SpringMVC異常處理</title>
</head>
<body>
<h2>SpringMVC異常處理</h2>
<a href="${pageContext.request.contextPath}/exception/test">異常處理</a>
</body>
</html>

編寫控制層代碼

編寫控制代碼ExceptionController

package com.itheima.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/exception")
public class ExceptionController {

    @RequestMapping("/test")
    public String testException() throws Exception{
        System.out.println("控制器執(zhí)行成功...");
        int i = 10/0;
        return "success";
    }
}

異常處理方式

在SpringMVC中提供了二種異常處理方式 :

  • 使用Spring MVC提供的簡(jiǎn)單異常處理器SimpleMappingExceptionResolver

  • 實(shí)現(xiàn)Spring的異常處理接口HandlerExceptionResolver 自定義自己的異常處理器

簡(jiǎn)單異常處理器

SpringMVC已經(jīng)定義好了該類型轉(zhuǎn)換器,在使用時(shí)可以根據(jù)項(xiàng)目情況進(jìn)行相應(yīng)異常與視圖的映射配置

<!--配置簡(jiǎn)單映射異常處理器-->
<bean class=“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>       <property name=“defaultErrorView” value=“error”/>   默認(rèn)錯(cuò)誤視圖
    <property name=“exceptionMappings”>
        <map>       異常類型                                     錯(cuò)誤視圖
            <entry key="com.itheima.exception.MyException" value="error"/>
            <entry key="java.lang.ClassCastException" value="error"/>
        </map>
    </property>
</bean>

自定義異常處理器

編寫自定義異常CustomException

①創(chuàng)建異常處理器類實(shí)現(xiàn)HandlerExceptionResolver
②配置異常處理器
③編寫異常頁(yè)面
④測(cè)試異常跳轉(zhuǎn)

package com.itheima.exception;

public class CustomException extends Exception {

    private String message;

    public CustomException(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

定義異常處理器

自定義異常處理器CustomExceptionResolver

public class CustomExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
        ex.printStackTrace();
        CustomException customException = null;
        //如果拋出的是系統(tǒng)自定義異常則直接轉(zhuǎn)換
        if (ex instanceof CustomException) {
            customException = (CustomException) ex;
        } else {
            //如果拋出的不是系統(tǒng)自定義異常則重新構(gòu)造一個(gè)系統(tǒng)錯(cuò)誤異常徘六。
            customException = new CustomException("系統(tǒng)錯(cuò)誤内边,請(qǐng)與系統(tǒng)管理 員聯(lián)系!");
        }

        //創(chuàng)建ModelAndView對(duì)象
        ModelAndView modelAndView = new ModelAndView();
        //保存錯(cuò)誤信息
        modelAndView.addObject("message", customException.getMessage());
        //設(shè)置跳轉(zhuǎn)的視圖名稱
        modelAndView.setViewName("error");

        return modelAndView;
    }
}

編寫錯(cuò)誤頁(yè)面

編寫錯(cuò)誤頁(yè)面error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>執(zhí)行失敗</title>
</head>
<body>
 執(zhí)行失斔敦假残! ${message }
</body>
</html>

配置異常處理器

springmvc.xml中配置異常處理器

<!-- 配置自定義異常處理器 -->
<bean id="handlerExceptionResolver" class="com.itheima.exception.CustomExceptionResolver"/>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炉擅,隨后出現(xiàn)的幾起案子辉懒,更是在濱河造成了極大的恐慌,老刑警劉巖谍失,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眶俩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡快鱼,警方通過(guò)查閱死者的電腦和手機(jī)颠印,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門纲岭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人线罕,你說(shuō)我怎么就攤上這事止潮。” “怎么了钞楼?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵喇闸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我询件,道長(zhǎng)燃乍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任宛琅,我火速辦了婚禮刻蟹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘿辟。我一直安慰自己舆瘪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布仓洼。 她就那樣靜靜地躺著介陶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪色建。 梳的紋絲不亂的頭發(fā)上哺呜,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音箕戳,去河邊找鬼某残。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陵吸,可吹牛的內(nèi)容都是我干的玻墅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼壮虫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼澳厢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起囚似,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剩拢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后饶唤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體徐伐,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年募狂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了办素。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片角雷。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖性穿,靈堂內(nèi)的尸體忽然破棺而出勺三,到底是詐尸還是另有隱情,我是刑警寧澤季二,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布檩咱,位于F島的核電站揭措,受9級(jí)特大地震影響胯舷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绊含,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一桑嘶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧躬充,春花似錦逃顶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至伴找,卻和暖如春盈蛮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背技矮。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工抖誉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衰倦。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓袒炉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親樊零。 傳聞我的和親對(duì)象是個(gè)殘疾皇子我磁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容