SpringMVC初步探索

    MVC

HelloMVC

配置web.xml

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

<web-app>
  <display-name>Archetype Created Web Application</display-name>

<!--  CharacterEncodingFilter用于处理字符编码的问题,所以要在使用的获取请求信息之前完成设置编码的操作,
      不然获取的数据还会有乱码的情况-->
<!--  所以要将CharacterEncodingFilter写在HiddenHttpMethodFilter之前-->

  <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>forceResponseEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

<!--  用于设置真实请求的过滤器-->
<!--  在此过程中会通过方法获取对应的请求信息-->
<!--  例子在form表单中只能设置"get"和"put"两种请求方式,而我们需要使用"delete"或"post",
      这时就可以设置name="_method"的隐藏域,通过该隐藏域传入最终的请求方式-->

<!--  在 HiddenHttpMethodFilter 类的 HiddenHttpMethodFilter 方法中-->
<!--  HttpServletRequest requestToUse = request;-->

<!--  在请求中设置的请求方式为POST,并在请求设置_method属性,-->
<!--  该属性最终会被包装到一个新的HttpServletRequest对象中,放到doFilter中,实现放行-->

<!--  private String methodParam = DEFAULT_METHOD_PARAM;public static final String DEFAULT_METHOD_PARAM = "_method";-->

<!--  if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {-->
<!--        String paramValue = request.getParameter(this.methodParam);-->
<!--        if (StringUtils.hasLength(paramValue)) {-->
<!--        String method = paramValue.toUpperCase(Locale.ENGLISH);-->
<!--           if (ALLOWED_METHODS.contains(method)) {-->
<!--                requestToUse = new HttpMethodRequestWrapper(request, method);-->
<!--                }-->
<!--         }-->
<!--    }-->

<!--  filterChain.doFilter(requestToUse, response);-->


  <filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:bean-springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
<!--  除了.jsp,其他都可以通过-->
  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

配置springmvc-servlet.xml

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

    <!--    注解扫描-->
    <context:component-scan base-package="com.huang"/>
    <!--    配置thymeleaf-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>


<!--    下面两个注解都需要写,如果只写default-servlet-handler,
        那么所有的请求都会找default-servlet-handler,就会出现映射找不到的情况,最终会报404-->
<!--    添加了 mvc:annotation-driven,就可以保证请求进来时先进DispatcherServlet,
        如果找不到了才会进default-servlet-handler,一般是处理静态资源-->
    <mvc:default-servlet-handler/>
<!--    识别springMVC对应的注解驱动-->
    <mvc:annotation-driven/>
</beans>

对应的HelloController

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 HelloController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();

        //封装对象,放在ModelAndView中。Model
        mv.addObject("msg","HelloSpringMVC!");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }

}

其对应的执行流程为下:

使用注解实现此步骤

配置web.xml : 和helloMVC一样。

配置springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" 
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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.huang.controller"/>
<!--让spring-mvc不处理静态资源,使css, js,不走静态资源   -->
    <mvc:default-servlet-handler/>
<!--支持mvc注解驱动-->
<!--    在spring中一般采用@RequestMapping注解来完成映射关系-->
<!--    要想使@RequsetMapping注解生效-->
<!--    就必须向上下文中注册DefaultAnnotationHandlerMapping-->
<!--    和一个AnnotationMethodHandlerAdapter实例-->
<!--    而<mvc:annotation-driven/>会自动帮我们注入这两个实例-->
    <mvc:annotation-driven/>
<!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

对应的HelloController

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

@Controller
//自动配置bean
//@RequestMapping("/hello")在类上面的@RequestMapping表示在访问的url里都要先走类的路径再走方法的路径
public class helloController{

    @RequestMapping("/hello")
    //对应的请求
    public String hello(Model model){
        //分装数据
        model.addAttribute("smg", "helloSpringMVC");
        //会被视图解析器处理
        return "hello";
    }
}

注解方法和普通方法的区别:

普通方法:没一个controller只能写一个方法。

注解方法:一个controller可以写多个方法。

@RequestMappering的用法:本质就是一个url,其可以使用在类上,也可以使用在方法上,但使用在类上时,我们就必须在访问方法的url时,加上在类上的url,否则会访问失败。

    RestFul风格

使用PathVarible注解,让方法参数的值对应绑定到一个URL模板变量上。

对应例子为下:

@Controller
public class RestFulController {

    @RequestMapping("/RestFul/{a}/{b}")
    public String add(@PathVariable String a, @PathVariable String b, Model model){
        String result = a + b;
        model.addAttribute("smg", "结果为" + result);
        return "hello";
    }
}

@RequestMapping可以手动设置请求方式。

分别为:

  • RequestMethod.DELETE
  • RequestMethod.GET
  • RequestMethod.PUT
  • RequestMethod.POST
  • RequestMethod.PATCH

@Request Mapping对应的格式:

//    @RequestMapping(name = URL, method = 对应的请求方式)

注解设置请求方式:

  • GetMapping
  • PostMapping
  • PutMapping
  • DeleteMapping
  • PatchMapping

    RestFul风格的优点:

  1. 使路径变得更加整洁。
  2. 获得参数更加方便,框架会自动进行类型转换。
  3. 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方式。

    重定向和转发

重定向为客户端行为,状态码为307,转发为服务端行为,状态码为302。

WEB-INF目录是受保护的,且对客户端是隐藏的。

由于重定向是客户端行为,使用其无法访问WEB-INF中的jsp文件,而转发为服务端行为,可以访问其对应的WEB-INF文件。

(重点)重定向是不走视图解析器的。

通过springMVC实现重定向和转发:
 

@Controller
public class ModelTest1 {
    @RequestMapping("对应的URL")
    public String test01(){
      //转发
      return "/xxx.jsp";
    }
    public String test02(){
        //转发
        return "forward:/xxx.jsp";
    }
    public String test03(){
        //重定向
        return "redirect:/xxx.jsp";
    }
}

要将视图解析器注释掉,因为此时controller类中的方法返回的String 为一个完整的url,如果视图解析器没注释的话,这个url就会进入视图解析器中,拼接出一个错误的url。

    接收请求参数和前端会显

当请求中的参数的参数是对象,其会匹配对应的创建类中的字段名,如果名字一样则匹配,如果不一样则不匹配。使用在传递参数时,要保证传递参数的字段名和创建类的字段名相同,如果前端传递参数的字段名不一样,则后端获得的对象对应的字段名的值为null。

    Model和ModelMap和ModelandView的区别

model:只适用于存储数据。

ModeMap:继承LinkedMap,除了实现了自身的一些方法,同样的继承了LinkedMap的方法和特性。

Modelandview : 可以储存数据的同时,可以设置返回的逻辑视图进行控制展示层的跳转。

    乱码问题的解决方案

乱码问题是在前后端交互的时候产生的,所以我们要采用过滤器的方式才能在本质上解决问题。

在springMVC中由一个已经写好的过滤器CharacterEncodingFilter,我们可以直接使用。

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

    Json(数据交换的格式)

例子为下:

 let user = {
        name:"黄飞武",
        age:3,
        sex:"男"
    }
    console.log(user);
    // 将字符串转换为json
    let json = JSON.stringify(user);
    console.log(json);
    //将json转换为string
    console.log(JSON.parse(json));

  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>

  jackson

其对应的依赖为:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

@ResponseBody的作用:在对应的方法上加此注解时,此方法就不会走视图解析器。(其是配合@Controller使用的)

jackson的使用方法:

@Controller
public class jsonController {
    @RequestMapping("/j1")
    @ResponseBody
    public String json1(){
        User user = new User(1, "hfw", "男");
        ObjectMapper objectMapper = new ObjectMapper();
        String result = null;
        try {
            result = objectMapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return result;
    }

通过ObjectMapper的实例对象的writeValueAsString("对象")方法,将实例转换为字符串。(但我们会发现存在乱码问题)

ObjectMapper, 时间解析后的默认格式为:timestamp(时间戳)

SimpleDateFormat : 可以时间转换为对应的格式。

//自定义日期格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");

乱码问题的解决方案: 

  1. 原生的解决方式:在RequestMapping中存在produces,produces可以用来设置编码格式。 
 //@RequestMapping(value = "/j1", produces = "application/json;charset=utf-8")

     2.springMVC的解决方式:

在springMVC-servlet.xml中设置

<!--    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>

    @RestController

为了每次使方法返回String,而不走到视图解析器,我们每次都要加@ResponseBody,比较麻烦。

所以我们将Controller注释换为RsetController注释,保证方法不走视图解析器,返回对应的类型。

@RestController等价于@Controller + @ResponseBody。

@RestController默认返回给前端的数据类型为JSON。

    使用ObjectMapper实现自定义格式

 自定义时间格式:

@RequestMapping("/j2")
    public String json2(){
        ObjectMapper objectMapper = new ObjectMapper();
//HH为二十四小时,hh为十二小时
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        objectMapper.setDateFormat(simpleDateFormat);
        try {
            return objectMapper.writeValueAsString(new Date());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    创建objectMapperUtil工具类

目的:提高代码复用性。

public class objectMapperUtil {
    public static String getJson(Object object, String dateformat){
        ObjectMapper objectMapper = new ObjectMapper();
        //不使用时间戳的方式
//        objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateformat);
        objectMapper.setDateFormat(simpleDateFormat);
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

    Festjson

对应的依赖为下:

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>

JsonObject : 代表json对象。

JsonArray : 代表json数组。

例子为下:

 @RequestMapping("/j3")
    public String json3(){
        User user = new User(1, "hfw1", "男");
        User user1 = new User(2, "hfw2", "男");
        User user2 = new User(3, "hfw3", "男");
        User user3 = new User(4, "hfw4", "男");
        List<User> list = new ArrayList<>();
        list.add(user);
        list.add(user1);
        list.add(user2);
        list.add(user3);
//将list转换为json字符串
        return JSON.toJSONString(list);
    }

JSON.toJSONString("对象") : 将java对象转换为json字符串。

JSON.parseObject("json字符串") : 将json字符串转换为java对象。

JSON.toJSON("对象") : 将java对象转换为json对象。

JSON.toJavaObject("JSON对象") : json对象转换为java对象。

    SSM整合

需求的依赖为下:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
<!--    数据库连接池 : c3p0连接池-->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
    </dependency>
<!--    servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
<!--    jsp-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.6</version>
    </dependency>
    <!--      mybatis整合Spring使用-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.16</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.9</version>
    </dependency>
<!--    Spring-jdbc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.10</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.9</version>
    </dependency>
  </dependencies>

database.properties的配置

jdbc.driver=XXXX
jdbc.url=XXXXXX
#不能写username,否则会报错
jdbc.user=XXXX
jdbc.password=XXXXX

mybatis-config.xml的配置

<?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.huang.pojo"/>
    </typeAliases>
    <mappers>
<!--对应的Mapper的包-->
<!--注册Mapper-->
        <mapper class="com.huang.mapper.bookMapper"/>
    </mappers>
</configuration>

  spring-dao.xml的

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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">

    <!--指定对应的参数文件-->
    <context:property-placeholder location="classpath:对应的数据源.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"/>
        <property name="jdbcUrl" value="${url}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
<!--        c3p0连接池的私有属性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
<!--        关闭连接后不自动commit-->
        <property name="autoCommitOnClose" value="false"/>
<!--        获取连接超时时间-->
        <property name="checkoutTimeout" value="10000"/>
<!--        当获取连接失败重试次数-->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>
<!--设置SqlSessionFactory-->
    <bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--设置数据源-->
        <property name="dataSource" ref="dataSource"/>
<!--        绑定mybatis的配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--        配置dao接口扫描包,动态实现了Dao接口可以注入到spring容器中-->
    </bean>
<!--    配置dao接口扫描包,动态的实现了dao接口可以注入到spring中-->
<!--通过扫描实现自动配置-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--        注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="SqlSessionFactory"/>
<!--        要扫描的dao包-->
        <property name="basePackage" value="com.huang.Mapper"/>
    </bean>
</beans>

在原来配置spring-dao.xml时,我们通常会写一个SqlSessionTemplate bean,再通过实体类来实现Dao层操作,而在这次我们采用 配置dao接口扫描包,动态的实现了dao接口可以注入到spring中,实现自动配置。(此代码是死的,可以直接套用)

配置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"
         metadata-complete="true">
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <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>
</web-app>

配置servlet和过滤器。

其中对应的spring-mvc.xml的配置文件为下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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">
    <!--注解驱动-->
    <mvc:annotation-driven/>
    <!--静态资源过滤器-->
    <mvc:default-servlet-handler/>
    <!--视图解析器-->
    <context:component-scan base-package="com.huang.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

配置spring-service.xml

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

    <!--    扫描service下面的包-->
    <context:component-scan base-package="com.huang.service"/>
    <!--    将我们所有业务类注入到spring容器中,可以通过配置和注解实现-->
    <bean id="BookServiceImpl" class="com.huang.service.bookServiceImpl">
        <!--        这里用要将dao的名字改成mapper,否则会找不到-->
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
    <!--    配置事务-->
    <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

最终将三个xml文件整合到applicationContext.xml中

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

    <import resource="spring-dao.xml"/>
    <import resource="spring-service.xml"/>
    <import resource="spring-mvc.xml"/>
</beans>

在配置Spring的时候,Spring就自动帮我们配置了事务。

最终编写Controller层,进行对应的数据查找,完成整合。(例子为下)

@Controller
@RequestMapping("/book")
public class bookController {
    @Autowired
    @Qualifier("BookServiceImpl")
    private bookService 对应的service层的实现类;
    @RequestMapping("/allBook")
    public String selectBookList(Model model){
        List<Books> books = bookService.selectBooksList();
        model.addAttribute("allbook", books);
        return "allBook";
    }
}

    Ajax

作用:实现异步处理对应的请求。

一般我们都会采用JQuery的来写Ajax。

JQuery对应的cdn为下:

<!--jquery对应的官网的cdn-->
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<!--百度CDN-->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

Ajax函数格式:

$.post({
          url:"对应的请求或对应的地址",
          data:{数据以键值对的形式存储},
          //在回调函数中函数的形参有:data(数据), status(状态)
          success:function (data){
            //成功是回调的函数
          }
          error:function(){
            //失败时回调的函数
          }
          datatype:设置后台返回数据的类型
        })

     拦截器

拦截器的作用域:拦截器只会拦截访问Controller中的方法,并不会拦截静态资源。

使用方法:编写一个类,通过继承Handlerceptor,来编写拦截器。

例子为下:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

//将拦截器配置到IOC容器中
@Component
public class firstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //proHandle方法就是在调用Controller的requestMappering对应的路径的方法 前 执行的拦截方法
        //这return ture 就是放行, return false就是拦截
        System.out.println("first proHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //postHanle方法就是在执行完Controller中对应的方法后,执行的拦截
        System.out.println("first postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //afterCompletion就是在dispatchServlet中将ModelAndView渲染到页面后的拦截器
        System.out.println("first afterCompletion");
    }
}

在bean.xml的配置

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

    <!--    注解扫描-->
    <context:component-scan base-package="com.huang"/>
    <!--    配置thymeleaf-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
<!--    <mvc:view-controller path="/" view-name="index"/>-->

    <!--    下面两个注解都需要写,如果只写default-servlet-handler,
            那么所有的请求都会找default-servlet-handler,就会出现映射找不到的情况,最终会报404-->
    <!--    添加了 mvc:annotation-driven,就可以保证请求进来时先进DispatcherServlet,
            如果找不到了才会进default-servlet-handler,一般是处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--    识别springMVC对应的注解驱动-->
    <mvc:annotation-driven/>

    <mvc:interceptors>
<!--        如果直接在Interceptors中设置拦截器的话就是默认拦截Controller中对应的请求-->
<!--        <ref bean="firstInterceptor"/>-->
        <mvc:interceptor>
<!--            这里的path中的设置"/*"就是对应一层的目录-->
<!--            如果要匹配使用的路径就应该设置path为"/**"-->
            <mvc:mapping path="/**"/>
<!--            设置exclude-mapping就是对应排除拦截的路径-->
            <mvc:exclude-mapping path="/hhhhh"/>
            <ref bean="firstInterceptor"/>
        </mvc:interceptor>

    </mvc:interceptors>

    <mvc:interceptors>
        <ref bean="firstInterceptor"/>
        <ref bean="secondInterceptor"/>
    </mvc:interceptors>
</beans>

存在多个拦截器时的执行顺序 

  •     若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行。

  •     若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterComplation()会执行 

手撕源码

1.三个拦截器执行的位置

 Prohandle会按照在ioc容器中配置的顺序执行拦截器。(这里使用遍历 ,interceptorInde记录遍历到最后一个返回true的拦截器)

 PostHandle因为反向遍历所以输出的顺序与配时的顺序相反。

 如果 Prohand返回的是false,那么PostHandle不会执行。

即使 Prohand返回的是false,afterCompletion也会执行。

因为 interceptorInde为最后一个返回true的索引,且以倒叙的遍历方式执行,最后也就是会实现倒叙打印从interceptorInde到零。

    文件上传

通过模拟对服务器进行上传文件的操作。

 例子

编写一个fileUp.html页面用于点击上传文件
 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a th:href="@{/fileLoad}">点击下载美女照片</a>
<!--因为上传到是文件,所以就不能使用在地址中添加&的操作,需要将文件以二进制的方式上传-->
<!--所以设置enctype="multipart/form-data",multipart表示上传的是文件-->
<form th:action="@{/fileUp}" method="post" enctype="multipart/form-data">
    <input type="file" name="photo"/><br>
    <input type="submit" value="上传"/>
</form>
</body>
</html>

引入文件上传的依赖

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

 在spring中的bean.xml中配置multipartResolver的bean

<?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-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!--    注解扫描-->
    <context:component-scan base-package="com.huang"/>
    <!--    配置thymeleaf-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<!--    可以保证出来的文件被springMVC处理封装为MultipartFile-->
<!--    MultipartFile便于进一步的操作-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

    <mvc:view-controller path="/" view-name="index"/>
    <mvc:view-controller path="/file" view-name="fileLoad"/>

    <!--    下面两个注解都需要写,如果只写default-servlet-handler,
            那么所有的请求都会找default-servlet-handler,就会出现映射找不到的情况,最终会报404-->
    <!--    添加了 mvc:annotation-driven,就可以保证请求进来时先进DispatcherServlet,
            如果找不到了才会进default-servlet-handler,一般是处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--    识别springMVC对应的注解驱动-->
    <mvc:annotation-driven/>
</beans>

编写Controller层代码

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

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
public class fileController {

    @RequestMapping("/fileUp")
    public String fileUp(MultipartFile photo, HttpSession session) throws IOException {
        System.out.println(photo.getOriginalFilename());
        //获取传入文件的名字,如果这里上传的名字相同就是出现覆盖的情况,所以要保证不同
        String originalFilename = photo.getOriginalFilename();
        //获取文件的后缀字符串,方便后续拼接
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        //为了保证名字不重复,这里使用UUID生成随机字符串
        String uuid = String.valueOf(UUID.randomUUID());
        String fileName = uuid + suffix;
        //获取当前工程的Context
        ServletContext servletContext = session.getServletContext();
        //获取要上传到的文件夹位置
        //这里的就是设置需要上传带到服务器中的位置,也就是在服务器中完整的路径
        String realPath = servletContext.getRealPath("/photo");
        //因为可能是第一次上传,为了保证文件夹的存在,所以还需要进行判断文件夹是否存在
        //将当前文件夹地址放到一个新的file中,进行对应的判断操作
        File file = new File(realPath);
        if(!file.exists()) {
            //不存在是创建文件夹
            file.mkdir();
        }
        //此时文件夹必定存在,我们就可以往文件夹存放文件
        //File.separator就是表示文件夹和文件直接的分隔符 , "\\"
        String finalPath = realPath + File.separator + fileName;
        //将上传来的文件迁移到对应文件路径中
        photo.transferTo(new File(finalPath));
        return "success";
    }
}

 进行测试,测试结果为下

 这里只要改个 realPath,其他可以直接CV,基本是不变的。

    文件的下载 

通过模拟在服务器中下载对应的图片。

 例子

编写一个fileLoad.html页面用于点击下载文件

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a th:href="@{/fileLoad}">点击下载美女照片</a>
</body>
</html>

在spring的bean.xml文件中配置mvc注解驱动和default-servlet-handler

<?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-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!--    注解扫描-->
    <context:component-scan base-package="com.huang"/>
    <!--    配置thymeleaf-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <mvc:view-controller path="/" view-name="index"/>
    <mvc:view-controller path="/file" view-name="fileLoad"/>

    <!--    下面两个注解都需要写,如果只写default-servlet-handler,
            那么所有的请求都会找default-servlet-handler,就会出现映射找不到的情况,最终会报404-->
    <!--    添加了 mvc:annotation-driven,就可以保证请求进来时先进DispatcherServlet,
            如果找不到了才会进default-servlet-handler,一般是处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--    识别springMVC对应的注解驱动-->
    <mvc:annotation-driven/>
</beans>

 编写控制层

@Controller
public class fileController {

    @RequestMapping("/fileLoad")
    public ResponseEntity<byte[]> fileLoad(HttpSession session) throws IOException {
        //通过session获取整个工程的Context
        ServletContext servletContext = session.getServletContext();
        //通过工程的Context获取1.jpg在服务器上的正确地址
        String realPath = servletContext.getRealPath("/static/1.jpg");
        //图片的获取本质就是文件的复制,所以使用流进行获取
        //创建输入流
        FileInputStream fileInputStream = new FileInputStream(realPath);
        //创建一个byte数组读取输入流中的数据
        //fileInputStream.available()可以获取当前输入流的数据的长度
        byte[] bytes = new byte[fileInputStream.available()];
        fileInputStream.read(bytes);
        fileInputStream.close();
        //创建可以响应头用于创建响应报文
        MultiValueMap<String, String> head = new HttpHeaders();
        //在响应头中设置下载文件的方式和名字
        // "Content-Disposition", "attachment;filename=1.jpg" :使用附件的方式下载,
        //这里的key和value的值是固定的,我们只需要修改图片的名字即可(1.jpg)
        head.add("Content-Disposition", "attachment;filename=1.jpg");
        //设置状态码
        HttpStatus ok = HttpStatus.OK;
        //因为要返回一个响应报文,所以直接创建一个响应报文
        return new ResponseEntity<>(bytes, head, ok);
    }
}

创建static文件夹并在其中放置对应的图片

运行测试

完成测试,以后需要用直接复制即可。 

异常处理器

方法1:bean.xml配置方式

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

    <!--    注解扫描-->
    <context:component-scan base-package="com.huang"/>
    <!--    配置thymeleaf-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">

                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>

                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <mvc:default-servlet-handler/>
    <!--    识别springMVC对应的注解驱动-->
    <mvc:annotation-driven/>

<!--    配置异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--        设置异常映射 就是键值对的方式,一个异常对应一个指定的页面-->
        <property name="exceptionMappings">
            <props>
<!--                计算异常-->
<!--                与Controller中的视图解析器的解析步骤一样,这里就是通过thymeleaf解析-->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
<!--        exceptionAttribute为异常信息,vlue就是设置异常信息在请求域中的key-->
        <property name="exceptionAttribute" value="ex"></property>
    </bean>
</beans>

 方法2:通过注解配置,设置一个Controller层。

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ExceptionController {


    @ExceptionHandler(value = {ArithmeticException.class})
//    value为数组可以设置多个对应的异常信息
    public String exceptionTest(Exception exception,Model model) {
//        exception就是对应的错误信息
        model.addAttribute("ex", exception);
        return "error";
    }
}

springMVC全注解开发

1.导入相应的依赖。

2.使用webInit替代web.xml。

import com.huang.config.springConfig;
import com.huang.config.springMVCConfig;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;


public class webInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    /**
     * getRootConfigClasses就是获取Spring的配置类
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{springConfig.class};
    }

    /**
     *getServletConfigClasses就是获取springMVC的配置类
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{springMVCConfig.class};
    }

    /**
     * 就是web.xml配置dispatchServlet的路径
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    /**
     * 设置字符编码处理器
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceRequestEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{encodingFilter, hiddenHttpMethodFilter};
    }
}

3.创建spring的配置类和springMVC的配置类来代替bean.xml。

spring配置类

import org.springframework.context.annotation.Configuration;

@Configuration
public class springConfig {
}

springMVC的配置类

import com.huang.interceptor.firstInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import java.util.List;
import java.util.Properties;

@Configuration
//开启spring的注解扫描
@ComponentScan("com.huang")
//开启springMVC的注解驱动
@EnableWebMvc
//实现WebMvcConfigurer就是将该配置类作为springMVC配置类
public class springMVCConfig implements WebMvcConfigurer {

    //配置thymeleaf注解解析器
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }

    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
    //配置开启默认的servlet处理器
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        //允许默认的servlet处理器进行处理
        configurer.enable();
    }

    //    配置文件上传解析器
    @Bean
    public CommonsMultipartResolver commonsMultipartResolver() {
        return new CommonsMultipartResolver();
    }
    //配置拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        firstInterceptor interceptor = new firstInterceptor();
        registry.addInterceptor(interceptor)
                .addPathPatterns("/**");
    }

    //配置异常处理器
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        //设置异常处理器的属性
        properties.setProperty("java.lang.ArithmeticException", "error");
        simpleMappingExceptionResolver.setExceptionMappings(properties);
        simpleMappingExceptionResolver.setExceptionAttribute("ex");
        //加入异常处理解析器的list中
        resolvers.add(simpleMappingExceptionResolver);
    }
}

4.创建对应的页面,即可运行项目。

SpringMVC的执行流程

  1. 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。

  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:

a) 不存在

i. 再判断是否配置了mvc:default-servlet-handler

ii. 如果没配置,则控制台报映射查找不到,客户端展示404错误

iii. 如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误

b) 存在则执行下面的流程

  1. 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。

  2. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(找到对应的Controller)

  3. 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】

  4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息(比如: @RequestBody,@RequestEntity, 对应的报文信息)

b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

  1. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。

  2. 此时将开始执行拦截器的postHandle(...)方法【逆向】。

  3. 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。(看return的字符串是否有前缀来使用对应的视图解析器)

  4. 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。

  5. 将渲染结果返回给客户端。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值