Spring框架的作用
主要解决了创建对象和管理对象的问题
重要注解
- @Component
- @Controller
- @Service
- @Repository
- @Configuration() 被此注解修饰的类作为配置类
- @Bean 被此注解修饰的方法创建的对象会被spring管理
通过Spring创建对象
使用组件注解创建对象
- 需要被Spring创建对象的类型,必须添加组件注解
- 基础的组件注解有: @Component(通用) / @Controller(控制层) / @Service(业务层) / @Repository(持久层)
- 在Spring框架的作用范围内,以上4个注解是等效的;
使用@Bean注解创建对象
- @Configuration() 被此注解修饰的类作为配置类
- @Bean 被此注解修饰的方法创建的对象会被spring管理
/**
* 被此注解修饰的类作为配置类
*/
@Configuration()
public class BeanConfig {
@Bean
public Date date(){
System.out.println("BeanConfig.date()");
return new Date();
}
@Bean
public Calendar calendar(){
System.out.println("BeanConfig.calendar");
return Calendar.getInstance();
}
@Bean
public LocalDateTime localDateTime(){
System.out.println("BeanConfig.localDateTime");
return LocalDateTime.now();
}
}
自定义的类可以通过组件注解创建对象,但是我们使用其他人封装好的类时则只能使用@Bean注解创建对象
那么通过spring创建的对象放在哪里了呢?
ApplicationContext接口
翻译过来叫做应用程序上下文,也称为spring的容器,spring创建并管理的对象都放在这个容器中
存放在容器中的对象 我们称为bean
AnnotationConfigApplicationContext 是这个接口的一个实现类
@Autowired
AnnotationConfigApplicationContext ac;
通过自动装配之后获取该类的对象,我们可以使用getBean()方法得到spring框架帮我们创建的对象
@Test
void testGetBean(){
CategoryService categoryService = ac.getBean(CategoryService.class);
System.out.println("categoryService = " + categoryService);
Date date = ac.getBean(Date.class);
System.out.println("date = " + date);
}
自动装配 @Autowired
如果匹配类别Bean有多个,必须保证名称匹配才可以正确装配
关于名称匹配:被自动装配的属性名称,与Bean的名称相同.
关于Bean的名称:如果类名的第一个字母是大写的,且第二个字母事小写的,则Bean的名称是将类名首字母改为小写,否则Bean的名称就是类名!
SpringMVC
SpringMVC主要解决了:接受请求响应结果这个问题
重要注解
- @RequestMapping
请求路径
和处理请求的方法
之间的关系映射,通过Method参数可以指定请求方式 - @ResponseBody 通过方法返回值的方式给客户端响应数据
- @RestController = @ResponseBody + @RequestMapping
- @GetMapping 将请求方式限制为Get,除了不能添加在类上,其他用法与
@RequestMapping
相同 - @PostMapping 将请求方式限制为Post,除了不能添加在类上,其他用法与
@RequestMapping
相同 - @PathVariable 此注解修饰的形参可以获取访问路径同名部分的参数
- @RestControllerAdvice 被修饰的类表示是统一异常处理类,和@ExceptionHandler注解配合使用;
此注解 == @ResponseBody + @ControllerAdvice , 被此注解修饰的类中的方法返回值会放在响应正文中响应给前端 - @ExceptionHandler 捕获全局异常
POJO
RESTful
RESTful是一种设计风格(并不是规范或标准)
RESTful的典型表现: 将id或类似具有"唯一性"的参数值作为URL的一部分,而不像传统参数那样体现
好处: URL更容易表现其意思,便于阅读
注意:不具备"唯一性"的参数值通常不会设计为URL的一部分
@PathVariable
此注解修饰的属性可以获取访问路径同名部分的参数
以下三种方法是可以共存的
//精准匹配
@RequestMapping("/test/edit")
public String edit(BrandEditDTO brandEditDTO){
System.out.println("test");
System.out.println("brandEditDTO = " + brandEditDTO);
return "尝试编辑品牌(尚未完成)test";
}
//使用正则表达式匹配
@RequestMapping("/{id:[0-9]+}/edit")
public String edit(@PathVariable Long id,BrandEditDTO brandEditDTO){
System.out.println("id = " + id );
System.out.println("brandEditDTO = " + brandEditDTO);
return "尝试编辑品牌(尚未完成)";
}
//使用正则表达式时避免发生冲突
@RequestMapping("/{name:[a-zA-Z]+}/edit")
public String edit(@PathVariable String name,BrandEditDTO brandEditDTO){
System.out.println("edit");
System.out.println("name = " + name );
System.out.println("brandEditDTO = " + brandEditDTO);
return "尝试编辑品牌(尚未完成)111111";
}
统一处理异常
这里自定义异常类有个注意点:
- 当自定义异常类(假设类名叫MyException)继承RuntimeException时,那么我们在throw new MyException时是不用在方法上throws的
- 当一个方法中使用throw抛出一个
非RuntimeException
的异常时,就要在该方法上使用throws声明这个异常的抛出。此时调用该方法的代码就必须处理这个异常,否则编译不通过。
响应JSON格式的字符串
MyBatis框架
解决了数据编程相关的问题,主要是简化了数据库编程.
通过代理模式
自动生成接口的实现对象,需要明确哪些接口需要生成代理对象
重要注解
@Mapper
@MapperScan(全限定包名)
指定MyBatis框架扫描的包,生成括号内指定的包下所有接口的代理对象@Param()
当接口中方法的形参数量大于1时,常使用该注解修饰接口方法中的多个形参.在springboot环境下可不使用此注解
在接口上添加@Mapper
注解,在启动项目时,MyBatis会对整个项目进行扫描,对于已经添加此注解的接口就会生成代理对象.
也可以在配置类上添加@MapperScan
注解,用于指定各Mapper接口所在的包,指定包下的接口上就不需要使用@Mapper
注解了.
推荐使用@MapperScan
的方法
注意:使用
@MapperScan
注解时,一定只指向Mapper接口所在的包,并确保此包下无其他接口
使用MyBatis
添加依赖
使用xml方式配置sql
首先在properties配置文件中增加以下配置,让MyBatis框架知道XML文件的保存路径
注意:这里的classpath表示的是
resources
目录
两个重要属性
- namespace ⇒ 指定接口的全限定类名
- id ⇒ 指定方法名
使用useGeneratedKeys及keyProperty属性获取数据库中主键自增的值
@Param的使用
当接口的形参数量只有一个时,不需要使用@Param注解,mapper.xml文件中的
#{}
中的值是什么其实是无所谓的
比如当使用id去执行删除命令时,使用的sql语句:delete from xxx where id=#{id} delete from xxx where id=#{0} delete from xxx where id=#{xxx}
以上三句sql在此种情况下都是可以的
使用Mybatis实现批量操作(增,删,改)数据
利用"动态SQL"机制:
- xml中的配置
上述sql最终可以理解为:
delete from pms_brand where id in (1,2,3,4,5)
- mapper接口的实现:
//可变形参 = 数组
int deleteByIds(Long... ids);
//数组
int deleteByIds(Long[] ids);
//集合
int deleteByIds(List<Long> ids);
使用MyBatis实现动态SQL修改数据
在动态SQL机制中,可以使用< if >
标签,可用于对某参数值进行判断,从而生成不同的SQL语句片段
<set>
标签有2个作用:
1 能在正确位置生成set关键字
2 能够将动态生成的sql语句最后一个字符的逗号删除
查询
统计查询
单一结果查询
查询列表
联表查询
联表查询时,用于封装查询结果的对象中的某个属性可能会有多个值,对于这种情况,可以使用List集合来保存数据,同时在Mapper.xml文件中使用< collection >标签来封装查询得到的多个值对应的属性
注意点:
1.必须使用< resultMap > 标签来指定对应关系
2.明确的写出每个字段和属性的对应关系
3.使用< collection >标签来封装查询得到的多个值对应的属性
总结xml中的标签
<mapper namespace="cn.tedu.csmall.server.mapper.BrandMapper">
</mapper>
<mapper>
- 属性:
namespace
指定mapper层的全限定类名
- 属性:
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
SQL...
</insert>
<insert>
- 属性:
id
指定方法名
- 属性:
<delete id="deleteById">
SQL...
</delete>
<delete>
- 属性:
id
指定方法名
- 属性:
<update id="updateNameById">
update pms_brand
<set>
<if test="name != null">name=#{name},</if>
<if test="pinyin != null">pinyin=#{pinyin},</if>
<if test="productCount != null">product_count=#{productCount},</if>
</set>
where id = #{id}
</update>
<update>
- 属性:
id
指定方法名
- 属性:
<set>
通过配合使用< if >标签实现动态修改数据
<select>
- 属性:
id
指定方法名 resultType
指定返回值类型(基本数据类型或在java.lang包下的引用类型都可以直接写类名,其他需写全限定类名)resultMap
用于指定下划线式命名和驼峰式命名的对应关系,其指定的值对应<resultMap>
标签中的id
值
- 属性:
注意: < select >标签中 resultType和resultMap属性只能有一个
<resultMap>
id
用于对应< select >标签中的 resultMap 属性的值type
指定返回值类型(基本数据类型或在java.lang包下的引用类型都可以直接写类名,其他需写全限定类名)
<if test="pinyin != null">
某代码片段
</if>
<if test="pinyin == null">
某代码片段
</if>
<if>
判断标签test
判断条件
<choose>
<when test="条件">
满足条件时的SQL片段
</when>
<otherwise>
不满足条件时的SQL片段
</otherwise>
</choose>
<choose>
<delete id="deleteByIds">
delete from pms_brand where id in (
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</delete>
<foreach>
遍历