SpringMVC

Spring MVC

SSM:MyBatis+Spring+SpringMVC

JAVASE:认真学习,老师带,入门快

Javaweb:认真学习,老师带,入门快

框架:研究官方文档,锻炼自学能力,锻炼比较能力,锻炼项目能力

SpringMVC+Vue+SpringBoot+SpringCloud+Linux

Spring:IOC和AOP

SpringMVC:SpringMVC的执行流程

1、DispatcherServlet

DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。

DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。

img

DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:

1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;

2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);

3、通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);

4、通过ViewResolver解析逻辑视图名到具体视图实现;

5、本地化解析;

6、渲染具体的视图等;

7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。

8、DispatcherServlet初始化的上下文加载的Bean是只对SpringMVC有效的Bean,如Controller、HandlerMapping、HandlerAdapter 等等,该初始化上下文只加载Web相关组件。

9、 DispatcherServlet初始化主要做了如下两件事情:

  1. 初始化SpringMVC使用的Web上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文);

  2. 初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。

  3. 配置web.xml,引入DispatcherServlet,注意设置级别,绑定配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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_4_0.xsd"
             version="4.0">
    <!--    1,注册DispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--    关联一个spring的配置文件:【servlet-name】-servlet.xml-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
    <!--        启动级别-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  4. 配置springmvc-servlet.xml ,由springmvc代理,记得导入类处理器映射器BeanNameUrlHandlerMapping,处理器适配器SimpleControllerHandlerAdapter

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           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">
    
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
    <!--    添加视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
    <!--        前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--        后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    <!--    Handle-->
        <bean id="/hello" class="com.controller.HelloController"></bean>
    </beans>
    
  5. 编写com.controller.HelloController,继承Controller类

    public class HelloController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //ModelAndView 模型和视图
            ModelAndView modelAndView = new ModelAndView();
    
            //封装对象
            modelAndView.addObject("msg","HelloSpringMVC!");
    
            modelAndView.setViewName("hello");
            return modelAndView;
        }
    }
    
  6. /WEB-INF/jsp/下编写hello.jsp文件即可,可以引入$

2、使用注解来实现

  1. 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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_4_0.xsd"
             version="4.0">
        <!--    1,注册DispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--    关联一个spring的配置文件:【servlet-name】-servlet.xml-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext.xml</param-value>
            </init-param>
            <!--        启动级别-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  2. springmvc-config的配置

    <?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
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    <!--        自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
        <context:component-scan base-package="com.controller"/>
    <!--    让spring mvc 不处理静态资源 .css .js .html mp3.mp4-->
        <mvc:default-servlet-handler/>
    <!--    处理器映射器,处理器适配器,一句话解决-->
        <mvc:annotation-driven/>
        <!--    添加视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--        前缀-->
            <property name="prefix" value="/jsp/"/>
            <!--        后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    
  3. 控制器的实现

    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloController {
    
        //真实访问地址 : 项目名/HelloController/hello
        @RequestMapping("/hello")
        public String sayHello(Model model){
            //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
            model.addAttribute("msg","hello,SpringMVC");
            //web-inf/jsp/hello.jsp
            return "hello";
        }
    }
    

3、Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法
  • 在Spring MVC中,对于Controller的配置方式有很多种

方式一:实现Controller接口

  • 缺点:每次只能实现一个方法

springmvcXML配置

<?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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--    让spring mvc 不处理静态资源 .css .js .html mp3.mp4-->
    <mvc:default-servlet-handler/>
    <!--    处理器映射器,处理器适配器,一句话解决-->
    <mvc:annotation-driven/>
    <!--    添加视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--        前缀-->
        <property name="prefix" value="/jsp/"/>
        <!--        后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
<!--    在没有使用注解的情况下配置controller的bean-->
    <bean name="/test01" class="com.controller.ControllerTest01"/>
</beans>

实现接口:

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//只要实现了Controller接口的类,说明这就是一个接收器
public class ControllerTest01 implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","ControllerTest01");
        modelAndView.setViewName("test");
        return modelAndView;
    }
}

方式二:使用注解来实现

  1. 让springmvc的配置文件可以扫描到注解

    <!--        自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
    <context:component-scan base-package="com.controller"/>
    
  2. 完整的配置

    <?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
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--        自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
        <context:component-scan base-package="com.controller"/>
        <!--    让spring mvc 不处理静态资源 .css .js .html mp3.mp4-->
        <mvc:default-servlet-handler/>
        <!--    处理器映射器,处理器适配器,一句话解决-->
        <mvc:annotation-driven/>
        <!--    添加视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--        前缀-->
            <property name="prefix" value="/jsp/"/>
            <!--        后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    
  3. Contlorler类

    @Controller//被spring接管
    //被这个注解的类,中所有的方法,如果返回值是String,并且有具体页面可以跳转,那么就会被视图解析器解析
    public class ControllerTest02 {
        @RequestMapping("/test02")
        public String test01(Model model){
            model.addAttribute("msg","ControllerTest02");
            return "test";
        }
    }
    

4、RestFul风格

概念:

  1. RestFul就是一个资源定位符资源操作的风格。不是标准也不是协议,只是一个风格。基于这个风格设计的软件可以更加简洁,更有层次,更易于实习缓存等机制

  2. RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTFUL特点包括:

1、每一个URI代表1种资源;

2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;

3、通过操作资源的表现形式来操作资源;

4、资源的表现形式是XML或者HTML;

5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。

http://localhost:8080/add/1/2

@Controller
public class RestFulController {
    //原来的方式:http://localhost:8080/add?a=1&b=3
    @RequestMapping("/add")
    public String test1(int a, int b, Model model){
        int res = a + b;
        model.addAttribute("msg","结果为"+res);
        return "test";
    }
    //RestFul:http://localhost:8080/add/a/b
    @RequestMapping("/add/{a}/{b}")
    public String test2(@PathVariable int a, @PathVariable int b, Model model){
        int res = a + b;
        model.addAttribute("msg","结果为"+res);
        return "test";
    }
}

限定方法请求(比如get)

@RequesMapping(value="/add/{a}/{b}".method=RequestMethod.GET)

通过专用注解来实现@GetMapping

@GetMapping("/add/{a}/{b})

5、数据传递

另外还有

//重定向
return "redirect:/index.jsp";
//return "redirect:hello.do"; //hello.do为另一个请求/

5.1、从前端接收

@Controller
@RequestMapping("/user")
public class UserController {
    @GetMapping("/t1")
    public String test1(@RequestParam("username")  String name, Model model){
        //1.接受前端参数;http://localhost:8080/user/t1?username=zhangsan
        System.out.println("接收到前端到参数为:"+name);
        //2.将返回的结果传递给前端
        model.addAttribute("msg",name);
        //3.跳转视图
        return "test";
    }
    /*

   1. 接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
   2,假设传递的是一个对象User。匹配User对象中的字段名;如果名字一致则OK,否则不匹配
    */
    //前端接收的是一个对象:id name age,http://localhost:8080/user/t2?id=1&name=df&age=1
    @GetMapping("/t2")
    public String test2(User user){
        System.out.println(user);
        return "test";
    }
}

5.2、数据显示到前端

第一种 : 通过ModelAndView

public class ControllerTest1 implements Controller {

   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
       //返回一个模型视图对象
       ModelAndView mv = new ModelAndView();
       mv.addObject("msg","ControllerTest1");
       mv.setViewName("test");
       return mv;
  }
}

第二种 : 通过ModelMap

继承了LinkedHashMap,所以他拥有了LinkedHashMap的全部功能

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
   //封装要显示到视图中的数据
   //相当于req.setAttribute("name",name);
   model.addAttribute("name",name);
   System.out.println(name);
   return "hello";
}

第三种 : 通过Model

@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
   //封装要显示到视图中的数据
   //相当于req.setAttribute("name",name);
   model.addAttribute("msg",name);
   System.out.println(name);
   return "test";
}

5.3、SpringMVC的过滤器配置

<filter>
   <filter-name>encoding</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>encoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

6、JackSon

6.1、 JSON

json是什么

早期,所有的数据传输习惯使用xml文件

  • JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在JavaScript一切皆为对象,任何js支持的类型都可以用JSON来表示

格式:

  • 对象都用{}
  • 数组都有[]
  • 所有的键值对都是用key:value

JSON字符串和JS对象的转换

 'use strict'
 var user = {
     name:"xiaoming",
     age:3,
     sex:"男"
 }
 //对象转换为json字符串
 var jsonUser =JSON.stringify(user)
 console.log(jsonUser)
 //json字符串转换为对象
 var objectUser = JSON.parse(jsonUser)
// var objectUser = JSON.parse('{"name":"xiaoming","age":3,"sex":"男"}')
 console.log(objectUser)

很多人搞不清楚,JSON和JS对象的区别

var obj={a:'hello',b:'hellob'};
var json={"a":"hello","b":"hellob"};

6.2、Jackson

maven导入

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.10.8</version>
</dependency>

controller

@Controller
//@RestController:全局不走视图解析器
public class UserController {
    @RequestMapping(value = "j1",produces = {"text/html;charset=UTF-8;","application/json;charset=UTF-8;"})
    @ResponseBody//它就不会走视图解析器了,会直接返回一个字符串
    public String json1() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //创建一个对象
        User user1 = new User("张三1",3,"男");
        User user2 = new User("张三2",3,"男");
        User user3 = new User("张三3",3,"男");
        User user4 = new User("张三4",3,"男");
        User user5 = new User("张三5",3,"男");
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat.format(date);
        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);
        userList.add(user5);
        String s = objectMapper.writeValueAsString(userList);
        s=s+simpleDateFormat.format(date);;
        return s;
    }

执行结果

[{"name":"张三1","age":3,"sex":"男"},{"name":"张三2","age":3,"sex":"男"},{"name":"张三3","age":3,"sex":"男"},{"name":"张三4","age":3,"sex":"男"},{"name":"张三5","age":3,"sex":"男"}]2022-07-20 18:05:52

编写工具类:

public class JsonUtil {
    public  static String getJson(Object object) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(object);
    }
}
@RequestMapping(value = "j2",produces = {"text/html;charset=UTF-8;","application/json;charset=UTF-8;"})
@ResponseBody//它就不会走视图解析器了,会直接返回一个字符串
public String json2() throws JsonProcessingException {
    //创建一个对象
    User user1 = new User("张三1",3,"男");
    User user2 = new User("张三2",3,"男");
    User user3 = new User("张三3",3,"男");
    User user4 = new User("张三4",3,"男");
    User user5 = new User("张三5",3,"男");

    List<User> userList = new ArrayList<User>();

    userList.add(user1);
    userList.add(user2);
    userList.add(user3);
    userList.add(user4);
    userList.add(user5);

    String json = JsonUtil.getJson(userList);
    return json;
}

6.3、FastJson

Maven导包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

1 JSONObject类使用

JSONObject实现了Map接口,而json对象中的数据都是以"键:值"对形式出现, JSONObject底层操作是由Map实现的。类中主要是get()方法。JSONObject相当于json对象,该类中主要封装了各种get方法,通过"键:值"对中的键来获取其对应的值。

2 JSONArray类使用

JSONArray的内部是通过List接口中的方法来完成操作的。JSONArray代表json对象数组,json数组对象中存储的是一个个json对象,所以类中的方法主要用于直接操作json对象。比如其中的add(),remove(),containsAll()方法,对应于json对象的添加,删除与判断。 其内部主要由List接口中的对应方法来实现。

跟JSONObject一样,JSONArray里面也有一些get()方法,不过不常用,最有用的应该是getJSONObject(int index)方法,该方法用于获取json对象数组中指定位置的JSONObject对象,配合size()方法,可用于遍历json对象数组中的各个对象。 通过以上两个方法,在配合for循环,即可实现json对象数组的遍历。此外JSONArray中也实现了迭代器方法来遍历。 通过遍历得到JSONObject对象,然后再利用JSONObject类中的get()方法,即可实现最终json数据的获取。

3 JSON类使用

JSON类主要是实现转化用的,最后的数据获取,还是要通过JSONObject和JSONArray来实现。类中的主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。

总结一下fastjson中三个类的用途和方法:

  • JSONObject:解析Json对象,获取对象中的值,通常是使用类中的get()方法
  • JSONArray:JSON对象数组,通常是通过迭代器取得其中的JSONObject,再利用JSONObeject的get()方法进行取值。
  • JSON:主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。 转换之后取值还是按各自的方法进行。
@RequestMapping(value = "j3",produces = {"text/html;charset=UTF-8;","application/json;charset=UTF-8;"})
@ResponseBody//它就不会走视图解析器了,会直接返回一个字符串
public String json3(){
    User user1 = new User("张三1",3,"男");
    User user2 = new User("张三2",3,"男");
    User user3 = new User("张三3",3,"男");
    User user4 = new User("张三4",3,"男");
    User user5 = new User("张三5",3,"男");

    List<User> userList = new ArrayList<User>();

    userList.add(user1);
    userList.add(user2);
    userList.add(user3);
    userList.add(user4);
    userList.add(user5);
    String str =  JSON.toJSONString(userList);
    return str;
}

7、SSM整合

7.1、初始化

  1. 创建数据库

    CREATE DATABASE ssmbuild;
    USE ssmbuild;
    CREATE TABLE `books`(
                            `bookID` INT NOT NULL AUTO_INCREMENT COMMENT '书id',
                            `bookName` VARCHAR(100) NOT NULL COMMENT '书名',
                            `bookCounts` INT NOT NULL COMMENT '数量',
                            `detail` VARCHAR(200) NOT NULL COMMENT '描述',
                            KEY `bookID`(`bookID`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    
    INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
                                                                      (1,'Java',1,'从入门到放弃'),
                                                                      (2,'MySQL',10,'从删库到跑路'),
                                                                      (3,'Linux',5,'从进门到进牢')
    
  2. mavan导入相关包和配置滤过静态资源

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
    
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!--        spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.21</version>
        </dependency>
        <!--        mybatis-spring-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.21</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.10.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    
  3. 创建实体类:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Books {
        private  int bookID;
        private  String bookName;
        private int bookCounts;
        private String detail;
    }
    
  4. 编写dao接口

    public interface BookMapper {
        //增加一本书
        int insertBook(Books books);
        //删除一本书
        int deleteBookById(@Param("bookId")int id);
        //更新一本书
        int updateBook(Books books);
        //查询一本书
        Books queryBookById(@Param("bookId") int id);
        //查询全部的书
        List<Books> queryAllBook();
    }
    

7.2、整合MyBatis

  1. 编写精简到mybatis配置文件:

    <?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>
        <typeAliases>
            <package name="com.pojo"></package>
        </typeAliases>
        <mappers>
            <package name="com.dao"/>
        </mappers>
    </configuration>
    
  2. 编写dao接口的mapper

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.dao.BookMapper">
        <insert id="insertBook" parameterType="Books">
            insert into ssmbuild.books(bookName, bookCounts, detail)
            values (#{bookName},#{bookCounts},#{detail});
        </insert>
        <delete id="deleteBookById" parameterType="_int">
            delete from ssmbuild.books
            where bookID=#{bookID};
        </delete>
        <update id="updateBook" parameterType="Books">
            update ssmbuild.books
            set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
            where bookID=#{bookID};
        </update>
        <select id="queryBookById" resultType="Books">
            select *
            from ssmbuild.books
            where bookID=#{bookID};
        </select>
        <select id="queryAllBook" resultType="Books">
            select *
            from ssmbuild.books;
        </select>
        <select id="queryBookByName" resultType="Books">
            select *
            from ssmbuild.books
            where bookName = #{bookName};
        </select>
    </mapper>
    
  3. db.properties

    jdbc.driver = com.mysql.cj.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
    jdbc.username = root
    jdbc.password = admin
    
  4. service接口

    public interface BookService {
        //增加一本书
        int insertBook(Books books);
        //删除一本书
        int deleteBookById(int id);
        //更新一本书
        int updateBook(Books books);
        //查询一本书
        Books queryBookById(int id);
        //查询全部的书
        List<Books> queryAllBook();
    }
    
  5. 调用dao层的bookmapper实现service接口

    public class BookServiceImpl implements BookService{
        //业务层调用dao层,组合Dao层
        private BookMapper bookMapper;
    
        public void setBookMapper(BookMapper bookMapper) {
            this.bookMapper = bookMapper;
        }
    
        @Override
        public int insertBook(Books books) {
            return bookMapper.insertBook(books);
        }
    
        @Override
        public int deleteBookById(int id) {
            return bookMapper.deleteBookById(id);
        }
    
        @Override
        public int updateBook(Books books) {
            return bookMapper.updateBook(books);
        }
    
        @Override
        public Books queryBookById(int id) {
            return bookMapper.queryBookById(id);
        }
    
        @Override
        public List<Books> queryAllBook() {
            return bookMapper.queryAllBook();
        }
    }
    

7.3、整合Spring

  1. dao的spring配置文件

    1. 关联数据库配置文件
    2. 连接池配置
    3. SqlSessionFactory
    4. 配置dao接口扫描包,动态的实现了dao接口可以注入到spring容器中
    <?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:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!--    1. 关联数据库配置文件-->
        <context:property-placeholder location="classpath:db.properties"/>
    <!--    2. 连接池-->
    <!--    c3po:自动化操作(自动化加载配置文件,并且可以自动设置到对象中)-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="user" value="${jdbc.name}"/>
            <property name="password" value="${jdbc.passwd}"/>
    
            <property name="maxPoolSize" value="30"/>
            <property name="minPoolSize" value="10"/>
    
            <property name="autoCommitOnClose" value="false"/>
    
            <property name="checkoutTimeout" value="10000"/>
    <!--        获取连接失败重试次数-->
            <property name="acquireRetryAttempts" value="2"/>
        </bean>
    <!--    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
    <!--        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>-->
    <!--        <property name="url" value="jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true &amp;characterEncoding=utf8&amp;useSSL=true&amp;serverTimezone=UTC"/>-->
    <!--        <property name="username" value="root"/>-->
    <!--        <property name="password" value="root1@12"/>-->
    <!--    </bean>-->
    <!--    3. SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
    <!--        绑定mybatis的配置文件-->
            <property name="configLocation" value="classpath:mybatis.xml"/>
        </bean>
    <!--    配置dao接口扫描包,动态的实现了dao接口可以注入到spring容器中-->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--        注入sqlSessionFactory-->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!--        要扫描的dao包-->
            <property name="basePackage" value="com.dao"/>
        </bean>
    </beans>
    
  2. service的spring配置

    1. 扫描service下的包
    2. 将我们所有的业务类,注入到spring中,可以通过配置,或者注解实现
    3. 声明式事务配置
    4. AOP支持(可以先不写)
    <?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:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    
    <!--  1. 扫描service下的包-->
        <context:component-scan base-package="com.service"/>
    <!--  2. 将我们所有的业务类,注入到spring中,可以通过配置,或者注解实现-->
        <bean id="BookServiceImpl" class="com.service.BookServiceImpl">
            <property name="bookMapper" ref="bookMapper"/>
        </bean>
    <!--  3. 声明式事务配置-->
        <bean id="DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--        注入事务愿-->
            <property name="dataSource" ref="dataSource"/>
        </bean>
    <!--   4. aop事务支持-->
    </beans>
    

7.4、整合SpringMVC

  1. 注解驱动
  2. 静态资源过滤
  3. 扫描包controller
  4. 视图解析器
<?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/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!--1.注解驱动-->
    <mvc:annotation-driven/>
<!--2.静态资源过滤-->
    <mvc:annotation-driven/>
<!--3.扫描包controller-->
    <context:component-scan base-package="com.controller"/>
<!--4.视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--        前缀-->
        <property name="prefix" value="/jsp/"/>
        <!--        后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

7.5、controller

package com.controller;

import com.alibaba.fastjson.JSON;
import com.dao.BookMapper;
import com.pojo.Books;
import com.service.BookService;
import com.service.BookServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/book")
public class BookController {
    //controller 调service层
    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;

    //查询全部的书籍,并且返回一个书籍展示页面
    @RequestMapping("/allBook")
    public String list(Model model){
        List<Books> books =  bookService.queryAllBook();
        model.addAttribute("list", books);
        return "allBook";
    }
    //跳转到增加书籍界面
    @RequestMapping("/toAddBook")
    public String toAddPaper(){
        return "addBook";
    }
    //添加书籍的请求
    @RequestMapping("/addBook")
    public String addBook(Books books){
        System.out.println("addBook=>"+books);
        bookService.insertBook(books);
        return "redirect:/book/allBook";//重定向到首页
    }
    //跳转到修改页面
    //跳转到增加书籍界面
    @RequestMapping("/toUpdate")
    public String toUpdate(int id,Model model)
    {
        System.out.println(id);
        Books books = bookService.queryBookById(id);
        model.addAttribute("books",books);
        return "updateBook";
    }
    //修改书籍
    @RequestMapping("/UpdateBook")
    public  String upDateBook(Books books){
        System.out.println("updateBook=>"+books);
        bookService.updateBook(books);
        return "redirect:/book/allBook";//重定向到首页
    }
    //删除书籍
    @RequestMapping("/deleteBook/{id}")
    public String deleteBook(@PathVariable("id") int id){
        System.out.println(id);
        bookService.deleteBookById(id);
        return "redirect:/book/allBook";
    }
    //查询书籍
    @RequestMapping("/queryBookName")
    public String queryBook(String queryBookName,Model model){
        Books books = bookService.queryBookByName(queryBookName);
        List<Books> list = new ArrayList<>();
        list.add(books);
        model.addAttribute("list",list);
        return "/allBook";
    }
}

其他资料在gitee上

8、Ajax

​ Ajax即Asynchronous Javascript And XML(异步JavaScript和XML)在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合的‘新’方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。 [3] 使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作

1.判断当前输入是否为:”test“,失去焦点判断

<%--
  Created by IntelliJ IDEA.
  User: stone
  Date: 2022/7/22
  Time: 17:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        function x() {
           
            $.post({
                url:"${pageContext.request.contextPath}/a1",
                data:{"name":$("#username").val()},
                success:function (data) {
                    alert(data);
                }
            })
        }
    </script>
</head>
<body>
<%--    失去焦点的时候,发起一个请求到后台--%>
用户名:<input type="text" id="username" onblur="x()">
</body>
</html>

后台

@RestController
public class AjaxController {
    @RequestMapping("/a1")
    public void a1(String name, HttpServletResponse response) throws IOException {
        System.out.println("a1:param=>"+name);
        if ("test".equals(name)){
            response.getWriter().print("ture");
        }else {
            response.getWriter().print("false");
        }
    }
}

2.Ajax异步加载数据

controller

@RequestMapping("/a2")
public List<User> a2(){
    ArrayList<User> users = new ArrayList<>();
    //添加数据
    users.add(new User("张三",19,"男"));
    users.add(new User("李四",19,"男"));
    users.add(new User("王五",20,"男"));
    return users ;
}

Jsp

<%--
  Created by IntelliJ IDEA.
  User: stone
  Date: 2022/7/23
  Time: 15:22
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                /*
                * 这是一个间歇的方式,post(url,param「可以省略」,回调success)
                * */
                $.post("${pageContext.request.contextPath}/a2",function (data) {
                    console.log(data);
                    let html="<>";
                    for (let i = 0;i<data.length;i++){
                        html+="<tr>"+
                            "<td>"+data[i].name+"</td>"+
                            "<td>"+data[i].age+"</td>"+
                            "<td>"+data[i].sex+"</td>"+
                            "</tr>"
                    }
                    $("#content").html(html)
                })
            })
        })
    </script>
</head>
<body>
<input type="button" value="加载数据" id="btn">
    <table>
        <tr>
            <td>姓名</td>
            <td>年龄</td>
            <td>性别</td>
        </tr>
        <tbody id="content">
<%--        数据在后台--%>
        </tbody>
    </table>
</body>
</html>

3.Ajax查找用户名

<%--
  Created by IntelliJ IDEA.
  User: stone
  Date: 2022/7/23
  Time: 15:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script>
        function a1() {
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"name":$("#name").val()},
                success:function (data){
                    console.log(data)
                    $("#userInfo").html(data)
                }
            })
        }
    </script>
</head>
<body>
    <p>
        用户名:<input type="text" id="name" onblur="a1()">
        <span id="userInfo"></span>
    </p>
    <p>
        密码:<input type="password" id="pwd" >
        <span id="pwdInfo"></span>
    </p>
</body>
</html>
@RequestMapping("/a3")
public String a3(String name ,String pwd){
    String msg = null;
    if(name!=null){
        if("admin".equals(name)){
            msg ="ok";
        }else{
            msg="用户查询失败";
        }
    }
    return msg;
}

json乱码处理

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <constructor-arg value="utf-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
    <property name="failOnEmptyBeans" value="false"/>
</bean>
    </property>
</bean>
    </mvc:message-converters>
</mvc:annotation-driven>

9、拦截器

在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中,即平时所说的“权限检测”及“日志记录”。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。

Spring MVC 提供了 Interceptor 拦截器机制,用于请求的预处理和后处理。

在开发一个网站时可能有这样的需求:某些页面只希望几个特定的用户浏览。对于这样的访问权限控制,应该如何实现呢?拦截器就可以实现上述需求。在 Struts2 框架中,拦截器是其重要的组成部分,Spring MVC 框架也提供了拦截器功能。

Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

9.1、拦截器实现

1.实现HandlerInterceptor类

public class MyInterceptor implements HandlerInterceptor {
    @Override
    //return ture 会执行下一个拦截器,放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("==========处理前=========");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("==========处理后=========");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("==========清理=========");
    }
}

2.applicationContext.xml注册

<!--    Springmvc过滤器-->
    <mvc:interceptors>
        <mvc:interceptor>
<!--            包括这个请求下面得到所有请求-->
            <mvc:mapping path="/**"/>
            <bean class="com.configuration.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

9.2、拦截未登录

起始页:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/user/goLogin">登录</a>
  <a href="${pageContext.request.contextPath}/user/main">首页</a>
  </body>
</html>

登录页:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录页面</h1>
  <form action="${pageContext.request.contextPath}/user/login" method="post">
    用户名:<input type="text" name="username">
      密码:<input type="password" name="password">
      <input type="submit" value="提交">
  </form>
</body>
</html>

首页:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
${username}
<a href="${pageContext.request.contextPath}/user/goOut">注销</a>
</body>
</html>

controller:

package com.controller;

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

import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/user")
public class LoginController {
    @RequestMapping("/login")
    public String login(HttpSession session, String username, String password, Model model){
        //把用户的信息放入session中
        session.setAttribute("userLoginInfo",username);
        String name = (String) session.getAttribute("userLoginInfo");
        model.addAttribute("username",name);
        return "main";
    }
    @RequestMapping("main")
    public String main(){
        return "main";
    }
    @RequestMapping("goLogin")
    public String jlogin(){
        return "login";
    }
    @RequestMapping("/goOut")
    public String goOut(HttpSession session){
        session.removeAttribute("userLoginInfo");
        return "main";
    }
}

拦截器:path="/user/**"

package com.configuration;

import org.springframework.web.servlet.HandlerInterceptor;

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

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //登录页面也会放行
        if(request.getRequestURI().contains("login")){
            return true;
        }
        //放行的判断:判断什么时候下登录
        //第一次登录也是没有session的
        HttpSession session = request.getSession();
        if(session.getAttribute("userLoginInfo")!=null){
            return true;
        }

        //判断什么情况下登录
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }
}

10、文件上传与下载

10.1、文件上传

Spring MVC 框架的文件上传基于 commons-fileupload 组件,并在该组件上做了进一步的封装,简化了文件上传的代码实现,取消了不同上传组件上的编程差异。

MultipartResolver接口

在 Spring MVC 中实现文件上传十分容易,它为文件上传提供了直接支持,即 MultpartiResolver 接口。MultipartResolver 用于处理上传请求,将上传请求包装成可以直接获取文件的数据,从而方便操作。

MultpartiResolver 接口有以下两个实现类:

  • StandardServletMultipartResolver:使用了 Servlet 3.0 标准的上传方式。
  • CommonsMultipartResolver:使用了 Apache 的 commons-fileupload 来完成具体的上传操作。

MultpartiResolver 接口具有以下方法。

名称 作用
byte[] getBytes() 以字节数组的形式返回文件的内容
String getContentType() 返回文件的内容类型
InputStream getInputStream() 返回一个InputStream,从中读取文件的内容
String getName() 返回请求参数的名称
String getOriginalFillename() 返回客户端提交的原始文件名称
long getSize() 返回文件的大小,单位为字节
boolean isEmpty() 判断被上传文件是否为空
void transferTo(File destination) 将上传文件保存到目标目录下

下面我们使用 CommonsMultipartResolver 来完成文件上传,分为单文件上传和多文件上传两部分介绍。

单文件上传

1. 导入 jar 文件

文件上传使用 Apache Commons FileUpload 组件,需要导入 commons-io-2.4.jar 和 commons-fileupload-1.2.2.jar 两个 jar 文件(可在 Apache 官网下载)。

Maven 项目在 pom.xml 文件中添加以下依赖。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.2</version>
</dependency>

2. 配置 MultipartResolver

使用 CommonsMultipartReslover 配置 MultipartResolver 解析器,在 springmvc-servlet.xml 中添加代码如下。

<!-- 配置MultipartResolver,用于上传文件,使用spring的CommonsMultipartResolver -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="5000000" />
    <property name="defaultEncoding" value="UTF-8" />
</bean>
  • defaultEncoding:请求的编码格式,默认为 ISO-8859-1,此处设置为 UTF-8(注:defaultEncoding 必须和 JSP 中的 pageEncoding 一致,以便正确读取表单的内容)。
  • maxUploadSize:上传文件大小上限,单位为字节。

3. 编写文件上传表单页面

负责文件上传表单的编码类型必须是“multipart/form-data”类型。

fleUpload.jsp 代码如下。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传</title>
</head>
<body>
    <form action="${pageContext.request.contextPath }/fileupload"
        method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="myfile"><br> 
        文件描述:<input type="text" name="description"><br> 
        <input type="submit" value="提交">
    </form>
</body>
</html>

基于表单的文件上传需要使用 enctype 属性,并将它的值设置为 multipart/form-data,同时将表单的提交方式设置为 post。

表单的 enctype 属性指定的是表单数据的编码方式,该属性有以下 3 个值。

  • application/x-www-form-urlencoded:这是默认的编码方式,它只处理表单域里的 value 属性值。
  • multipart/form-data:该编码方式以二进制流的方式来处理表单数据,并将文件域指定文件的内容封装到请求参数里。
  • text/plain:该编码方式只有当表单的 action 属性为“mailto:”URL 的形式时才使用,主要适用于直接通过表单发送邮件的方式。

由上面 3 个属性的解释可知,在基于表单上传文件时 enctype 的属性值应为 multipart/form-data。

4. 创建POJO类

在该 POJO 类中声明一个 MultipartFile 类型的属性封装被上传的文件信息,属性名与文件选择页面 filleUpload.jsp 中的 file 类型的表单参数名 myfile 相同,代码如下。

public class FileDomain {
    private String description;
    private MultipartFile myfile;
    /** 省略setter和getter参数*/
}

5. 编写控制器

创建 FileUploadController 控制类,具体代码如下。

@Controller
public class FileUploadController {
    // 得到一个用来记录日志的对象,这样在打印信息时能够标记打印的是哪个类的信息
    private static final Log logger = LogFactory.getLog(FileUploadController.class);
    @RequestMapping("getFileUpload")
    public String getFileUpload() {
        return "fileUpload";
    }
    /**
     * 单文件上传
     */
    @RequestMapping("/fileupload")
    public String oneFileUpload(@ModelAttribute FileDomain fileDomain, HttpServletRequest request) {
        
        String realpath = request.getServletContext().getRealPath("uploadfiles");
        String fileName = fileDomain.getMyfile().getOriginalFilename();
        File targetFile = new File(realpath, fileName);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        // 上传
        try {
            fileDomain.getMyfile().transferTo(targetFile);
            logger.info("成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "showFile";
    }
}

6. 创建成功显示页面

showFile.jsp 代码如下。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传</title>
</head>
<body>
    文件描述:${fileDomain.description }
    <br>
    <!-- fileDomain.getMyFile().getOriginalFilename()-->
    文件名称:${fileDomain.myfile.originalFilename }
</body>
</html>

7. 测试文件上传

访问地址:http://localhost:8080/springmvcDemo2/getFileUpload,运行结果如下。

fileUpload.jsp页面
fileUpload.jsp 页面

showFile.jsp页面
showFile.jsp 页面

posted @   项sir  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2021-07-24 中国的金融体系与多层次资本市场-中国的多层次资本市场
XIANGSIR
点击右上角即可分享
微信分享提示