SpringMVC
# SpringMVC
# @RequeatMapping把请求的路径和对应处理的controller方法关联起来
url路径:ip+接口+上下文路径applicationContext+类上注解路径信息+方法前注解路径信息
使用对应请求方法派生的注解方式。使用@PathVariable注解把请求路径的占位符对应到形参中
@RequestMapping("/user")
public UserController{
@RequestMapping(value={"/index","/"},method = RequestMethod.GET)
public String index(){}
@PostMapping("/add")
public String add(){}
----restful风格-----
@GetMapping("/delete/{username}/{id}")
public String del(@PathVariable("id") Integer id,@PathVariable("username") String uasername){}
}
2
3
4
5
6
7
8
9
10
11
web-xml配置中央控制器servlet,并初始化spring资源
<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:springmvc.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>
2
3
4
5
6
7
8
9
10
11
12
13
# 获取请求参数
Controller方法形参参数名和请求参数名对应(不对应使用@RequestParam匹配)
形参直接用实体类形参来获取请求参数,前提是实体类属性名要和请求参数名对应(设置get,set方法)。
@RequestMapping("/user")
public String add(String username,String password){}
public String add(User user){}
2
3
编码问题,直接在web-xml中使用spring封装的编码过滤器
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 往域中共享数据及转发视图
使用model往请求域共享数据
会话域和应用域使用原生HttpSession的API方法以及session.getServletContext()
public String testModel(Model model) {
model.addAttribute("name", "admin");
return "index";
}
2
3
4
转发视图"forward:/test","redirect:/test"。浏览器(html)会自动解析/的路径不包含上下文路径,而服务器解析(后端controller)包含上下文路径applicationContext
# RESTful
所有资源统一由对应的地址标识,对资源不同方式的操作(增删改查)通过不同的请求方式来表述(get,post,delete,put),然后请求参数不再用?分隔url和请求参数,而是把参数拼接在url作为资源路径一部分user/1/admin,然后通过注解获取。
但是浏览器仅支持get和post请求,因此需要使用过滤器hiddenHttpMethodFilter来转换请求方式。转换时请求方式为post,然后表单包含一个请求参数_method,值为真实的请求方式(put,delete)
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
------
GettingMapping/DeleteMapping
2
3
静态资源请求时要添加<mvc:default-servlet-handler/>,让默认的servlet处理
# json
springMVC使用@RequestBody把前端传到后端服务器的json格式请求参数转化成java对象
(maven导入jackson依赖=>spring.xml配置文件设置<mvc:annotation-driven />,启动springmvc控制器的注解功能 =>给形参中接收的变量注解)
@ResponseBody注解controller方法,方法返回值为要转化为json格式的java对象,SpringMVC会自动把该java对象转为json格式相应给请求的页面。
@RestController注解相当于类标识@Controller,然后类里面所有方法注解@ResponseBody
# 文件上传下载
使用ResponseEntity<byte[]作>为控制器的返回值
File.separator可以在不同文件系统下'/'或者'\'分割文件不同目录
@RequestMapping()
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
IOException {
//获取ServletContext对象,也就是项目在服务器的上下文路径
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
InputStream is = new FileInputStream(realPath);
byte[] bytes = new byte[is.available()];
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,
statusCode);
is.close();
return responseEntity;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
上传功能:spring配置multipartfile实例bean(通过id实例化bean)=>表单设置enctype属性=>controller方法形参添加MultipartFile photoname形参接收表单穿过来的文件数据。
----Spring bean配置-----
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
-----前端form表单------
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
-----服务器接收文件保存在服务器-----
@PostMapping("/upload")
public String testUpload(MultipartFile photo, HttpSession session) throws IOException {
String filename = photo.getOriginalFilename();
ServletContext servletContext = session.getServletContext();
String photoPath=servletContext.getRealPath("photo");
File file = new File(photoPath);
if (!file.exists()) {
file.mkdir();
}
String filetype = filename.substring(filename.lastIndexOf("."));
filename = UUID.randomUUID().toString() + filetype;
String fileSavePath = photoPath + File.separator + filename;
photo.transferTo(new File(fileSavePath));
return "index";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 拦截器
用于拦截控制器方法的执行,需要实现HandlerInterceptor接口的三个方法(控制器方法之前,控制器方法之后,视图渲染之后),preHandle返回true则放行当前控制器方法。拦截器的作用对象是所有的控制器的方法,若想针对某个路径的请求通过<mvc:interceptors>
<mvc:interceptors>
<bean class="interceptor.FirstInterceptor"/>
</mvc:interceptors>
2
3
多个拦截器执行:一般情况执行顺序和在springMVC中配置的顺序有关,preHandle是顺序执行,而postHandle和afterCompletion是反序执行(for循环是从interceptors.size()—>0)。
若有拦截器返回false,则该拦截器之后的preHandle以及afterCompletion(包括当前拦截器)不会执行;所有拦截器的postHandle都不会执行。
# SpringMVC执行过程
DispatcherServlet初始化:创建WebApplicationContext容器(反射创建ioc容器对象—>把Spring容器设置为父容器)—>刷新容器(初始化策略包括初始化文件上传处理器,handlemapping)—>将ioc容器在应用域共享
DispatcherServlet处理请求过程:HttpServlet类中根据请求的method来调用对应的doGet/doPost方法;而在它的子类FrameworkServlet中,重写了所有do方法,全部都是processRequest来处理;最终在DispatcherServlet方法中真正处理请求的由doDispatch进行。
doDispatch:通过mappedHandle映射(url,method信息)找到对应的处理器方法,它本质是一个处理器执行链,里面还包括拦截器方法;然后由HandleAdapter执行处理器控制器方法(把请求参数填充控制器方法的形参)—>postHandle—>Handle处理完后,控制器方法返回类型选择合适的视图解析器,处理视图(render)—>afterCompletion
# SSM整合
在web服务器启动,读取Spring配置文件,创建Spring的IOC容器。使用监听器完成
控制层的bean通过SpringMVC配置文件进行管理,业务层服务层的bean通过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">
<!-- 字符过滤编码-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 改变请求方式编码-->
<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>
<!-- 设置springMVC文件位置和名称-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.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>
<!-- 配置spring监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 设置spring配置文件自定义的位置和名称-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
</web-app>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
spring.xml(把mybatis核心配置文件整合到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:tx="http://www.springframework.org/schema/tx"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描除控制层所有包-->
<context:component-scan base-package="service"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 实际上这个类实现了factoryBean接口,因此getObject返回sqlSessionFactory,能够在ioc拿到这个对象-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="pojo"></property>
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true"></property>
</bean>
</property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor"></bean>
</array>
</property>
</bean>
<!-- 配置mapper接口扫描,能将包下所有接口通过sqlSession创建代理实现类对象,并交给IOC容器管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper"></property>
</bean>
</beans>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
springMVC.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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
<context:component-scan base-package="controller"></context:component-scan>
<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>
<!-- 默认servlet处理静态资源-->
<mvc:default-servlet-handler/>
<!-- 开启mvc注解驱动-->
<mvc:annotation-driven/>
<!-- 视图控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!-- 文件上传解析器-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" name="multipartResolver"></bean>
</beans>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43