Spring进阶(一)
Spring进阶(一)
Spring整合Mybatis
- 将MyBatis的DataSource交给Spring IoC容器创建并管理,使用第三方数据库连接池(Druid,C3P0等)代替MyBatis内置的数据库连接池
- 将MyBatis的SqlSessionFactory交给Spring IoC容器创建并管理,使用spring-mybatis整合jar包中提供的SqlSessionFactoryBean类代替项目中的MyBatisUtil工具类
- 将MyBatis的接口代理方式生成的实现类,交给Spring IoC容器创建并管理
Mybatis核心对象分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 //1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionfactoryBuilder()
//2.加载SqlMapconfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");,
//3.创建sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory
=sqlSessionFactoryBuilder.build(inputstream);
//4.获取sqlSession
SqlSession sqlSession=sqlsessionFactory.openSession();
//5.执行SqlSession对象执行查询,获取结果user
AccountDao accountDao =sqlSession.getMapper(AccountDao.class)
Account ac =accountDao.findById(2);
System.out.println(ac);
//释放资源
sqlsession.close();配置文件内容
1
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
><configuration>
<!--起别名-->
<typeAliases>
<package name="com.hngy.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false&useServerPrepStmts=true"/>
<property name="username" value="username"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--扫描mapper-->
<package name="com.hngy.mapper"/>
</mappers>
</configuration>
利用Spring开始整合
- 导入相应的maven坐标
1
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 <dependencies>
<!-- Junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MyBatis核心Jar包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- MySql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- Lombok工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<!-- Spring核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
<!-- Spring-test测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.3</version>
<scope>test</scope>
</dependency>
<!-- slf4j日志包 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- druid阿里的数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Spring整合ORM 自动导入spring-orm,spring-jdbc,spring-tx-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.3</version>
</dependency>
<!-- Spring整合MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
- 设置配置文件
设置Spring配置,通过注解的方式
1
2
3
4
5
6
7
8
9
//要扫的包
//@PropertySource:加载类路径jdbc.properties文件
//将jdbc和mybatis的配置加入到要扫的包下
public class SpringConfig {
}配置jdbc.properties,创建jdbcConfig
1
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 import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
public class JdbcConfig {
private String driver;
private String url;
private String userName;
private String password;
//数据库池连接对象
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}配置MybatisConfig
1
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 import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
//定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
//设置MyBatis的别名解析路径,MyBatis会在这个包下查找类,并为这些类创建别名
ssfb.setTypeAliasesPackage("com.itheima.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
//定义bean,返回MapperScannerConfigurer对象
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
//设置要扫的包
msc.setBasePackage("com.itheima.dao");
return msc;
}
}
- 使用
```java
import com.itheima.config.SpringConfig;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App2 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountService accountService = ctx.getBean(AccountService.class);
Account ac = accountService.findById(1);
System.out.println(ac);
}
}
SpringMvc
一种基于Java实现MVC模型的轻量级Web框架
web程序工作流程、
三层架构
web程序通过浏览器访问前端页面,发送异步请求到后端服务器
后台服务器采用三层架构进行功能开发
- 表现层负责接收请求和数据然后将数据转交给业务层
- 业务层负责调用数据层完成数据库表的增删改查,并将结果返给表现层
- 表现层将数据转换成json格式返回给前端
前端页面将数据进行解析最终展示给用户。
表现层与数据层的技术选型:
- 数据层采用Mybatis框架
- 变现层采用SpringMVC框架,SpringMVC主要负责的内容有:
- controller如何接收请求和数据
- 如何将请求和数据转发给业务层
- 如何将响应数据转换成json发回到前端
SpringMVC程序流程
1.浏览器发送请求到Tomcat服务器
2.Tomcat服务器接收到请求后,会将请求交给SpringMVC中的==DispatcherServlet[前端控制器]==来处理请求
3.DispatcherServlet不真正处理请求,只是按照对应的规则将请求分发到对应的Bean对象
4.Bean对象是有我们自己编写来处理不同的请求,每个Bean中可以处理一个或多个不同的请求url
5.DispatcherServlet和Bean对象都需要交给Spring容器来进行管理
拦截器
- 拦截器和过滤器的区别
归属不同:Filter属于servlet技术,Interceptor属于SpringMVc技术
拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVc的访问进行增强
- 拦截器执行顺序
preHandle
return true
controller
postHandle
afterCompletion
return false
结束
拦截器链的运行顺序
preHandle:与配置顺序相同,必定运行
postHandle:与配置顺序相反,可能不运行
aftercompletion:与配置顺序相反,可能不运行入门案例
1
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 package com.itheima.controller.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {
//原始方法调用前执行的内容
//返回值类型可以拦截控制的执行,true放行,false终止
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String contentType = request.getHeader("Content-Type");
HandlerMethod hm = (HandlerMethod)handler;
System.out.println("preHandle..."+contentType);
return true;
}
//原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
//原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
- 配置类中配置
1
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 package com.itheima.config;
import com.itheima.controller.interceptor.ProjectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
public class SpringMvcSupport extends WebMvcConfigurationSupport {
private ProjectInterceptor projectInterceptor;
/*静态资源过滤*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
具体实现
- 导入坐标
1
2
3
4
5
6
7
8
9
10
11
12
13
14 <!--1. 导入SpringMVC与servlet的坐标-->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
创建控制器类, @Controller位于SpringMVC控制器类定义上方 设定SpringMVC的核心控制器bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 //2.制作控制器类,等同于Servlet
//2.1必须是一个spring管理的bean
//2.2定义具体处理请求的方法
//2.3设置当前方法的访问路径
//2.4设置响应结果为json数据
public class UserController {
public String save(){
System.out.println("user save ...");
return "{'module':'springmvc'}";
}
}创建配置类
1
2
3
4
5 //3.定义配置类加载Controller对应的bean
public class SpringMvcConfig {
}创建Tomcat的Servlet容器配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 //4.定义servlet容器的配置类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载springMVC配置
protected WebApplicationContext createServletApplicationContext() {
//初始化WebApplicationContext对象
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
//加载指定配置类
ctx.register(SpringMvcConfig.class);
return ctx;
}
//设置Tomcat接收的请求哪些归SpringMVC处理
protected String[] getServletMappings() {
return new String[]{"/"};
}
//设置spring相关配置
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}第二种加载方式,重要
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 public class ServletcontainersInitconfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
相关注解
1
2
3
4
5
6
7
8 设置当前控制器方法请求访问路径 位于SpringMVC控制器类或方法定义上方
设置当前控制器方法响应内容为当前返回值,无需解析 位于SpringMVC控制器类或方法定义上方
定SpringMVC的核心控制器bean 位于SpringMVC控制器类定义上方
设置spring配置类扫描路径,用于加载使用注解格式定义的bean 位于类定义上方
开启json数据类型自动转换
当形参和表单提交过来的元素名称不对应时
设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行 专用于异常处理器的上方
开启事务
- 相关方法的作用
- AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
- AbstractDispatcherServletInitializer提供三个接口方法供用户实现
- createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
- createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围
- ngetServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理
- createServletApplicationContext用来加载SpringMVC环境
- createRootApplicationContext用来加载Spring环境
避免Spring错误的加载到bean
SpringMVC相关的bean(表现层bean)
Spring控制的bean
- 业务bean(service)
- 功能bean(DataSoure)
SpringMVC加载的bean对应的包都在com.xxx.controller包内
方法
将spring加载bean的范围为com.xxx,排除掉controller包内的bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//@ComponentScan({"com.itheima.service","com.itheima.dao"})
配置类配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.itheima.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
public class SpringMvcSupport extends WebMvcConfigurationSupport {
//设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//当访问/pages/????时候,从/pages目录下查找内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}封装集合对象
1
2
3
4
5
6
7
8
9 //集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
public String listParam(List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'module':'list param'}";
}
//SpringMVC将List看做是一个POJO对象来处理,将其创建一个对象并准备把前端的数据封装到对象中,但是List是一个接口无法创建对象,所以会报错
//:使用`@RequestParam`注解
- JSON数据,用POJO类的话属性名对应上就行
1
2
3
4
5
6
7 //使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
public String listParamForJson({ List<String> likes)
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}参数带@RequestBody的区别
带注解的方法通常用于处理JSON格式的数据,不带注解的方法可以处理任何类型的请求参数,只要它们能够与
pojo
对象的属性名匹配带注解的方法从请求体中接收JSON数据并将其转为POJO对象,不带注解的从请求参数中获取数据,并将其绑定到POJO对象
字符串的返回