@param
实际上就是将多参数组成一个map集合,其中@Param中value配置型的值为map集合的key(可以起任意名),形参值为map集合的value
List<Emp> selectByParam(@Param("sal") Double sal, @Param(value = "deptno") Integer deptno);
事务注解
@Transactional
可用于方法与类上
@Service
//@Transactional
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpDao empDao;
public Emp findById(Integer empno) {
return empDao.selectById(empno);
}
public List<Emp> list() {
return empDao.select();
}
/**
* 注解式事务
*/
// @Transactional
// @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ,
// rollbackFor = Exception.class, readOnly = true, timeout = 5)
public PageInfo<Emp> listPage(Integer pageNumber, Integer pageSize) {
PageHelper.startPage(pageNumber, pageSize);
PageInfo<Emp> pageInfo = new PageInfo<Emp>(empDao.select());
return pageInfo;
}
}
spring注解
@Component
标记在类上,将标记的类放入IOC容器中,配置非三层架构中的对象,例如配置类对象…
@Controller
标记在类上,标识该类是controller控制层的类,将Controller对象放入IOC容器中
@Service
标记在类上,标识该类是业务层的类,将Service对象放入IOC容器中
@Repository
标记在类上,标识该类是操作数据(持久)层的类,将Dao对象放入IOC容器中
@Value
a.标记在成员变量上,作用:为简单类型的成员变量赋值,该成员变量可以不提供set方法
b.读取自定义配置文件配置(见springboot注解)
@Autowired
@Resource
使用时需要标注在@Autowired注解下面
@Qualifier
标记在成员变量上,从IOC容器中取出该对象
-
注入简单类型:@Value
-
注入自定义类型:@Autowired,@Resource,@Qualifier
@Autowired:即可使用名称装配又可使用类型装配,先根据类型匹配,再根据名称匹配。是Spring自带注解
@Qualifier:即可使用名称装配又可使用类型装配,先根据类型匹配,再根据名称匹配。且可以指定Bean名称
@Resource:即可使用名称装配又可使用类型装配,先根据名称匹配,再根据类型匹配。是Java中自带的注解,由spring框架进行注解解析。
@Primary
当IOC容器中有多个同类型的对象时,此注解标记的类为主类
@Component
// @Primary
public class Employee {
@Value("7369")
private Integer empno;
@Value("zhangsan")
private String ename;
/**
* 自定义类型的属性赋值(依赖注入)是通过自动注入完成
*
* @Autowired @Qualifier指定Bean的名称
* 先根据类型匹配,出现问题后,再根据名称
* @Resource
* 先根据名称,再根据类型
*/
@Autowired
// @Resource
// @Qualifier("department2")
private Department dept;
}
切面AOP注解
@Aspect
@Aspect:把当前类标识为一个切面供容器读取
@Order
@Order:配置切面类的优先级
@Pointcut
@Pointcut:配置切面表达式
@Before
@Before:前置通知,方法执行之前
@After
@After:后置通知,无论当前方法是否正常结束都会执行
@AfterReturning
@AfterReturning:返回通知,方法正常结束之后
@AfterThrowing
@AfterThrowing:异常通知,方法非正常结束之后
异常通知与返回通知,互斥,只会执行其中一种
@Pointcut
切面表达式
@Component
//把当前类标识为一个切面供容器读取
@Aspect
//@Order
public class AopAspect {
/**
* 配置切面表达式,两种方式
* a.使用注解,方法名称就是切面表达式名称
* b.设置常量
*/
@Pointcut("execution(* com.bjpowernode.controller.*.*(..))")
private void exp(){}
private static final String POINT_CUT = "execution(* com.bjpowernode.controller.*.*(..))";
/**
* 前置通知,使用@Before
*/
@Before("exp()")
public void before(){
System.out.println("前置通知。。。。");
}
/**
* 后置通知,使用@After
*/
@After(POINT_CUT)
public void after(){
System.out.println("后置通知。。。。");
}
/**
* 返回通知,使用@AfterReturning
* @param result 返回的结果
*/
@AfterReturning(value = POINT_CUT ,returning = "result")
public void returning(Object result){
System.out.println("返回通知。。。。"+result);
}
/**
* 异常通知,使用@AfterThrowing
* @param ex 错误信息
*/
@AfterThrowing(value = POINT_CUT ,throwing = "ex")
public void afterThrowing(Exception ex){
System.out.println("异常通知。。。。"+ex.getMessage());
}
}
请求注解
@RequestMapping
获取请求路径,@RequestMapping(“请求路径”),可注解在类与方法上
/**
* @RequestMapping
* 位置:方法和类
* 作用:将一个请求路径与处理请求的方法绑定
* 一个处理请求的方法绑定多个请求路径
* 路径:建议路径以斜杠开头,不以斜杠开头也可以
*/
// @RequestMapping("/url.do")
@RequestMapping({"/url.do", "/getUrl.do", "/test.do"})
public ModelAndView url(){
System.out.println("测试@RequestMapping注解中路径绑定...");
return new ModelAndView("success");
}
@GetMapping
获取查询(get)请求
@GetMapping("/get/{id}")
public String get(@PathVariable("id") Integer id){
System.out.println("UserController中的get方法..." + id);
return "success";
}
@PostMapping
获取新增(post)请求
@PostMapping("/save")
public String save(){
System.out.println("UserController中的save方法...");
return "success";
}
@PutMapping
获取修改(put)请求
@PutMapping("/edit")
public String edit(){
System.out.println("UserController中的edit方法...");
//put请求与delete请求最后必须重定向到jsp,因为jsp不支持put和delete请求的转发
return "redirect:/user/list";
}
@DeleteMapping
获取删除(delete)请求
@DeleteMapping("/remove/{id}")
public String remove(@PathVariable("id") Integer id){
System.out.println("UserController中的remove方法..." + id);
return "redirect:/user/list";
}
@RequestParam
当标注了注解之后默认当前请求参数中必须有此参数,手动绑定请求参数与形参
/**
* @RequestParam
* 1.手动绑定请求参数与形参
* 2.当标注了注解之后默认当前请求参数中必须有此参数, required = true
* 3.通过修改配置项required = false,可以不限制请求参数
* 4.defaultValue =设置默认值
*/
@RequestMapping("/simple2.do")
public String simple2(@RequestParam(value = "empno", required = false, defaultValue = "100") Integer id){
System.out.println("id:" + id);
return "success";
}
在SpringMVC中集合类型都不能直接接收请求参数,需要使用@RequestParam注解来标注
/**
* 在SpringMVC中集合类型都不能直接接收请求参数,需要使用@RequestParam注解来标注
*
* list集合类似于数组
*/
@RequestMapping("/list.do")
public String listParam(@RequestParam List<Integer> ids){
System.out.println("list集合:" + ids);
return "success";
}
/**
* map集合类似于对象
*/
@RequestMapping("/map.do")
public String mapParam(@RequestParam Map<String, Object> map){
System.out.println("map集合:" + map);
return "success";
}
@PathVariable
获取路径传参时路径中的数据,路径中的变量名与形参名称保持一致时,注解可以不使用value配置项
不一致时,注解必须使用value配置项,告知从路径中获取的数据名称
public String get(@PathVariable("id") Integer id){
System.out.println("UserController中的get方法..." + id);
return "success";
}
@ResponseBody
处理异步的请求的类或方法
@Controller
//表示当前处理器类中所有的方法都是响应json串
@ResponseBody
public class JsonController(){}
/**
* 处理异步的请求的方法
* 返回值:可以是任意类型
*
* 响应时需要使用注解来标注
* 当引入jackson依赖之后,使用@ResponseBody标注方法
* jackson工具会将方法返回值转换为json串,并且会将响应头中Content-Type修改为application/json
* 响应客户端
*/
@ResponseBody
@RequestMapping("/getObj.do")
public Student getObj(){
Student student = new Student(10, "tom", new Date());
return student;
}
@RequestBody
接受json串(数据)
作用:将json串转换为Java对象
/**
* @RequestBody
* 作用:将json串转换为Java对象
*/
@ResponseBody
@RequestMapping("/sendData.do")
public String sendData(@RequestBody Student student){
System.out.println(student);
return "ok";
}
@RestController
相当于
@ResponseBody 处理异步的请求的类或方法
@Controller标记在类上,标识该类是controller层的类,将Controller对象放入IOC容器中
// @RestController = @ResponseBody + @Controller
@RestController
@RequestMapping("/emp")
public class EmpController {}
日期
@DateTimeFormat
在日期格式处理上使用,格式化前端页面提交的请求参数的日志格式(将字符串转换日期类型)
/**
* 接收请求参数,可以直接定义处理请求方法的形参,类型也会自动转换
*
* 在日期格式处理上使用的注解@DateTimeFormat
* 作用:格式化前端页面提交的请求参数的日志格式(将字符串转换日期类型)
*
* 注意:请求参数名与处理请求方法的形参名必须保持一致
*/
@RequestMapping("/simple.do")
public String simple(Integer id, String name, @DateTimeFormat(pattern = "yyyy-MM-dd") Date birth){
System.out.println("id:" + id);
System.out.println("name:" + name);
System.out.println("birth:" + birth);
return "success";
}
@JsonFormat与@JSONField
将Java中Date对象转换为指定格式的字符串
/**
* @DateTimeFormat 将浏览器提交的日期格式字符串转换为Java中Date对象
* jackson
* @JsonFormat 将Java中Date对象转换为指定格式的字符串,发送给前台
* fastjson
* @JSONField 将Java中Date对象转换为指定格式的字符串
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
// @JsonFormat(pattern = "yyyy-MM-dd")
@JSONField(format = "yyyy-MM-dd")
private Date birthday;
public Student() {
}
异常处理
@ControllerAdvice
当前项目所有的异常,都进入到此处理器中进行处理
只能用在类上
/**
* 全局异常处理类
* @ControllerAdvice
* 作用:当前项目所有的异常,都进入到此处理器中进行处理
*/
@ControllerAdvice
public class MyExceptionHandler(){}
@RestControllerAdvice
定义此类为异常处理类,响应类型为JSON串
@RestControllerAdvice
public class GlobalExceptionHandler {}
@ExceptionHandler
注解式异常处理 如果出现异常,将自动执行此方法
只能用在方法上
/**
* 局部异常处理方法
*
* 注解式异常处理
* 如果出现异常,将自动执行此方法
* @ExceptionHandler
* 配置项:表示当前方法接收处理的异常类型
*
*/
@ExceptionHandler(RuntimeException.class)
public String handleRuntimeException(Model model){
model.addAttribute("message", "sorry!!!Runtime");
return "error";
}
@ExceptionHandler(Exception.class)
public String handleException(Model model){
model.addAttribute("message", "sorry!!!");
return "error";
}
springboot注解
@SpringBootApplication
标记此类为springbot的启动类
@SpringBootApplication
public class SpringbootDome01Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootDome01Application.class, args);
}
}
@SpringBootConfiguration
@SpringBootApplication的f父注解
/**
* @SpringBootConfiguration
* 作用:表示当前类为一个配置类(XML)
* 当前启动类也是一个配置类
*/
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot01HelloworldApplication.class, args);
Student student = applicationContext.getBean(Student.class);
System.out.println(student);
}
}
@EnableAutoConfiguration
@SpringBootApplication的f父注解
/**
* @EnableAutoConfiguration
* 作用:
* 1.@AutoConfigurationPackage
* 确定当前项目的组件扫描包<context:component-scan base-package="com.bjpowernode"/>
* 启动类所在包就是组件扫描基础包
* 2.开启自动化配置
* 自动化配置:自动配置当前模块的XML
* springboot在启动时自动加载了多个自动化配置类(实现系统的自动配置),在2.6.9版本中加载了133个,实际生效24个
* 在加载自动化配置的过程中,会根据当前项目引入的依赖来确定当前模块的自动化配置是否生效。
*/
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot01HelloworldApplication.class, args);
Student student = applicationContext.getBean(Student.class);
System.out.println(student);
}
}
@ComponentScan
@SpringBootApplication的f父注解
/**
* @ComponentScan
* 作用:配置组件扫描包的注解
*/
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot01HelloworldApplication.class, args);
Student student = applicationContext.getBean(Student.class);
System.out.println(student);
}
}
@Conditional以及@ConditionalXXX
@SpringBootApplication的f父注解
/**
* @Conditional以及@ConditionalXXX
* 作用:配置类是否生效的条件
*/
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Springboot01HelloworldApplication.class, args);
Student student = applicationContext.getBean(Student.class);
System.out.println(student);
}
}
@Configuration
标记此类为配置类
相当于spring中的applicationContext.xml配置文件
/**
* 配置类
* 相当于spring中的applicationContext.xml
*/
@Configuration
//快速导入
@Import(value = Person.class)
public class StudentConfig {}
对象放入IOC容器三种方法
/**
* 1.xml配置文件
* 2.注解@Component
* 3.Java Config注解@Configuration
*/
java Config
/**
* 配置类
* 相当于spring中的applicationContext.xml
*/
@Configuration
//快速导入
@Import(value = Person.class)
public class StudentConfig {
/**
* 配置bean
* 返回值类型为放置到IOC容器中的对象类型,返回值为放入IOC容器的bean对象
* 方法的名称为bean的名称
*/
@Bean
@Primary
public Student getStudent(){
return new Student();
}
}
@SpringBootTest
springboot测试类注解
/**
* @SpringBootTest
* springboot中的测试类注解
* 测试类在启动时,可以访问IOC容器,到IOC容器中获取bean对象
*/
@SpringBootTest
class Springboot01HelloworldApplicationTests {
@Autowired
Student student;
@Test
void contextLoads() {
System.out.println(student);
}
}
@Import(类名.class)
将对象快速导入到IOC容器中,用于启动类或配置类上
/**
* 配置类
* 相当于spring中的applicationContext.xml
*/
@Configuration
//快速导入
@Import(value = Person.class)
public class StudentConfig {}
@Value
读取自定义配置文件配置
配置文件
#键: 值
myKey: myValue
#同一层级
com1: java
bjpowernode: java
#二级层级
com2:
bjpowernode: java
#三级层级
com3:
bjpowernode:
text: java
#数据类型
name: 张三
date: 2022/07/09
age: 20
gender: true
obj: ~
#数组(集合,对象)
array: [1,2,3]
list:
- 1
- 2
- 3
set: 1,2,3
student:
name: tom
age: 22
birthday: 2000/01/01
gender: true
hobby: [sing,jump,rap,basketball]
address:
city: 郑州
area: 金水区
street: 未来路
#springboot服务器相关配置
#tomcat端口号设置
server:
port: 8080
#根路径设置
servlet:
context-path: /web
读取自定义配置文件配置
/**
* 使用@Value+spring表达式读取自定义配置
*/
@Value("${name}")
private String name;
@Value("${student.name}")
private String student;
@Value("${date}")
private Date date;
@ConfigurationProperties
批量读取配置
prefix:前缀
/**
* 1.编写类与成员变量,成员变量名称与配置名保持一致
* 2.需要使用两个注解有两种方法
* a.@ConfigurationProperties + @Component
* b.@ConfigurationProperties + @EnableConfigurationProperties
*/
@Component
@ConfigurationProperties( prefix = "")
public class StudentConfig {}
@Value(“”)与@ConfigurationProperties( prefix = “”)对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IDKT5STa-1660373758148)(file:///C:\Users\admin\AppData\Local\Temp\ksohtml14912\wps1.png)]
松散语法的意思就是一个属性在配置文件中可以有多个属性名,举个栗子:学生类当中的 firstName 属性,在配置文件中可以叫 firstName、first-name、first_name 以及 FIRST_NAME。 而 @ConfigurationProperties 是支持这种命名的,@Value 不支持。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pP00NODb-1660373758150)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1657522068326.png)]
@EnableConfigurationProperties({*.class, *.class})
用于启动类上,作用将某个类(可以加载多个)加载到IOC容器中,类似于@Component
@SpringBootApplication
@EnableConfigurationProperties({StudentProperties.class, AddressProperites.class})
public class Springboot02ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot02ConfigApplication.class, args);
}
}
@PropertySource(value = “classpath:*.properties”)
加载第三方配置文件
@Component
@ConfigurationProperties(prefix = "jdbc.mysql")
//加载第三方资源文件
@PropertySource(value = "classpath:db.properties")
public class MysqlProperties {}
@ImportResource(locations = “classpath:application*.xml”)
加载原生spring配置文件
@SpringBootApplication
@EnableConfigurationProperties({StudentProperties.class, AddressProperites.class})
//加载原生spring的配置文件XML
@ImportResource(locations = "classpath:applicationContext.xml")
public class Springboot02ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot02ConfigApplication.class, args);
}
}
配置文件优先级
优先级:谁生效谁的优先级高,谁最后读谁优先级高
properties > yml(yaml)
yml(yaml)优先读取,properties后读取
后读取的配置会替换掉先读取的配置内容
配置文件配置多个:application-(扩展名),
例如:application-dev,application-prod,application-test
application-dev:开发时使用
application-prod:生产(发布)时使用
application-test:测试时使用
在主配置文件中配置激活副配置文件
#激活环境配置profiles
spring:
profiles:
active: (配置文件扩展名)
lombok代码简化(注解)依赖
@Getter
@Setter
@ToString
@Data
(上面注解简写)
@NoArgsConstructor
(无参构造)
@AllArgsConstructor
(有参构造)
@Accessors(chain = true)
开启对象中方法的链式调用
<!--lombok依赖
作用:简化。实现注解式get/set,构造方法,toString方法...注解式日志
条件:1.依赖 2.IDEA(ombok)插件
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
// @Getter
// @Setter
// @ToString
@Data(上面注解简写)
@NoArgsConstructor (无参构造)
@AllArgsConstructor (有参构造)
//开启对象中方法的链式调用
@Accessors(chain = true)
public class Student {
private Integer id;
private String name;
private Integer age;
private String address;
private Double scroe;
}
public static void main(String[] args) {
Student student = new Student();
// student.setId(1);
// student.setName("小明");
// student.setAge(20);
// student.setAddress("北京");
// student.getName();
//链式赋值
student.setId(1)
.setName("小明")
.setAge(20)
.setAddress("北京");
student.getName();
System.out.println(student);
Student s2 = new Student(2, "小红", 21, "上海", 96.5);
System.out.println(s2);
}
@Slf4j
日志注解,使用@Slf4j后无需在写成员变量,并定义一个常量log
//注解式日志
@Slf4j
@RestController
public class LogController {
/**
* 使用日志:
* 在当前类中声明一个Logger类型的成员变量
* 使用@Slf4j后无需在写成员变量,并定义一个常量log
*/
//private Logger logger = LoggerFactory.getLogger(LogController.class);
}
@MapperScan(basePackages = {“…”, “…”})
批量批量加载mapper接口
/**
* 批量加载mapper接口
*/
@MapperScan(basePackages = {"com.bjpowernode.dao", "com.bjpowernode.dao2"})
@SpringBootApplication
public class Springboot07MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot07MybatisApplication.class, args);
}
}
@Mapper
加载单个mapper配置文件,配置在接口上
/**
* 单个加载mapper接口
* 将当前标注接口生成Mapper代理对象,并将代理对象放入IOC容器中
*/
@Mapper
public interface AdminDao {
List<Admin> select();
}
事务
@Transactional(rollbackFor = Exception.class)
添加事务,作用在类或方法上
默认回滚运行异常
//sprigboot项目中事务采用注解的方式配置
@Transactional(rollbackFor = Exception.class)
public class AdminServiceImpl implements AdminService {
@Autowired
private AdminDao adminDao;
@Override
// @Transactional(rollbackFor = Exception.class)
public List<Admin> list() {
return adminDao.select();
}
校验注解
实体类中使用的注解
@NotNull 数据不能为null
@NotEmpty 数据不能为null,不能为空字符串
@NotBlank 数据不能为null,不能为空字符串,不能由空白字符组成
@Size 校验数据、集合、字符串的长度
@Range 数字范围校验
@Email 邮箱校验
@Pattern(regexp=“”, message = “”) 正则校验
通用配置项:message 校验失败时的提示信息
/**
* 后台数据校验通过注解的方式来实现
*
* 1.在实体类的成员变量上添加校验注解
* 2.在接收请求参数的形参前添加注解
* @Validated放在需要校验的形参前,形参后跟随一个形参BindingResult(收集错误信息)
*/
@Data
public class Student {
/**
* @NotNull 数据不能为null
* @NotEmpty 数据不能为null,不能为空字符串
* @NotBlank 数据不能为null,不能为空字符串,不能由空白字符组成
* @Size 校验数据、集合、字符串的长度
* @Range 数字范围校验
* @Email 邮箱校验
* @Pattern(regexp="", message = "") 正则校验
*
* 通用配置项:message 校验失败时的提示信息
*/
// @NotNull
// @NotEmpty
@NotBlank(message = "姓名不能为空")
@Size(message = "姓名长度为4~10个字符", min = 4, max = 10)
private String name;
@NotNull(message = "年龄不能为空")
@Range(message = "年龄范围为0~100岁", min = 0, max = 100)
private Integer age;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不合法")
// @Pattern(regexp="", message = "")
private String email;
}
controller中使用的注解
@Validated
@Validated放在需要校验的形参前,形参后跟随一个形参BindingResult(收集错误信息)
@RestController
public class ValidationController {
@PostMapping("/save")
public String save(@Validated Student student, BindingResult bindingResult){
//判断校验是否通过
if(bindingResult.hasErrors()){
List<ObjectError> list = bindingResult.getAllErrors();
for (ObjectError objectError : list) {
//打印错误信息
System.out.println(objectError.getDefaultMessage());
}
}else{
System.out.println(student);
}
return "ok";
}
}
校验配置文件
@Validated
@Data
//批量读取配置文件
@ConfigurationProperties(prefix = "user")
@Validated
//设置此类为配置类
//@Configuration
public class UserYml {
@NotBlank(message = "用户不能为空")
@Size(message = "用户名在4~16位之间",min = 4,max = 14)
private String username;
@NotNull(message = "年龄不能为空")
@Range(message = "年龄在0~150岁之间",min = 0,max = 150)
private Integer age;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱不合法")
private String email;
}
@Pattern
正则校验:@Pattern(regexp=“”, message = “”)
regexp:校验规则
message:错误提示信息
书写API文档注解
@ApiModel
描述实体类
@ApiModelProperty
描述实体类属性
@Data
@AllArgsConstructor
@NoArgsConstructor
//描述实体类
@ApiModel("学生实体类")
public class Student {
//描述属性
@ApiModelProperty("学生ID")
private Integer id;
//描述属性
@ApiModelProperty("学生姓名")
private String name;
//描述属性
@ApiModelProperty("学生地址")
private String address;
//描述属性
@ApiModelProperty("学生生日")
private Date birthDate;
}
@Api
描述接口(controller)类
tags:“描述信息”
@ApiOperation
描述方法
@ApiImplicitParams
描述方法中的多个参数
@ApiImplicitParam
描述方法中的单个参数
name:描述的请求参数名
value:请求参数解释
required:当前请求参数是否时必须的
dataType: 请求参数类型
defaultValue: 请求参数默认值
paramType:传参类型
query:拼接传参
path:路劲传参
@ApiResponses
多个返回结果描述
@ApiResponse
单个返回结果描述
code:响应码
message:响应码描述
@RestController
@RequestMapping("/student")
@Api(tags = "学生接口")
public class StudentController {
/**
* 查询所有学生
*/
@GetMapping("/list")
@ApiOperation("分页查询")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNumber", value = "当前页码", required = false, dataType = "Integer", defaultValue = "1", paramType = "query"),
@ApiImplicitParam(name = "pageSize", value = "每页显示数", required = false, dataType = "Integer", defaultValue = "5", paramType = "query"),
@ApiImplicitParam(name = "student",value = "查询学生条件",required = false,dataType = "Student",paramType = "query")
})
@ApiResponses({
@ApiResponse(code = 0,message = "成功"),
@ApiResponse(code = -1,message = "失败")
})
public Result selectList(@RequestParam(value = "pageNumber", defaultValue = "1") Integer pageNumber,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
Student student) {
System.out.println(pageNumber);
System.out.println(pageSize);
System.out.println(student);
return Result.success();
}
/**
* 通过ID查询学生
*/
@GetMapping("/get/{id}")
@ApiOperation("通过id查询学生")
@ApiImplicitParam(name = "id",value = "查询学生id",required = true,dataType = "Integer",paramType = "path")
@ApiResponses({
@ApiResponse(code = 0,message = "成功"),
@ApiResponse(code = -1,message = "失败")
})
public Result selectById(@PathVariable("id") Integer id) {
System.out.println(id);
return Result.success();
}
/**
* 新增学生
*/
@PostMapping("/save")
@ApiOperation("新增学生")
@ApiImplicitParam(name = "student",value = "新增学生信息",required = true,dataType = "Student",paramType = "query")
@ApiResponses({
@ApiResponse(code = 0,message = "成功"),
@ApiResponse(code = -1,message = "失败")
})
public Result save(@RequestBody Student student) {
System.out.println(student);
return Result.success();
}
/**
* 修改学生信息
*/
@PutMapping("update")
@ApiOperation("修改学生信息")
@ApiImplicitParam(name = "student",value = "修改学习信息",required = true,dataType = "student",paramType = "query")
@ApiResponses({
@ApiResponse(code = 0,message = "成功"),
@ApiResponse(code = -1,message = "失败")
})
public Result update(@RequestBody Student student) {
System.out.println(student);
return Result.success();
}
/**
* 删除学生
*/
@DeleteMapping("/delete/{id}")
@ApiOperation("通过id删除学生")
@ApiImplicitParam(name = "id",value = "删除学生的id",required = true,dataType = "Integer",paramType = "path")
@ApiResponses({
@ApiResponse(code = 0,message = "成功"),
@ApiResponse(code = -1,message = "失败")
})
public Result delete(@PathVariable("id") Integer id) {
System.out.println(id);
return Result.success();
}
}
空指针问题
使用swagger3.0时会出现空指针解决方案
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
异步注解
@EnableAsync
开启异步调用,用在主方法上
//开启异步调用
@EnableAsync
@SpringBootApplication
public class Springboot11OtherApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot11OtherApplication.class, args);
}
}
@Async
异步调用注解,使用在需要异步的方法上
@Service
public class AsyncService {
/**
* 异步调用注解
*/
@Async
public void task1(){
try {
long start = System.currentTimeMillis();
//模拟程序执行好事
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("task1耗时:" + (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
定时任务注解
@EnableScheduling
开启定时任务,作用在主类上
//开启定时任务
@EnableScheduling
@SpringBootApplication
public class Springboot11OtherApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot11OtherApplication.class, args);
}
}
@Scheduled
定时任务注解,作用在需要定时执行的方法上
cron:定时表达式
@Service
public class JobService {
/**
* 定时任务注解 @Scheduled cron为定时表达式
* 秒 分 时 日 月 周 年(可选)
* *星号:表示每,每秒,每分....
* ?问好:只能在日期和星期两个位置出现,排除冲突
* -中划线:表示一个范围
* ,逗号:表示一个列表值,比如在星期中使用 1,2,4
*/
// @Scheduled(cron = "* * * ? * 1-5")
@Scheduled(cron = "0/5 * * ? * 1-7")
public void myJob(){
System.out.println("定时执行...");
}
}
Redis缓存注解
开启缓存注解两步
A:开启缓存注解
B:配置缓存管理器
@EnableCaching
开启缓存注解
@CachePut
向redis中存放数据
@Cacheable
作用:根据指定key获取redis对应的value,如果在redis查找不到对应value值,就会执行方法,将方法的返回值存储到redis中
@CacheEvict
作用:清除缓存/批量清除缓存
自定义配置
@Configuration
/**
* k开启缓存注解
*/
@EnableCaching
public class RedisConfig {
/**
* 配置RedisTemplate
* 目的:设置全局的序列化规则
*
* 在配置类的方法中,方法的参数(形参)可以直接到IOC容器中获取bean
*/
@Bean("redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
//创建RedisTemplate对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
//设置key与value的序列化
//设置string类型key
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置hash类型key
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//设置string类型Value
redisTemplate.setValueSerializer(jackson2JsonSerializer());
//设置hash类型Value
redisTemplate.setHashValueSerializer(jackson2JsonSerializer());
return redisTemplate;
}
/**
* 配置value序列化
*/
public RedisSerializer<Object> jackson2JsonSerializer(){
//获取Jackson2JsonRedisSerializer对象
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
/**
* 设置序列化工具
* ObjectMapper 对象与json之间的转换工具
*/
ObjectMapper objectMapper = new ObjectMapper();
/**
* PropertyAccessor.ALL 所有对象属性可操作
* JsonAutoDetect.Visibility.ANY 当前所有属性可访问
*/
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
/**
* ObjectMapper.DefaultTyping.NON_FINAL 序列化的时候属性不是常量
*/
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//ObjectMapper设置到序列化器中
serializer.setObjectMapper(objectMapper);
return serializer;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
//1.RedisCacheConfiguration Redis的缓存配置对象
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
//设置缓存信息
//设置键过期时间
configuration = configuration.entryTtl(Duration.ofHours(4))
//设置序列化规则
//key为字符串
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
//Value为Json串
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonSerializer()))
.disableCachingNullValues();
//2.设置缓存空间(键中的层级,键的前缀)
Set<String> cacheNames = new HashSet<>();
cacheNames.add("default:cache");
cacheNames.add("user:login");
//3.为不同缓存空间设置配置
Map<String,RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("default:cache",configuration);
configMap.put("user:login",configuration.entryTtl(Duration.ofHours(2)));
//4.创建缓存管理器
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}
实例
@Service
public class UserService {
/**
* @CachePut
* 作用:向redis中存放数据
* 缓存的值为当前方法的返回值
* redis中的键 = 配置项cacheNames + 配置项key
*
* 配置项:
* cacheNames/value 缓存空间,缓存键的前缀,是属于键中的固定部分,所以指定字符串
* key 缓存键中动态部分,其中不能使用固定字符串,需要使用表达式来实现
* 表达式:
* #result 表示当前方法的返回值对象
* #当前方法参数名(推荐使用)
* #root.args 表示当前方法的参数列表(数组)
* #root.args[0] 表示当前方法的第一个参数 #a0 #p0
* #root.methodName表 示当前方法的名称
* unless/condition 存储条件,其中必须使用表达式
* unless:条件成立则不存储,条件不成立则存储
* condition:条件成立则存储,条件不成立则不存储
*
*/
@CachePut(cacheNames = CommonsUtil.USER_LOGIN_CACHE, key = "#username", unless = "#result == null")
public User login(String username, String password){
//模拟登录
return new User(1000, username, password);
// return null;
}
/**
* @Cacheable
* 作用:根据指定key获取redis对应的value,如果在redis查找不到对应value值,就会执行方法,将方法的返回值存储到redis中
*
* 如果只想实现查询的功能,方法返回值为null,并配置存放条件为null值不存储
*/
@Cacheable(cacheNames = CommonsUtil.USER_LOGIN_CACHE, key = "#username", unless = "#result == null")
public User getUser(String username){
System.out.println("getUser.....");
return new User(111, username, null);
}
/**
* @CacheEvict
* 作用:清除缓存
*/
@CacheEvict(cacheNames = CommonsUtil.USER_LOGIN_CACHE, key = "#username")
public void removeUser(String username){
System.out.println("删除缓存...");
}
/**
* 批量删除缓存:根据缓存的前缀(缓存空间)删除多个缓存
*/
@CacheEvict(cacheNames = CommonsUtil.USER_LOGIN_CACHE, allEntries = true)
public void removeUserAll(){
System.out.println("删除全部缓存...");
}
}
mybatis-Plus注解
前提
service层继承IService<实体类类型>类
serviceImpl继承ServiceImpl<持久层接口类型, 实体类类型>类
dao层继承BaseMapper<实体类类型>类
@TableName
描述:表名注解,标识实体类对应的表
使用位置:实体类
@TableId
描述:主键注解
使用位置:实体类主键字段
@TableField
描述:字段注解(非主键)
@TableLogic
描述:表字段逻辑处理注解(逻辑删除)
@Data
@Accessors(chain = true)
@TableName("tab_user")
public class User {
/**
* type = IdType.ASSIGN_ID 默认值,表示当前主键值由MybatisPlus生成,采用雪花算法
* IdType.AUTO MybatisPlus不再生成主键,而是由数据库生成
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String userId;
private String name;
private Integer age;
@TableField("email")
private String userEmail;
private String gender;
//扩容属性,关联属性
//表示当前属性在表中没有对应字段
@TableField(exist = false)
private String genderName;
//标识当前属性对应的逻辑删除标志字段
@TableLogic
private String delFlag;
}
SpringSecurity注解
@EnableWebSecurity
SpringSecurity5.0版本之后,无需配置此注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
开启权限使用注解,配置类或启动类上使用
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityDemoApplication {}
@PreAuthorize
@PreAuthorize 在方法调用前进行权限检查
// 角色检查
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/query")
public String adminQuery(){
return "admin-query";
}
// 权限检查
@PreAuthorize("hasAuthority('sys:query')")
@GetMapping("/query")
public String query(){
return "系统查询";
}
@JsonIgnore
json忽略:在进行json字符串转换时忽略此方法
/**
* json忽略:在进行json字符串转换时忽略此方法
*/
@JsonIgnore
public String getPassword() {
return this.userpwd;
}
分布式
@EnableDubbo
开启dubbo注解扫描
@SpringBootApplication
@EnableDubbo//开启dubbo注解扫描
public class DubboxProviderApp {
public static void main(String[] args) {
SpringApplication.run(DubboxProviderApp.class,args);
}
}
@Reference
从zookeeper注册中心中找对应的Service类
@RestController
public class HelloController {
//@Autowired//从ioc容器中找HelloService
@Reference//从zookeeper中找HelloService
private HelloService helloService;
@RequestMapping("/hello")
public String hello(){
System.out.println(helloService.getClass()+"----------------");
return helloService.hello();
}
}
SpringCloud
SpringCloud
测试
@RunWith
@SpringBootTest
编写测试类时,如果需要使用springboot的环境的话。就使用以上两个注解
//测试时使用springboot的环境
@RunWith(SpringJUnit4ClassRunner.class)
//springboot启动类
@SpringBootTest(classes = SpringBootApp.class)
public class Test {}
nacos组件
@EnableDiscoveryClient
向注册中心注册该服务,并可以获取其他服务的调用地址
作用在启动类上
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigApp {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApp.class,args);
}
}
@RefreshScope
重新从BeanFactory获取一个新的实例(该实例使用新的配置)
@RestController
@RefreshScope //重新从BeanFactory获取一个新的实例(该实例使用新的配置)
public class ConfigController {}
ribbon组件
@LoadBalanced
添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取注册中心的所有可用服务,通过获取到的服务信息(ip,port)替换 serviceId 实现负载请求。
@LoadBalanced //开启ribbon负载均衡,默认时轮询策略
public RestTemplate restTemplate(){
return new RestTemplate();
}
Feign组件
@EnableFeignClients
开启feign注解的扫描
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients//开启feign注解的扫描
public class FeignConsumerApp {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApp.class,args);
}
}
@FeignClient(“feign-provider”)
处理此类请求的服务名
以下注解含义仅在使用了@FeignClient注解后表示,并要将参数明文指定出来
@RequestMapping
拼接请求路径
@PathVariable
路径方式发送请求参数
@RequestParam
?拼接方式发送请求参数
@RequestBody
将对象转化为Json串形式发送请求参数
如:实体类(pojo),数组,集合
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
@RequestMapping("/getUserById/{id}")//拼接url
public User getUserById(@PathVariable("id") Integer id);//restful形式拼接参数
@RequestMapping("/deleteUserById")//拼接url
User deleteUserById(@RequestParam("id") Integer id);//?形式拼接参数,?id=250
@RequestMapping("/addUser")
User addUser(@RequestBody User user);//pojo--->json
}
fastDFS组件
@EnableMBeanExport
解决bean重复的问题
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {
}
RabbitMQ组件
@Component
public class Recver {
/**
* 监听者接收消息三要素:
* 1、queue
* 2、exchange
* 3、routing key
*/
@RabbitListener(bindings = {@QueueBinding(
value = @Queue(value = "springboot_queue",durable = "true"),
exchange = @Exchange(value = "springboot_exchange",type = ExchangeTypes.TOPIC),
key = {"*.*"}
)})
public void listen(String msg, Channel channel, Message message){
System.out.println("接收到消息:"+msg);
try {
// 手动ACK
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@RabbitListener
:方法上的注解,声明这个方法是一个消费者方法,需要指定下面的属性:bindings
:指定绑定关系,可以有多个。值是@QueueBinding
的数组。@QueueBinding
包含下面属性:value
:这个消费者关联的队列。值是@Queue
,代表一个队列exchange
:队列所绑定的交换机,值是@Exchange
类型key
:队列和交换机绑定的RoutingKey