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风格的优点:
- 使路径变得更加整洁。
- 获得参数更加方便,框架会自动进行类型转换。
- 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方式。
重定向和转发
重定向为客户端行为,状态码为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");
乱码问题的解决方案:
- 原生的解决方式:在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的执行流程
-
用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。
-
DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:
a) 不存在
i. 再判断是否配置了mvc:default-servlet-handler
ii. 如果没配置,则控制台报映射查找不到,客户端展示404错误
iii. 如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误
b) 存在则执行下面的流程
-
根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
-
DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(找到对应的Controller)
-
如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】
-
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息(比如: @RequestBody,@RequestEntity, 对应的报文信息)
b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
-
Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
-
此时将开始执行拦截器的postHandle(...)方法【逆向】。
-
根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。(看return的字符串是否有前缀来使用对应的视图解析器)
-
渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
-
将渲染结果返回给客户端。