zoukankan      html  css  js  c++  java
  • SpringMVC学习文档

    SpringMVC学习文档

    springMVC就是类似与Struts2的mvc框架,始于SpringFrameWork的后续产品

    为什么要学习SpringMVC?

    springMVC Struts2 区别
    对比项目 SpringMVC Struts2 优势
    国内市场情况 有大量用户,一般新项目启动都选择springmvc 有部分老用户,一直在使用 国内情况springmvc的shiyonglv已经超过了struts2
    框架入口 基于servlet 基于filter 只是配置方式不同
    框架设计思想 控制器基于方法级别的拦截,处理器设计为单实例 控制器基于类级别拦截,处理器设计为多实例 由于设计本身的原因,造成了struts2只能设计为多实例模式,相比于springmvc设计为单实例模式,struts2会消耗更多服务器内存
    参数传递 通过方法入参传递 通过类的成员变量传递 struts2通过成员变量传递参数,导致参数线程不安全,有可能引发并发的问题
    与spring整合 与spring同一家公司可以与spring无缝整合 需要整合包 springmvc与spring整合更轻松

    一.概述

    1.1SpringMVC入门

    1.1.1配置核心控制器web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <!-- 配置spring mvc的核心控制器-->
    <servlet>
    <servlet-name>SpringMVCDispatcherServlet</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>
    <!-- 配置servlet的对象的创建时间点:应用加载时创建。
    取值只能是非0正整数,表示启动顺序-->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>SpringMVCDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    </web-app>
    

    1.1.2配置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">
    <!-- 配置创建spring容器要扫描的包-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
    <!-- 配置视图解析器-->
    <bean id="internalResourceViewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>
        <!--开启springmvc框架注解的支持 -->
        <mvc:annotation-friven/>
    </beans>
    

    1.1.3编写控制器并使用注解配置

    @Controller("helloController")
    public class HelloController {
    @RequestMapping("/hello")
    public String sayHello() {
    System.out.println("HelloController的sayHello 方法执行了。。。。");
    return "success";
    }
    }
    

    1.2SpringMVC架构

    1.2.1框架默认加载组件

    img

    处理器映射器与处理器适配器

    处理器映射器

    从spring3.1开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射

    class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    处理器适配器

    从spring3.1开始,废除了AnnotationMethodHandlerMapping的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配

    <bean class"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter "/>

    <! --配置注解驱动相当于同时使用最新的处理器映射器和处理器适配器 ,对json数据响应提供支持 -->

    <mvc:annotation-driven />

    视图解析器

    mav.setViewName("itemList");

    在springmvc.xml中

    1.3概述

    Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。 MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。

    • 模型(Model)封装了应用程序数据,通常它们将由POJO类组成。
    • 视图(View)负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
    • 控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

    1.4优点

    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风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配
    置支持等等。

    1.5.RequestMapping注解

    1.5.1作用

    用于建立请求URL和处理请求方法之间的对应关系。

    出现的位置

    类上:请求URL一级目录

    方法上:请求URL二级目录

    1.5.2属性

    value:用于指定请求的URL 与path属性相同(若只有value属性 value可省略)

    method:用于指定请求的方式

    params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和
    配置的一模一样。
    例如:
    params = {"accountName"},表示请求参数必须有accountName
    params = {"moeny!100"},表示请求参数中money不能是100。

    headers:用于指定限制请求消息头的条件。

    二.请求参数的绑定

    2.1绑定机制

    我们都知道,表单中请求参数都是基于key=value的。
    SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。
    例如:
    < a href="account/findAccount?accountId=10">查询账户中请求参数是:
    accountId=10

    @RequestMapping("/findAccount")
    public String findAccount(Integer accountId) {
    System.out.println("查询了账户。。。。"+accountId);
    return "success";

    2.2支持数据类型

    基本类型参数:
    包括基本类型和String类型
    POJO类型参数:
    包括实体类,以及关联的实体类
    数组和集合类型参数:
    包括List结构和Map结构的集合(包括数组)

    Model类型:

    用于数据的返回详见4.1.1

    SpringMVC绑定请求参数是自动实现的,但是要想使用,必须遵循以下使用要求。

    如果是基本类型或者String类型:
    要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
    如果是POJO类型,或者它的关联对象:
    要求表单中参数名称和POJO类的属性名称保持一致。并且控制器方法的参数类型是POJO类型。若是POJO含有包装对象则通过 . 来传递属性

    如果是集合类型,有两种方式:

    第一种:
    要求集合类型的请求参数必须在POJO中。在表单中请求参数名称要和POJO中集合属性名称相同。
    给List集合中的元素赋值,使用下标。
    给Map集合中的元素赋值,使用键值对。

    public class User implements Serializable {
    private String username;
    private String password;
    private Integer age;
    private List<Account> accounts;
    private Map<String,Account> accountMap;
    
    
    <form action="account/updateAccount" method="post">
    用户名称:<input type="text" name="username" ><br/>
    用户密码:<input type="password" name="password" ><br/>
    用户年龄:<input type="text" name="age" ><br/>
    账户1名称:<input type="text" name="accounts[0].name" ><br/>
    账户1金额:<input type="text" name="accounts[0].money" ><br/>
    账户2名称:<input type="text" name="accounts[1].name" ><br/>
    账户2金额:<input type="text" name="accounts[1].money" ><br/>
    账户3名称:<input type="text" name="accountMap['one'].name" ><br/>
    账户3金额:<input type="text" name="accountMap['one'].money" ><br/>
    账户4名称:<input type="text" name="accountMap['two'].name" ><br/>
    账户4金额:<input type="text" name="accountMap['two'].money" ><br/>
    <input type="submit" value="保存">
    </form>
    

    第二种:
    接收的请求参数是json格式数据。需要借助一个注解实现。

    2.3请求参数乱码

    在web.xml中配置过滤器

    <!-- 配置springMVC编码过滤器-->
    <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>
    <!-- 启动过滤器-->
    <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>
    <!-- 过滤所有请求-->
    <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    在springmvc的配置文件中可以配置,静态资源不过滤:
    <!-- location表示路径,mapping表示文件,**表示该目录下的文件以及子目录的文件-->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/scripts/" mapping="/javascript/**"/>
    
    

    2.4自定义类型转换器

    Springmvc在提交请求时所有的参数都是String类型 ,只不过springmvc在封装的时候会对大部分基本数据类型进行数据类型转换。

    但使用date时提交2020/01/01 会帮助转换,但提交2020-01-01时springmvc不支持这种格式的日期转换所以需要自定义类型转换器

    第一步:定义一个类,实现Converter接口,该接口有两个泛型。

    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="com.itheima.web.converter.StringToDateConverter"></bean>
    </array>
    </property>
    </bean>
    
    

    第三步:在annotation-driven标签中引用配置的类型转换服务

    <mvc:annotation-driven
    conversion-service="converterService"></mvc:annotation-driven>
    
    

    三.常用注解

    3.1RequestParam

    作用:
    把请求中指定名称的参数给控制器中的形参赋值。
    属性:
    value:请求参数中的名称。
    required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。

    示例:

    <!-- requestParams注解的使用-->
    <a href="springmvc/useRequestParam?name=test">requestParam注解</a>
    
    
    @RequestMapping("/useRequestParam")
    public String useRequestParam(@RequestParam("name")String username,
    @RequestParam(value="age",required=false)Integer age){
    System.out.println(username+","+age);
    return "success";
    }
    

    3.2RequestBody

    作用:
    用于获取请求体内容。直接使用得到是key=value&key=value...结构的数据。
    get请求方式不适用。
    属性:
    required:是否必须有请求体。默认值是:true。当取值为true时,get请求方式会报错。如果取值
    为false,get请求得到是null。

    示例

    post请求jsp代码:
    <!-- request body注解-->
    <form action="springmvc/useRequestBody" method="post">
    用户名称:<input type="text" name="username" ><br/>
    用户密码:<input type="password" name="password" ><br/>
    用户年龄:<input type="text" name="age" ><br/>
    <input type="submit" value="保存">
    </form>
    get请求jsp代码:
    <a href="springmvc/useRequestBody?body=test">requestBody注解get请求</a>
    控制器代码:
    @RequestMapping("/useRequestBody")
    public String useRequestBody(@RequestBody(required=false) String body){
    System.out.println(body);
    return "success";
    }
    
    

    结果:post打印数据get打印null

    3.3PathVaribale

    作用:
    用于绑定url中的占位符。例如:请求url中/delete/{id},这个{id}就是url占位符。
    url支持占位符是spring3.0之后加入的。是springmvc支持rest风格URL的一个重要标志。
    属性:
    value:用于指定url中占位符名称。
    required:是否必须提供占位符。

    示例

    <!-- PathVariable注解-->
    <a href="springmvc/usePathVariable/100">pathVariable注解</a>
    
    @RequestMapping("/usePathVariable/{id}")
    public String usePathVariable(@PathVariable("id") Integer id){
    System.out.println(id);
    return "success";
    }
    

    3.4CookieValue

    作用:
    用于把指定cookie名称的值传入控制器方法参数。
    属性:
    value:指定cookie的名称。
    required:是否必须有此cookie。

    3.5ModelAttribute

    作用:
    该注解是SpringMVC4.3版本以后新加入的。它可以用于修饰方法和参数。
    出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可
    以修饰有具体返回值的方法。
    出现在参数上,获取指定的数据给参数赋值。
    属性:
    value:用于获取数据的key。key可以是POJO的属性名称,也可以是map结构的key。
    应用场景:
    当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
    例如:
    我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数
    据是肯定没有此字段的内容,一旦更新会把该字段内容置为null,此时就可以使用此注解解决问题。

    四.响应数据和结果试图

    4.1返回值分类

    4.1.1字符串

    controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
    //指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/pages/success.jsp
    @RequestMapping("/testReturnString")
    public String testReturnString(Model model) {
    System.out.println("AccountController的testReturnString 方法执行了。。。。");
    User user =new User();
        model.addAttribute("user",user);
    return "success";
    }
    
    success.jsp
    <html>
    ....
    <body>
    ${user.name}   //如此即可取值
    </body>
    </html>
    

    4.2.2void

    如果没有return 会自动跳到此路径的jsp 比如 testReturnVoid.jsp

    @RequestMapping("/testReturnVoid")
    public void testReturnVoid(HttpServletRequest request,HttpServletResponse response)
    throws Exception {
    }
    //此时若想跳转
    //1:使用request转发
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,
    response);
    //2:使用response页面重定向
    response.sendRedirect("testRetrunString");
    //3:使用response指定响应结果
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json串");
    
    

    4.2.3ModelAndView

    ModelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。总体上与4.1.1中的类似。

    该对象有两个方法:

    addObject() 添加模型到对象中 与model类似 在jsp中用el表达式即可获取 ${attributeName}

    setViewName() 用于设置逻辑视图名称

    示例

    @RequestMapping("/testReturnModelAndView")
    public ModelAndView testReturnModelAndView() {
    ModelAndView mv = new ModelAndView();
    mv.addObject("username", "张三");
    mv.setViewName("success");
    return mv;
    }
        
    
    

    我们在页面上上获取使用的是requestScope.username取的,所以返回ModelAndView类型时,浏
    览器跳转只能是请求转发。

    4.2转发和重定向

    4.3ResponseBody 响应json数据

    作用:
    该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的
    数据如:json,xml等,通过Response响应给客户端

    jsp中的代码:
    <script type="text/javascript"
    src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
    <script type="text/javascript">
    $(function(){
    $("#testJson").click(function(){
    $.ajax({
    type:"post",
    url:"${pageContext.request.contextPath}/testResponseJson",
    contentType:"application/json;charset=utf-8",
    data:'{"id":1,"name":"test","money":999.0}',
    dataType:"json",
    success:function(data){
    alert(data);
    }
    });
    });
    })
    </script>
    <!-- 测试异步请求-->
    <input type="button" value="测试ajax请求json和响应json" id="testJson"/>
    
    
    控制器中的代码:
    /**
    * 响应json数据的控制器
    * @author 黑马程序员
    * @Company 
    * @Version 1.0
    */
    @Controller("jsonController")
    public class JsonController {
    /**
    * 测试响应json数据
    */
    @RequestMapping("/testResponseJson")
    public @ResponseBody Account testResponseJson(@RequestBody Account account) {
    System.out.println("异步请求:"+account);
    return account;
    }
    }
    

    五.SpringMVC实现文件上传

    5.1原理分析

    5.1.1前提

    A form表单的enctype取值必须是:multipart/form-data
    (默认值是:application/x-www-form-urlencoded)
    enctype:是表单请求正文的类型
    B method属性取值必须是Post
    C 提供一个文件选择域< input type="file" />

    一定要确保在您的 classpath 中有最新版本的 commons-fileupload.x.x.jar 文件。

    一定要确保在您的 classpath 中有最新版本的 commons-io-x.x.jar 文件。

    5.1.2示例

    jsp代码

    <form method="post" action="/TomcatTest/UploadServlet" enctype="multipart/form-data">
        选择一个文件:
        <input type="file" name="uploadFile" />
        <br/><br/>
        <input type="submit" value="上传" />
    </form>
    

    servlet代码

    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        // 上传文件存储目录
        private static final String UPLOAD_DIRECTORY = "upload";
        // 上传配置
        private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
        private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
        private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB
        /**
         * 上传数据及保存文件
         */
        protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
            // 检测是否为多媒体上传
            if (!ServletFileUpload.isMultipartContent(request)) {
                // 如果不是则停止
                PrintWriter writer = response.getWriter();
                writer.println("Error: 表单必须包含 enctype=multipart/form-data");
                writer.flush();
                return;
            }
            // 配置上传参数
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
            factory.setSizeThreshold(MEMORY_THRESHOLD);
            // 设置临时存储目录
            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 设置最大文件上传值
            upload.setFileSizeMax(MAX_FILE_SIZE);
            // 设置最大请求值 (包含文件和表单数据)
            upload.setSizeMax(MAX_REQUEST_SIZE);
            // 中文处理
            upload.setHeaderEncoding("UTF-8"); 
            // 构造临时路径来存储上传的文件
            // 这个路径相对当前应用的目录
            String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;
            // 如果目录不存在则创建
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdir();
            }
            try {
                // 解析请求的内容提取文件数据
                @SuppressWarnings("unchecked")
                List<FileItem> formItems = upload.parseRequest(request);
     
                if (formItems != null && formItems.size() > 0) {
                    // 迭代表单数据
                    for (FileItem item : formItems) {
                        // 处理不在表单中的字段
                        if (!item.isFormField()) {
                            String fileName = new File(item.getName()).getName();
                            String filePath = uploadPath + File.separator + fileName;
                            File storeFile = new File(filePath);
                            // 在控制台输出文件的上传路径
                            System.out.println(filePath);
                            // 保存文件到硬盘
                            item.write(storeFile);
                            request.setAttribute("message",
                                "文件上传成功!");
                        }
                    }
                }
            } catch (Exception ex) {
                request.setAttribute("message",
                        "错误信息: " + ex.getMessage());
            }
            
        }
    }
    

    5.2springmvc传统方式文件上传

    传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。
    并且上传完成之后,浏览器可能跳转。

    步骤

    1. 拷贝5.1中的两个jar包

    2. jsp页面

      <form action="/fileUpload" method="post" enctype="multipart/form-data">
          <imput type="file" name="uploadFile"/ >
              <input type="submit" value="上传">
      </form>
      
    3. 编写控制器

      @Controller("fileUploadController")
      public class FileUploadController {
      /**
      * 文件上传
      */
      @RequestMapping("/fileUpload")
      public String testResponseJson(String picname,MultipartFile
      uploadFile,HttpServletRequest request) throws Exception{
              //定义文件名
              String fileName = "";
              //1.获取原始文件名
              String uploadFileName = uploadFile.getOriginalFilename();
              //2.截取文件扩展名
              String extendName uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,
              uploadFileName.length());
              //3.把文件加上随机数,防止文件重复
              String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
              //4.判断是否输入了文件名
              if(!StringUtils.isEmpty(picname)) {
              fileName = uuid+"_"+picname+"."+extendName;
              }else {
              fileName = uuid+"_"+uploadFileName;
              }
              System.out.println(fileName);
              //2.获取文件路径
              ServletContext context = request.getServletContext();
              String basePath = context.getRealPath("/uploads");
              //3.解决同一文件夹中文件过多问题
              String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
              //4.判断路径是否存在
              File file = new File(basePath+"/"+datePath);
              if(!file.exists()) {
              file.mkdirs();
              }
              //5.使用MulitpartFile接口中方法,把上传的文件写到指定位置
              uploadFile.transferTo(new File(file,fileName));
              return "success";
      	}
      }
      
    4. 配置文件解析器

    <!-- 配置文件上传解析器-->
    <bean id="multipartResolver" <!-- id的值是固定的-->
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为5MB -->
    <property name="maxUploadSize">
    <value>5242880</value>
    </property>
    </bean>
    注意:
    文件上传的解析器id是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他
    字段也将无法绑定)
    

    5.3springmvc跨服务器上传

    5.3.1分服务器目的

    在实际开发中,我们会有很多处理不同功能的服务器。例如:
    应用服务器:负责部署我们的应用
    数据库服务器:运行我们的数据库
    缓存和消息服务器:负责处理大并发访问的缓存和消息
    文件服务器:负责存储用户上传文件的服务器。
    (注意:此处说的不是服务器集群)

    分服务器目的是为了让服务器各司其职,提高运行效率

    5.3.2步骤

    准备两个服务器

    在文件服务器的tomcat配置中加入允许读写操作

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
        	<param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>							//
        	<param-name>readonly</param-name>	//加入这几行的目的是:
            <param-value>false</param-value>	//
        </init-param>							//接收文件的目标服务器可以支持写入操作
         <init-param>
        	<param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    

    将上面两个jar包,以及jersey-client-1.18.1.jar、jersey-core-1.18.1.jar导入项目

    编写控制器

    @Controller("fileUploadController2")
    public class FileUploadController2 {
    public static final String FILESERVERURL =
    "http://localhost:9090/day06_spring_image/uploads/";
    /**
    * 文件上传,保存文件到不同服务器
    */
    @RequestMapping("/fileUpload2")
    public String testResponseJson(String picname,MultipartFile uploadFile) throws Exception{
            //定义文件名
            String fileName = "";
            //1.获取原始文件名
            String uploadFileName = uploadFile.getOriginalFilename();
            //2.截取文件扩展名
            String extendName uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,
            uploadFileName.length());
            //3.把文件加上随机数,防止文件重复
            String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
            //4.判断是否输入了文件名
            if(!StringUtils.isEmpty(picname)) {
            fileName = uuid+"_"+picname+"."+extendName;
            }else {
            fileName = uuid+"_"+uploadFileName;
            }
            System.out.println(fileName);
            //5.创建sun公司提供的jersey包中的Client对象
            Client client = Client.create();
            //6.指定上传文件的地址,该地址是web路径
            WebResource resource = client.resource(FILESERVERURL+fileName);
            //7.实现上传
            String result = resource.put(String.class,uploadFile.getBytes());
            System.out.println(result);
            return "success";
    	}
    }
    

    编写jsp

    <form action="fileUpload2" method="post" enctype="multipart/form-data">
    名称:<input type="text" name="picname"/><br/>
    图片:<input type="file" name="uploadFile"/><br/>
    <input type="submit" value="上传"/>
    </form>
    
    

    配置解析器

    <!-- 配置文件上传解析器-->
    <bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为5MB -->
    <property name="maxUploadSize">
    <value>5242880</value>
    </property>
    </bean>
    

    六.SpringMVC中的拦截器

    Spring MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
    用户可以自己定义一些拦截器来实现特定的功能。
    谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺
    序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
    说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但
    是也有区别,接下来我们就来说说他们的区别:
    过滤器是servlet规范中的一部分,任何java web工程都可以使用。
    拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
    过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。
    拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦
    截的。
    它也是AOP思想的具体应用。
    我们要想自定义拦截器,要求必须实现:HandlerInterceptor接口。

    七.SSM整合

    7.1环境准备

    创建数据库和表结构

    创建maven工程

    导入坐标建立依赖

    注意mybatis与spring对应关系

    mybatis-spring mybatis spring
    1.0.0 and1.0.1 3.0.1 to3.0.5 3.0.0 or higher
    1.0.2 3.0.6 3.0.0 or higher
    1.1.0 or higher 3.1.0 or higher 3.0.0 or higher
    1.3.0 or higher 3.4.0 or higher 3.0.0 or higher

    编写pojo

    便也业务层和持久层接口

    7.2整合步骤

    7.2.1保证Spring在web工程中独立运行

    编写spring配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	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-4.0.xsd
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    	<!-- 配置spring创建时要扫描的包 -->
    	<context:component-scan base-package="com.loserfromlazy">
            <!--指定骚包规则,不扫描@Controller注解的java类-->
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller">
            </context:exclude-filter>
        </context:component-scan>
    </beans>
    

    使用注解配置业务层和持久层

    @Service、@Repository

    7.2.2保证SpringMVC在web工程中独立运行

    在web.xml中配置核心控制类

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>boot-crm</display-name>
     
         <!--配置spring mvc的编码过滤器-->
      <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>
          <!--启动过滤器-->
          <init-param>
          	<param-name>forceEncoding</param-name>
             <param-value>true</param-value>
          </init-param>
      </filter>
         <!--过滤所有请求-->
      <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
        <!--配置spring mvc的核心控制器-->
      <servlet>
        <servlet-name>boot-crm</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <!--配置初始化参数,用于读取springmvc的配置文件-->
          <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
            <!--配置servlet的对象的创建时间点:应用加载时创建。取值只能是非0正整数,表示启动顺序-->
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>boot-crm</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    

    编写springmvc配置文件

    <?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:p="http://www.springframework.org/schema/p"
    	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-4.0.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    	<!-- 配置Controller扫描 -->
    	<context:component-scan base-package="com.yhr.crm.controller"/>
    	<!--另一种配置Controller的方式,使用时一种即可-->
    	<context:component-scan base-package="com.loserfromlazy">
            <!--指定扫包规则,只扫描@Controller注解的java类-->
            <context:ixclude-filter type="annotation" expression="org.springframework.stereotype.Controller">
            </context:ixclude-filter>
        </context:component-scan>
    	<!-- 配置注解驱动 -->
    	<mvc:annotation-driven />
    <mvc:default-servlet-handler />
    	<!-- 配置视图解析器 -->
    	<bean	class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<!-- 前缀 -->
    		<property name="prefix" value="/WEB-INF/jsp/"/>
    		<!-- 后缀 -->
    		<property name="suffix" value=".jsp"/>
    	</bean>
    </beans>
    

    编写Controller和jsp

    7.2.3整合spring和springmvc

    配置监听器实现启动服务创建容器

    在web.xml中加入

    <!--配置spring提供的监听器,用于启动服务时加载容器
    该监听器只能加载WEB-INF目录中名称为applicationContext.xml的配置文件-->
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    <!--手动指定配置文件的位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
      </context-param>
    

    7.2.4 保证Mybatis在web程序中独立运行

    编写dao接口的映射文件

    编写SqlMapConfig

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <!-- 加载属性文件 -->
        <properties resource="log4j.properties">
            <!--properties中还可以配置一些属性名和属性值  -->
            <!-- <property name="jdbc.driver" value=""/> -->
        </properties>
        <!-- 和spring整合后 environments配置将废除-->
        <environments default="development">
            <environment id="development">
            <!-- 使用jdbc事务管理,事务控制由mybatis-->
                <transactionManager type="JDBC" />
            <!-- 数据库连接池,由mybatis管理-->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                    <property name="url" value="jdbc:mysql://localhost:3306/pojo?useSSL=false&amp;serverTimezone=Hongkong&amp;characterEncoding=utf-8&amp;autoReconnect=true" />
                    <property name="username" value="root" />
                    <property name="password" value="manager" />
                </dataSource>
            </environment>
        </environments>
        <!-- 加载 映射文件 -->
        <mappers>
            <mapper resource="mybatis/user.xml"/>
        </mappers>
    </configuration>
    

    7.2.5 整合Mybatis和Spring

    清空SqlMapConfig.xml内容,把其中内容配置到spring中

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    </configuration>
    

    PS:由于我们使用的是代理开发dao的方式,所以Dao的具体实现类由Mybatis使用代理方式创建,所以mybatis的配置文件不能删除。

    当我们整合mybatis和spring时,mybatis创建的mapper.xml和dao接口文件名必须一致

    使用spring接管mybatis的session工程

    <!-- 配置 读取properties文件 jdbc.properties -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    
    	<!-- 配置 数据源 -->
    	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    		<property name="driverClassName" value="${jdbc.driver}"/>
    		<property name="url" value="${jdbc.url}"/>
    		<property name="username" value="${jdbc.username}"/>
    		<property name="password" value="${jdbc.password}"/>
    	</bean>
    
    	<!-- 配置SqlSessionFactory -->
    	<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    		<!-- 设置MyBatis核心配置文件 -->
    		<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
    		<!-- 设置数据源 -->
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    

    配置自动扫描所有mapper接口和文件

    <!-- 配置Mapper扫描 -->
    	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    		<!-- 设置Mapper扫描包 -->
    		<property name="basePackage" value="com.loserfromlazy.dao"/>
    	</bean>
    

    配置事务

    <!-- 事务管理器 -->
    	<bean id="transactionManager"	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<!-- 数据源 -->
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    
    	<!-- 通知 -->
    	<tx:advice id="txAdvice" transaction-manager="transactionManager">
    		<tx:attributes>
    			<!-- 传播行为 -->
    			<tx:method name="save*" propagation="REQUIRED"/>
    			<tx:method name="insert*" propagation="REQUIRED"/>
    			<tx:method name="add*" propagation="REQUIRED"/>
    			<tx:method name="create*" propagation="REQUIRED"/>
    			<tx:method name="delete*" propagation="REQUIRED"/>
    			<tx:method name="update*" propagation="REQUIRED"/>
    			<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
    			<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
    			<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
    			<tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
    		</tx:attributes>
    	</tx:advice>
    
    	<!-- 切面 -->
    	<aop:config>
    		<aop:advisor advice-ref="txAdvice"
    			pointcut="execution(* com.lofromlazy.service.*.*(..))"/>
    	</aop:config>
    

    applicationContext-dao.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	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-4.0.xsd
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    	<!-- 配置 读取properties文件 jdbc.properties -->
    	<context:property-placeholder location="classpath:jdbc.properties"/>
    
    	<!-- 配置 数据源 -->
    	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    		<property name="driverClassName" value="${jdbc.driver}"/>
    		<property name="url" value="${jdbc.url}"/>
    		<property name="username" value="${jdbc.username}"/>
    		<property name="password" value="${jdbc.password}"/>
    	</bean>
    
    	<!-- 配置SqlSessionFactory -->
    	<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    		<!-- 设置MyBatis核心配置文件 -->
    		<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
    		<!-- 设置数据源 -->
    		<property name="dataSource" ref="dataSource"/>
    		<!-- 别名包扫描 -->
    		<property name="typeAliasesPackage" value="com.yhr.crm.pojo"/>
    	</bean>
    
    	<!-- 配置Mapper扫描 -->
    	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    		<!-- 设置Mapper扫描包 -->
    		<property name="basePackage" value="com.yhr.crm.mapper"/>
    	</bean>
    </beans>
    
    作者:Loserfromlazy
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    基于Flask开发web微信
    爬取实例
    scrapy框架学习之路
    scripy
    wtforms
    由testcase数据之分析
    无用之flask学习
    无用之flask
    无用之学matplotlib,numpy,pandas
    jsp_1
  • 原文地址:https://www.cnblogs.com/yhr520/p/12550459.html
Copyright © 2011-2022 走看看