SSM框架-SpringMVC


SpringMVC


一、SpringMVC概述

1. 三层架构

  1. 服务器端开发程序主要由两种形式构成。一种是基于客户端的C/S架构,另一种是基于浏览器的B/S架构
  2. Java语言主要用于开发B/S架构,其中的B/S架构又分为了三层架构。
    • 表现层:WEB层,用于和客户端进行数据交互。表现层一般会采用MVC的设计模型。
    • 业务层:处理具体的业务功能的
    • 持久层:用于进行数据存储,操作数据库的

2. MVC模型

  1. MVC全称为Model、View、Controller 模型视图控制器,每个部分功能不同
  2. Model(模型):数据模型,JavaBean的类,用于进行数据的封装
  3. View(视图):指JSP、Html等用于展示数据给用户
  4. Controller(控制器):用于接受用于的请求,整个流程的控制器。进行数据校验等。

二、Spring的简单应用

1. SpringMVC实例

  1. 进行版本锁定
<!-- 设置配置信息 -->
<properties>
    <!-- 设置编码格式 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- 设置源码jdk版本 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <!-- 设置生成后的jdk版本 -->
    <maven.compiler.target>1.8</maven.compiler.target>
    <!-- 针对Spring的相关jar包进行版本锁定 -->
    <spring.version>5.0.2.RELEASE</spring.version>
</properties>
  1. 导入相关坐标
<dependencies>
    <!-- 导入Spring相关坐标 -->
    <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>
    <!-- 导入WEB相关jar包 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  1. 在web.xml中对Servlet进行设置
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <!-- SpringMVC的核心控制器 -->
  <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>
    <!-- 配置servlet启动时就加载对象 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
  1. 在SpringMVC的配置文件中对Spring和SpringMVC进行设置
    1. 引入SpringMVC相关配置的约束头文件
    <?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">
    
    </beans>
    
    1. 对SpringMVC的配置文件进行操作
    <?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">
        <!-- 设置spring自动扫描的包 -->
        <context:component-scan base-package="com.hsh.study" />
    
        <!-- 配置视图解析器 -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 目标页面位于的位置 -->
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <!-- 目标页面的后缀名 -->
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!-- 配置SpringMVC开启注解MVC的支持 -->
        <mvc:annotation-driven></mvc:annotation-driven>
    </beans>
    
  2. 编写index.jsp和Controller控制类
    1. index.jsp的编写
    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>开始的地方</h1>
        <a href="${pageContext.request.contextPath}/hello">SpringMVC的使用</a>
    </body>
    </html>
    
    1. Controller控制类的编写
    @Controller("accountController")
    public class AccountController {
        @RequestMapping("/hello")
        public String sayHello(){
            System.out.println("Hello SpringMVC!");
            return "success";
        }
    }
    
  3. 编写跳转成功页面(写在WEB-INF下的pages目录下)
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>欢迎来到成功界面</title>
    </head>
    <body>
            <h1>欢迎来到成功界面!!!</h1>
    </body>
    </html>

2. SpringMVC运行过程

  1. 当tomcat服务器运行时,因为在web.xml中配置的Servlet中选择了<load-on-startup>标签,所以在tomcat服务器启动时便创建了DispatcherServlet对象,同时执行servlet中的<init-param>加载Spring的springmvc.xml配置文件
  2. 由于Spring的配置文件中开启了注解扫描,那么Spring将为写的类AccountController创建对象
  3. 从index.jsp中发出请求后,请求首先到达DispatcherServlet核心控制器,根据配置的@RequestMapping注解找到执行的具体方法
  4. 根据执行方法的返回值,同时依据Spring配置文件中配置的视图解析器,会去指定目录下寻找指定名称的.jsp文件
  5. TomCat拿到结果并返回给用户。

3. SpringMVC中的组件

  1. 前端控制器(DispatcherServlet)
  2. 处理器映射器(HandlerMapping)
  3. 处理器(Handler)
  4. 处理器适配器(HandlAdapter)
  5. 视图解析器(View Resolver)
  6. 视图(View)

三、请求参数的绑定

1. 请求参数绑定概念

  1. 绑定机制
    • 由于表单中提交的数据都是k=v格式的,如:(username=root&password=123),所以SpringMVC的参数绑定过程便是将表单提交的请求参数作为控制器中方法的参数进行绑定的。
    • 要求:提交表单的属性值与参数的名称要一致。
  2. 支持的数据类型
    • 基本数据类型和字符串类型
    • 实体类类型(JavaBean)
    • 集合数据类型(List、Map集合等)

2. 基本数据类型和字符串类型

  • 提交表单的属性和参数的名称要要一致
  • 区分大小写

3. 实体类型(JavaBean)

  • 提交表单的属性和JavaBean中的属性名称要一致
  • 如果一个JavaBean类中包含其他的引用类型,那么表单的属性需要编成:对象.属性 如:user.name

4. 给集合属性封装

  • JSP页面编写方式:list[0].属性

5. 请求参数中文乱码的解决

  • 在web.xml中配置Spring提供的过滤器类
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!-- 配置过滤器 -->
  <filter>
    <filter-name>encodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>     
</web-app>

6. 自定义类型转换器

  1. 表单提交时任何数据都是字符串类型的,但是Spring框架内部提供了默认进行数据类型转换的方式。
  2. Spring同时也可以实现自定义数据的类型转换,实现方式为实现Converter接口
    • 自定义类型转换器
    public class StringToDateConverter implements Converter<String, Date> {
        /**
         * 进行类型转换
         * @param source
         * @return
         */
        @Override
        public Date convert(String source) {
            // 判断是否为空
            if (source == null){
                throw new RuntimeException("参数不能为空");
            }
            try {
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                // 解析字符串
                Date date = df.parse(source);
                return date;
            } catch (ParseException e) {
                throw new RuntimeException("参数转换异常!");
            }
        }
    }
    
    • 注册自定义类型转换器,在springmvc.xml配置文件中配置
    <!-- 注册自定义类型转换器 -->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.hsh.study.utils.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>
    <!-- 配置SpringMVC开启注解MVC的支持 -->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    

7. 在控制器中使用原生ServletAPI对象

  • 在控制器方法参数处定义HttpServletRequest和HttpServletResponse对象

四、SpringMVC常用注释

1. @RequestMapping

  1. 作用:RequestMapping注解的作用是建立请求Url和处理方法之间的对应关系
  2. 应用场景:RequestMapping注解可以作用于方法和类上
    • 作用在类上时:一级访问目录
    • 作用在方法上时:如果类上没有该注解则为一级目录,否则为二级访问目录
    • 在写url路径时可以省略/表示从应用的根目录开始,同时${pageContext.request.contextPath}也可以省略不写,但是路径上不能写/
  3. RequestMapping的属性
    • path:指定请求路径的url
    • value:value属性和path属性是一样的
    • method:指定方法的请求方式
    • params:指定限制请求参数的条件
    • headers:发送的请求中必须包含的请求头

2. @RequestParam

  1. 作用:将请求中的指定名称的参数传递给控制器中的形参赋值(作用于当实体类中的属性名和请求中的属性名不同时)
  2. 属性:
    • value:请求参数中的名称
    • required:请求参数中是否必须提供此参数,默认值为true
  3. 具体操作:
@RequestMapping("/hello")
public String getForm(@RequestParam(value="username",required=false)String uname){
    System.out.println(uname);
    return "success";
}

3. @RequestBody

  1. 作用:用于获取请求体的内容(get方式无请求体)
  2. 属性
    • required:是否必须有请求体,默认值为true
  3. 具体操作:
@RequestMapping("/hello")
public String getForm(@RequestBody String body){
    System.out.println(body);
    return "success";
}

4. @PathVariable

  1. 作用:用于绑定url中的占位符的。如url的路径为:/delete/{id} 这之中的{id}就是占位符
  2. 属性
    • value:指定url中的占位符名称
      3.Restful风格的URL
    1. 请求路径一样,根据不同的请求方式去执行后台的不同方法。
    2. Restful风格的URL优点:①结构清晰 ②符合标准 ③易于理姐 ④方便扩展
  3. 具体操作
@RequestMapping("/hello")
public String getForm(@PathVariable(value="id")String id){
    System.out.println(id);
    return "success";
}

5. @RequestHeader

  1. 作用:获取指定请求头的值
  2. 属性
    • value:请求头的名称
  3. 具体操作
@RequestMapping("/hello")
public String getForm(@RequestHeader("Accept")String header){
    System.out.println(header);
    return "success";
}

6. @CookieValue

  1. 作用:获取指定Cookie名称的值
  2. 属性
    • value:cookie的名称
  3. 具体操作
@RequestMapping("/hello")
public String getForm(@CookieValue(value="JSESSIONID")String cookieValue){
    System.out.println(cookieValue);
    return "success";
}

7. @ModelAttribute

  1. 作用
    • 出现在方法上:表示该方法会在控制器方法执行前先执行
    • 出现在参数上:获取指定的数据给参数赋值
  2. 应用场景
    • 当提交的表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据
  3. 具体操作
    • 修饰的方法有返回值
    // 作用于方法上时,先执行该方法再执行控制器方法
    @ModelAttribute
    public User showUser(String name){
        User user = new User();
        user.setUsername("张三");
        user.setAge(12);
        user.setMoney(1111);
        return user;
    }
    
    // 修改用户的操作
    @RequestMapping("/updateUser")
    public String updateUser(User user){
        System.out.println(user);
        reutrn "success";
    }
    
    • 修饰的方法无返回值
    // 作用于方法上时,先执行该方法再执行控制器方法
    @ModelAttribute
    public void showUser(String name, Map<String, User> map){
        // 模拟从数据库中查询对象
        User user = new User();
        user.setUsername("李四");
        user.setAge(15);
        user.setMoney(2222);
        // 存入Map集合
        map.put("user",user);
    }
    
    // 修改用户的操作
    @RequestMapping("/updateUser")
    public String updateUser(@ModelAttribute(value="user")User user){
        System.out.println(user);
        reutrn "success";
    }
    

8. @SessionAttribute

  1. 作用:用于多次执行控制器方法间的参数共享
  2. 属性
    • value:指定存入属性的名称
  3. 具体操作
@Controller("helloController")
@RequestMapping("/user")
// 将数据存入Session域对象中
@SessionAttribute(value = {"username", "password", "age"}, types={String.class,Integer.class})
public class HelloController{
    // 向session中存入值
    @RequestMapping("/save")
    public String save(Model model){
        System.out.println("向session域中保存数据");
        model.setAttribute("username","root");
        model.setAttribute("password","123");
        model.setAttribute("age",123);
        return "success";
    }
    
    // 向session中取值
    @RequestMapping("/find")
    public String find(ModelMap modelMap){
        String username = (String) modelMap.get("username");
        String password = (String) modelMap.get("password");
        Integer age = (Integer) modelMap.get("age");
        System.out.println(username + " " + password + " " + age);
        return "success";
    }
    
    // 清除session中的值
    @RequestMapping("/delete")
    public String delete(SessionStatus status){
        status.setComplete();
        return "success";
    }
}

五、响应数据和结果视图

1. 返回值分类

  1. 字符串
    • Controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
    // 在springmvc.xml文件中配置视图解析器
    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 目标页面位于的位置 -->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <!-- 目标页面的后缀名 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
    
    // 字符串返回
    @RequestMapping("/hello")
    public String sayHello(){
        System.out.println("Hello SpringMVC!");
        // 指定逻辑视图名,经过视图解析器解析为jsp的物理路径:/WEB-INF/pages/success.jsp
        return "success";
    }
    
  2. void
    • 当返回值为void时,页面的跳转可以使用原生Servlet中的转发和重定向完成页面的跳转
      1. 转发
      @RequestMapping("/testReturnVoid")
      public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
          // 使用转发转向页面
          request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
      }
      
      1. 重定向
      @RequestMapping("/testReturnVoid")
      public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
           // 使用重定向进行跳转
          response.sendRedirect( request.getContextPath() + "/Redirect.jsp");
      }
      
      1. 直接响应数据
      @RequestMapping("/testReturnVoid")
      public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
          // 直接响应数据
          response.setContentType("text/html;charset=utf-8");
          response.getWriter().write("响应成功!");
          return;
      }
      
  3. ModelAndView
    • ModelAndView是SpringMVC中提供的一个对象,该对象可以用控制器方法的返回值。
    @RequestMapping("/testReturnModelAndView")
    public ModelAndView testReturnModelAndView(){
        ModelAndView mv = new ModelAndView();
        // 向request域中添加值
        mv.addObject("username","张三");
        // 设置跳转的页面
        mv.setViewName("success");
        return mv;
    }
    

2. 转发和重定向

  1. forward 转发
    • Controller方法在提供了String类型的返回值后,默认的就是使用请求转发,在返回值中使用:forward:
    @RequestMapping("/testForward")
    public String testForward(){
        System.out.println("执行重定向操作!");
        return "forward:/WEB-INF/pages/success.jsp";
    }
    
    • 注:如果使用了==forward:== 则路径必须携程实际视图的url,相当于request.getRequestDispatcher(url).forward(request,response);。使用请求转发既可以转发到jsp中,也可以转发到其他控制器中。
  2. Redirect 重定向
    • Controller方法在提供了String类型的返回值后,在返回值中使用:redirect:
    @RequestMapping("/testRedirect")
    public String testRedirect(){
        System.out.println("执行重定向操作!");
        return "redirect:testForward";
    }
    
    • 注:此语句相当于response.sendRedirect(url)。如果重定向到jsp页面,则jsp的页面必须位于WEB-INF目录下,否则无法找到。

3. ResponseBody响应json数据

  • 该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据:json、xml等,并通过Response响应给客户端
  1. 首先DispatcherServlet核心控制器会拦截所有的资源,导致了静态资源(html、css、js)都会被拦截,从而无法使用。解决的方法是通过配置springmvc.xml配置文件使得静态资源的访问不进行拦截。
    • <mvc:resources>标签可以配置不过滤
      1. location:表示webapp目录下的所有文件
      2. mapping:表示以/static开头的所有请求路径,如/static/a和/static/b
    • 配置
    <!-- 设置静态资源不过滤-->
    <!-- 样式 -->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <!-- 图片 -->
    <mvc:resources location="/images/" mapping="/images/**"/>
    <!-- javascript -->
    <mvc:resources location="/js/" mapping="/js/**"/> 
    
  2. 使用@ResponseBody需要使用jackson的jar包
    • 引入jackson的jar包
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>
    
  3. 使用ajax请求json时导入JQuery
  4. 编写前端JS代码和表单
<!------------------------JS代码--------------------------------->
<script src="js/jquery.min.js"></script>
<script>
   $(function () {
       $("#btn").click(function () {
          $.ajax({
              type:"post",
              url:"account/testJson",
              contentType:"application/json;charset=utf-8",
              data:'{"name":"张三","money":123.12}',
              dataType:"json",
              success:function (data) {
                  alert(data.id);
                  alert(data.name);
                  alert(data.money);
              }
          });
       });
   });
</script>
<!------------------------HTML代码--------------------------------->
<hr>
<input type="button" id="btn" value="发送Ajax请求得到json响应数据">
<hr>
  1. 编写控制器类
@Controller("accountController")
@RequestMapping("/account")
public class AccountController {
    @RequestMapping("/testJson")
    public @ResponseBody Account testJson(@RequestBody Account account){
        System.out.println("执行Json操作!");
        System.out.println(account);
        account.setId(15);
        return account;
    }
}

二、SpringMVC实现文件上传

1. 传统的文件上传方式

  1. 文件上传的前提
    • form表单的enctype的取值必须为:multipart/form-data (默认值为application/x-www-form-urlencoded) ==enctype:是表单请求正文的类型==
    • method属性值必须为:post
    • 提供文件选择框:<input type="file" />
  2. 文件上传所需jar包
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
  1. JSP页面
<form action="user/fileupload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br>
    <input type="submit" value="提交">
</form>
  1. 文件上传的控制类
@RequestMapping("/fileupload")
public String fileupload(HttpServletRequest request) throws Exception{
    // 获取要上传的文件目录
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建File文件对象
    File file = new File(path);
    // 判断路径是否存在
    if(!file.exists()){
        file.mkdirs();
    }
    // 创建磁盘文件项工厂
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    // 解析request对象
    List<FileItem> list = fileUpload.parseRequest(request);
    // 遍历
    for (FileItem fileItem : list){
        // 判断文件项是否为上传的文件
        if(fileItem.isFormField()){

        }else{
            // 是上传的文件
            String filename = fileItem.getName();
            // 上传文件
            fileItem.write(new File(file, filename));
            // 删除临时文件
            fileItem.delete();
        }
    }
    return "success";
}

2. SpringMVC上传方式

  1. 文件上传所需jar包
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
  1. 编写控制器类
@RequestMapping("/fileupload2")
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception{
    // 获取要上传的文件目录
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建File文件对象
    File file = new File(path);
    // 判断路径是否存在
    if(!file.exists()){
        file.mkdirs();
    }
    // 获取到上传文件的名称
    String filename = upload.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    // 将文件名称唯一化
    filename = uuid + "_" + filename;
    // 上传文件
    upload.transferTo(new File(file,filename));
    return "success";
}
  1. 编写文件解析器
<!-- 配置文件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"/>
</bean>

3. SpringMVC跨服务器方式文件上传

  1. 导入开发所需jar包
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-core</artifactId>
    <version>1.18.1</version>
</dependency>
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-client</artifactId>
    <version>1.18.1</version>
</dependency>

  1. 编写控制器
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
    System.out.println("SpringMVC跨服务器方式的文件上传...");
    // 定义图片服务器的请求路径
    String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
    // 获取到上传文件的名称
    String filename = upload.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    // 把文件的名称唯一化
    filename = uuid+"_"+filename;
    // 向图片服务器上传文件
    // 创建客户端对象
    Client client = Client.create();
    // 连接图片服务器
    WebResource webResource = client.resource(path+filename);
    // 上传文件
    webResource.put(upload.getBytes());
    return "success";
}

4. 上传文件后进行回显

  1. 在 springmvc.xml 开启 mvc 注解支持
<!-- 开启springmvc注解支持 -->
    <mvc:annotation-driven />
  1. 在 springmvc.xml 中配置静态资源不过滤
<mvc:resources location="/img/" mapping="/img/**"/>
<!--我这里文件上传后的目录为 /upload,所以此处不过滤 /upload -->
<mvc:resources location="/upload/" mapping="/upload/**"/>
  1. 在文件上传的基础上增加如下代码
@RequestMapping("/fileupload")
    public String fileupload(MultipartFile upload, HttpServletRequest request) throws IOException {
        String realPath = request.getSession().getServletContext().getRealPath("/upload");
        File file = new File(realPath);
        if(!file.exists()){
            file.mkdirs();
        }
        String filename = upload.getOriginalFilename();
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        filename = uuid + filename;
        upload.transferTo(new File(file, filename));
        request.getSession().setAttribute("img","/upload/" + filename);
        return "success";
    }
  1. 编写回显到浏览器的页面
<H1>成功</H1>
<img src="${pageContext.request.contextPath}${img}" alt="">

5. SpringMVC 实现下载文件

  1. 编写调用下载的界面
<a href="${pageContext.request.contextPath}/test/download?image=cunhua.jpg" >下载此图片</a>
  1. 编写文件下载的 Controller
 @RequestMapping("/download")
    public void download(@RequestParam(name = "image") String image, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 设置响应头
        response.setHeader("Content-Disposition", "attachment;filename="+image);
        // 获取真实路径
        String realPath = request.getSession().getServletContext().getRealPath("/img");
        // 读取文件流
        FileInputStream is = new FileInputStream(realPath + "/" + image);
        //写文件的流
        ServletOutputStream os = response.getOutputStream();
        //copy
        IOUtils.copy(is, os);
        //关闭
        is.close();
        os.close();
    }

3. SpringMVC的异常处理

1. 异常处理思路

  • Controller调用service,service调用dao,异常都是向上抛出,最终由DispathcerServlet找异常处理器进行异常处理。

2. SpringMVC的异常处理

  1. 自定义异常类
public class SysException extends Exception {
    private String message;

    @Override
    public String getMessage() {
        return message;
    }

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

    public SysException(String message) {
        this.message = message;
    }
}
  1. 自定义异常处理器
public class SysExceptionResolver implements HandlerExceptionResolver {
    /**
     * 跳转到具体的错误页面的方法
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        e.printStackTrace();
        SysException exception = null;
        // 获取到异常对象
        if(e instanceof SysException){
            exception = (SysException) e;
        }else{
            exception = new SysException("联系我!");
        }
        ModelAndView mv = new ModelAndView();
        // 存入错误的提示信息
        mv.addObject("message",exception.getMessage());
        // 跳转的jsp页面
        mv.setViewName("error");
        return mv;
    }
}
  1. 配置异常处理器
<!-- 配置异常处理器 -->
<bean id="sysExceptionResolver" class="com.hsh.study.exception.SysExceptionResolver"></bean>

4. SpringMVC的拦截器

1. 概念

SpringMVC的处理器拦截器类类似于Servlet中的过滤器Filter,用于对处理其进行预处理和后处理。

  • 过滤器和拦截器的区别
    • 过滤器是Servlet规范中的一部分,任何Java Web工程都可以使用
    • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才可以使用
    • 过滤器在url-pattern中配置了/*后,可以对所有要访问的资源进行拦截
    • 拦截器只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或js都不回进行拦截
  • 自定义拦截器必须实现此接口:HandlerInterceptor

2. 自定义拦截器

  1. 创建拦截器并实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor{
    /**
    * controller方法执行前,进行拦截的方法
    * return true放行
    * return false拦截
    * 可以使用转发或者重定向直接跳转到指定的页面。
    */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception {
        System.out.println("拦截器执行了...");
        return true;
    }
}

  1. 在springmvc中配置拦截器
<!-- 配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 哪些方法进行拦截-->
        <mvc:mapping path="/user/*"/>
        <!-- 哪些方法不进行拦截
        <mvc:exclude-mapping path=""/>
        -->
        <!-- 注册拦截器对象-->
        <bean class="cn.itcast.demo1.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>

3. HandlerInterceptor接口中的方法

  1. preHandle方法是controller方法执行前拦截的方法
    1. 可以使用request或者response跳转到指定的页面
    2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
    3. return false不放行,不会执行controller中的方法。
  2. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
    1. 可以使用request或者response跳转到指定的页面
    2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  3. postHandle方法是在JSP执行后执行
    1. request或者response不能再跳转页面了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342