注解开发

注解开发定义bean

在实现类里面写@Component(“bookDao”)

在配置文件里写<context:component-scan base-package="com.ocean.dao.impl">

1
2
3
4
5
6
7
public class App{
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao)ctx.getBean("bookDao");
System.out.println(bookDao);
}
}

Spring提供@Component注解的三个衍生注解

@Controller:用于表现层bean定义

@Service:用于业务层bean定义

@Repository:用于数据层bean定义

纯注解开发模式

com.ocean.config下添加

SpringConfig.class代替配置文件

@Configuration用于设定当前类为配置类

@ComponentScan(“路径”)用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式{“1”,”2”}

1
2
3
4
5
6
@Configuration
@ComponentScan("路径")
public class SpringConfig{

}

AppForAnnotation.class

1
2
3
4
5
6
7
8
9
public class App{
public static void main(String[] args){
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao)ctx.getBean("bookDao");
System.out.println(bookDao);
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}

bean作用范围

@Scope(“singleton”)单例 prototype非单例

bean生命周期

@PostConstruct构造方法后

@PreDestory在销毁前

关闭容器.close

自动装配

@Autowired

自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此不用写setter方法注入

自动装配建议使用无参构造方法创建对象,如果不提供对应构造方法,请提供唯一的构造方法

按类型装配只能有一个实现类,按名称装配

如果有多个相同类型Bean使用@Qualifier(“bookDao”)在”写bean名称” ;无法单独使用

使用@Value对简单类型进行装配

在配置文件里添加pro注解@PropertySource(“.properties”)不支持通配符

@Value(“${name}”)

第三方bean管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class SpringConfig{
//1.定义一个方法获得要管理的对象
//2.添加@Bean表示当前方法的返回值是一个bean
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("");
ds.setUrl("");
ds.setUsername("");
ds.setPassword("");
return ds;
}
}

getBean(DataSource.class);

@Import({JdbcConfig.class})用这个注解访问配置文件;只允许写一次,多个配置文件用数组方式写

为第三方Bean注入资源

引用类型:方法参数

简单类型:成员变量

XML配置对比注解配置

功能 XML配置 注解
定义bean bean标签:id属性、class属性 @Component,@Controller,@Service,@Repository,@ComponentScan
设置依赖注入 setter注入、构造器注入 @Autowired,@Qualifier,@Value
配置第三方bean bean标签:静态工厂、实例工厂、FactoryBean @Bean
作用范围 scope属性 @Scope
生命周期 标准接口:init-method、destroy-method @PostConstructor,@PreDestroy

Spring整合mybatis

MyBatis程序核心对象分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuider sqlSessionFactoryBuider = new SqlSessionFactoryBuider();
//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);
//6.释放资源
sqlSession.close();

整合

pom文件,导入包

spring-jdbc

mybatis-spring

  • Config包里
    • JdbcConfig
    • MybatisConfig
    • SpringConfig

MybatisConfig.class

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.ocean.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.ocean.dao");
return msc;
}

App.class

1
2
3
4
5
6
7
8
public class App{
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);
}
}

Spring整合JUnit

导入JUnit坐标

1
2
3
4
5
6
7
8
9
10
11
12
@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest{
@Autowired
private AccountService accountService;

@Test
public void testFindBuId(){
System.out.println(accountService.findById(1));
}
}

SpringMVC

入门

  • SpringMVC与Servlet技术功能相同,均属于web层开发技术
  • 基于Java实现MVC模型的轻量级Web框架
  • 表现层开发的
  1. spring-webmvc坐标
  2. 创建SpringMVC控制器类(等同于Servlet功能)@Controller
  3. 初始化SpringMVC环境(同Spring环境),设定S平日那个MVC加载的bean
  4. 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求

@Controller

  • 类注解
  • 放在SpringMVC控制器类定义上方
  • 设定SpringMVC的核心控制器Bean

@RequestMapping(“/save”)

  • 方法注解
  • 放在SpringMVC控制器方法定义上方
  • 设置当前控制器方法请求访问路径
1
2
3
4
5
6
7
8
9
10
@Controller
public class UserController {
//设置访问路径
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'module':'springmvc'}";
}
}

AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web容器的抽象类

  • 加载springMVC容器配置
  • 设置哪些请求归属springmvc处理
  • 加载spring容器配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//定义servlet容器启动类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载springMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
//设置哪些请求归属springmvc处理
@Override
protected String[] getServletMappings() {

return new String[]{"/"};
}
//加载spring容器配置
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}

pom文件

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
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

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

<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>

SpringMVC工作流程分析

Controller加载控制与业务bean加载控制

SpringMVC相关bean(表现层bean)

Spring控制的bean:业务bean(Service)、功能bean(DataSource)

SpringMVC相关bean加载控制

SpringMVC加载的bean对应的包均在controller包内

Spring相关bean加载控制

一:Spring加载的bean扫描范围为com.ocean,排除掉controller内的bean

二:扫描范围为精准范围如service包,dao包

1
2
3
4
5
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMvcConfig {

}

@ComponentScan

  • excludeFilters:排除扫描路径种加载的bean,需要指定类别和具体项
  • includeFilters:加载指定的bean,需要指定类别和具体项
1
2
3
4
5
6
7
8
9
@Configuration
@ComponentScan(value = "com.itheima",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
))
public class SpringConfig {

}

加载springMVC容器配置

加载spring容器配置

extends AbstractDispatcherServletInitializer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//定义servlet容器启动类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载springMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
//设置哪些请求归属springmvc处理
@Override
protected String[] getServletMappings() {

return new String[]{"/"};
}
//加载spring容器配置
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}

简化开发

extends AbstractAnnotationConfigDispatcherServletInitializer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//定义servlet容器启动类
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}

@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

PostMan工具

用于网页调试与发生页面HTTP请求的Chrome插件,常用于进行接口测试

  • 注册登录
  • 创建工作空间
  • 发起请求测试结果

设置请求映射路径

冲突解决

1.直接增加@RequestMapping(“/user/save”)

2.在类前增加请求路径前缀@RequestMapping(“/user”)

get请求与post请求发送普通参数

json数据传递参数

日期类型参数传递

响应

REST风格

SSM整合

配置整合

  • Spring
    • SpringConfig
  • Mybatis
    • MybatisConfig
    • JdbcConfig
    • jdbc.properties
  • SpringMVC
    • ServletConfig
    • SpringMvcConfig

功能模块

  • 表与实体类
  • dao(接口+自动代理)
  • service(接口+实现类)
    • 业务层接口测试(整合JUnit)
  • controller
    • 表现层接口测试(PostMan)

表现层与前端数据传输协议实现

image-20220929153004526

异常处理器

  • 框架内部抛出的异常:因使用不合规导致
  • 数据层抛出的异常:因外部服务器故障导致
  • 业务层抛出的异常:因业务逻辑书写错误导致
  • 表现层抛出的异常:因数据收集、校验等规则导致
  • 工具类抛出的异常:因工具类书写不严谨不够健壮导致

所有的异常均抛出到表现层进行处理

AOP思想

异常处理器可以集中的、统一的处理项目中出现的异常

1
2
3
4
5
6
7
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
return new Result(666,null);
}
}

定义Result类

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
public class Result {
private Object data;
private Integer code;
private String msg;

public Result() {
}

public Result(Integer code,Object data ) {
this.data = data;
this.code = code;
}

public Result(Integer code, Object data, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}

public Object getData() {
return data;
}

public void setData(Object data) {
this.data = data;
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}

定义Code类

1
2
3
4
5
6
7
8
9
10
11
12
public class Code {
public static final Integer SAVE_OK = 20011;
public static final Integer DELETE_OK = 20021;
public static final Integer UPDATE_OK = 20031;
public static final Integer GET_OK = 20041;

public static final Integer SAVE_ERR = 20010;
public static final Integer DELETE_ERR = 20020;
public static final Integer UPDATE_ERR = 20030;
public static final Integer GET_ERR = 20040;

}

项目异常处理

  • 业务异常
    • 规范的瀛湖行为产生的异常
    • 不规范的用户行为操作产生的异常
  • 系统异常
    • 项目运行过程中可预计且无法避免的异常
  • 其他异常
    • 编程人员未预期到的异常

项目异常处理方案

  • 业务异常
    • 发送对应消息传递给用户,提醒规范操作
  • 系统异常
    • 发送固定消息传递给用户,安抚用户
    • 发送特定消息给运维人员,提醒维护
    • 记录日志
  • 其他异常
    • 发送固定消息传递给用户,安抚用户
    • 发送特定消息给编程人员,提醒维护
    • 记录日志

模拟异常

1
2
3
4
5
6
7
8
9
10
11
12
13
public Book getById(Integer id) {
if(id==1){
throw new BusinessException(666,"业务异常");
}
//可能出现的异常进行包装,转换成自定义异常
try {
int i = 1/ 0;
}catch (ArithmeticException e ){
throw new SystemException(666,"服务器访问超时",e);

}
return bookDao.getById(id);
}

1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
return new Result(666,null);
}
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex){
//记录日志
//发送消息给运维
//发送邮件给开发人员
return new Result(ex.getCode(),null,ex.getMessage());
}
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException ex){
//记录日志
//发送消息给运维
//发送邮件给开发人员,ex对象发送给开发人员
return new Result(Code.BUSINESS_ERR,null,"系统繁忙");
}
}
  1. 自定义项目系统级异常
  2. 自定义项目业务级异常
  3. 自定义异常编码
  4. 触发自定义异常
  5. 拦截并处理异常
  6. 异常处理器效果对比

前后台协议联调