SpringBoot项目笔记

5 篇文章 0 订阅
3 篇文章 0 订阅

Bean初始化调用

  Spring容器底层使用反射机制创建Bean实例,因此可在Bean的空参构造器中执行某些初始化操作,但如果在空参构造器中调用属性注入相关的内容,将出现异常:

@RestController
public class UserController {
    /* Spring容器先创建Bean实例,再使用Bean的实例进行注入 */
    @Autowired
    private UserService userService;
    /* Bean实例的创建在调用空参构造器之后完成 */
    public UserController() {
        /* 空参构造器中不可调用属性注入相关的内容 */
        userService.service();
    }
}

  实际上Bean的空参构造器中不可调用任何与属性注入相关的内容,因为Spring容器必须先创建Bean实例,才能使用Bean的实例进行属性注入,而Bean实例的创建在调用空参构造器之后完成。
  Spring提供了Bean的初始化调用方式:

/* InitializingBean接口中提供了Bean初始化调用的方法,
   实现此接口后,Spring容器将在Bean初始化后调用该方法 */
@RestController
public class UserController implements InitializingBean {
    @Autowired
    private UserService userService;
    /* 在afterPropertiesSet()中调用属性注入相关的内容 */
    @Override
    public void afterPropertiesSet() throws Exception {
        userService.service();
    }
}

自定义SpringBoot配置属性

  SpringBoot的配置文件支持自定义属性,作用是可以通过Spring容器将配置文件中的属性值注入到Bean类的指定属性中,因此需要有对应的Bean类加载自定义属性,并指定Bean类与配置文件中的属性对应关系。

自定义配置属性

application.yml

# ...
# 自定义配置属性
com.xxx.user:
  # 注意":"与值之间必须有空格!
  username: Tony
  password: 123456
# ...  

自定义Bean

  Bean类需要使用@Component等注解将实例交由Spring容器创建。

package com.xxx;
/* 使用相应的注解修饰类,声明类为Bean类 */
@Component
public class User {
    /* Bean的属性应与配置属性对应一致 */
    private String username;
    private String password;
    public String getUserName() {return username;}
    public void setUserName(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword() {this.password = password;}
}

加载配置属性

  SpringBoot不能自动将配置文件中的属性值注入到对应的Bean属性中,需要使用额外的注解实现。

@Value

  @ValueSpring提供的属性注入注解,作用是在Spring容器创建Bean类实例时,将配置文件中的指定属性值注入到Bean的属性中,@Value注解的定义为:

@Target({ElementType.FIELD,ElementType.METHOD, 
         ElementType.PARAMETER,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
    String value();
}

  @Value修饰属性:

package com.xxx;
@Component
public class User {
    /* "${}"中传入配置文件中的属性 */
    @Value("${com.xxx.user.username}")
    private String username;
    @Value("${com.xxx.user.password}")
    private String password;
    
    public String getUserName() {return username;}
    public void setUserName(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword() {this.password = password;}
}

  @Value修饰方法:

package com.xxx;
@Component
public class User {
    private String username;
    private String password;
    
    public String getUserName() {return username;}
    
    /* @Value修饰setter时将读取参数列表,并将指定的属性注入给参数(参数名不一定与属性名相同) */
    @Value("${com.xxx.user.username}")
    public void setUserName(String username) {this.username = username;}
    
    @Value("${com.xxx.user.password}")
    public String getPassword() {return password;}
    
    public void setPassword() {this.password = password;}
}

  在其它类中注入Bean:

@Component
public class Test {
    private User user;
    /* 自动装配Bean */
    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
}

@ConfigurationProperties

  @ConfigurationPropertiesSpring提供的注解,用于使用前缀查找配置文件中的自定义对象(属性集),并将配置文件中的同名配置属性注入到Bean的属性中。@ConfigurationProperties的定义为:

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
    /* 与prefix属性作用一致 */
    @AliasFor("prefix")
    String value() default "";
    /* 前缀,与value属性作用一致 */
    @AliasFor("value")
    String prefix() default "";
    
    /* 属性忽略 */
    boolean ignoreInvalidFields() default false;
    boolean ignoreUnknownFields() default true;
}

  @ConfigurationProperties修饰类:

package com.xxx;
@Component
/* 通过前缀与Bean类中的属性名查找配置文件中的配置属性 */
@Configuration("com.xxx.user")
public class User {
    /* 属性名应与配置文件中的配置属性名相同 */
    private String username;
    private String password;
    public String getUserName() {return username;}
    public void setUserName(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword() {this.password = password;}
}

  在其它类中注入Bean:

@Component
public class Test {
    private User user;
    /* 自动装配Bean */
    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
}

前后端数据交互

简单对象类型

示例

  SpringBoot使用JSON字符串接收对象类型的数据:

/* 必须将JSON对象字符串化 */
var user = JSON.stringify({username:"Tony",password:"123456"});
$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    data:user
});

  后台接收数据:

@Controller
public class UserController {
    /* consumes属性指定请求体格式,例如数据类型和编码格式等 */
    @PostMapping(value="test",consumes="application/json;charset=utf-8")
    /* 使用@RequestBody修饰参数用于接收对象 */
    public void test(@RequestBody User user) {
        System.out.println(user);
    }
}

@RequestBody

  @RequestBody用于接收JSON字符串并将其转换为实体类对象,定义为:

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
    /* 指定是否必须提供此请求参数 */
    boolean required() default true;
}

List类型

  前台示例:

/* 必须将JSON对象字符串化 */
var user1 = {username:"Tony",password:"123456"};
var user2 = {username:"Jack",password:"abcded"};
var user3 = {username:"Luis",password:"abc123"};
/* JSON数组的格式是[json1,json2,...],并非{json1,json2,...} */
var users = [user1,user2,user3];
$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    /* 必须将JSON对象字符串化 */
    data:JSON.stringify(users)
});

  或:

/* 必须将JSON对象字符串化 */
var user1 = {username:"Tony",password:"123456"};
var user2 = {username:"Jack",password:"abcded"};
var user3 = {username:"Luis",password:"abc123"};
var users = [];
/* 直接使用数组存储 */
users[0] = user1;
users[1] = user2;
users[2] = user3;
$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    /* 必须将JSON对象字符串化 */
    data:JSON.stringify(users)
});

  后台示例:

@Controller
public class UserController {
    /* consumes属性指定请求体格式,例如数据类型和编码格式等 */
    @PostMapping(value="test",consumes="application/json;charset=utf-8")
    /* 使用@RequestBody修饰参数用于接收对象 */
    public void test(@RequestBody List<User> users) {
        System.out.println(users);
    }
}

Map类型

  前台示例:

/* 必须将JSON对象字符串化 */
var user1 = {username:"Tony",password:"123456"};
var user2 = {username:"Jack",password:"abcded"};
var user3 = {username:"Luis",password:"abc123"};
/* 将需要作为Map的key的值作为JSON的key */
var users = {"Tony":user1,"Jack":user2,"Luis":user3};
$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    /* 必须将JSON对象字符串化 */
    data:JSON.stringify(users)
});

注意事项

JSON字符串

  SpringBoot接收JSON数据时,只能接收JSON字符串而不能接收JSON对象,例如:

$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    /* 不能接收JSON对象 */
    data:{username:"Tony",password:"123456"}
});

多个@RequestBody

  SpringBoot不支持多个@RequestBody修饰的参数,仅转换第一个参数:

/* 仅转换第一个参数 */
public void test(@RequestBody Type1 obj1,
                 @RequestBody Type2 obj2,
                 @RequestBody Type3 obj3) {
    // ...
}

  @RequestBody修饰的参数代表http请求的请求体,而一次请求中只有一个请求体,多个@RequestBody参数不符合实际意义。

请求体类型

  前后台必须明确指定请求体的格式要求,后台:

/* consumes属性指定请求体的格式要求,例如请求体的数据类型和编码格式 */
@PostMapping(value="test",consumes="application/json;charset=utf-8")
public void test(@RequestBody User user) {
    // ...
}

  前台:

$.ajax({
    type:"POST",
    url:"http://localhost:8080/test",
    async:true,
    /* 数据类型必须与后台一致 */
    dataType:"json",
    /* 必须指定此请求头 */
    headers:{"Content-Type":"application/json;charset=utf-8"},
    /* 必须将JSON对象字符串化 */
    data:JSON.stringify(users)
});

@Transactional

  @Transactional注解用于数据库访问的事务管理,其定义为:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    /* 指定事务管理器名 */
    @AliasFor("transactionManager")
    String value() default "";
    @AliasFor("value")
    String transactionManager() default "";
    /* 事务的传播行为,取值有:
       Propagation.REQUIRED - 如果有事务则加入事务,没有则新建
       Propagation.NOT_SUPPORTED - 容器不为这个方法开启事务 
       Propagation.REQUIRES_NEW - 不管是否存在事务都创建新的事务,原来的事务挂起,
           新事务执行完成后继续执行原来的事务
       Propagation.MANDATORY - 必须在一个已有的事务中执行,否则抛出异常
       propagation=Propagation.NEVER - 必须在一个没有的事务中执行,否则抛出异常
       propagation=Propagation.SUPPORTS - 如果其他bean调用这个方法,
           在其他bean中声明事务,那就用事务,如果其他bean没有声明事务,那就不用事务. */
    Propagation propagation() default Propagation.REQUIRED;
    /* 用于设置事务的隔离级别 */
    Isolation isolation() default Isolation.DEFAULT;
    /* 用于设置事务的超时时间,为-1表示永不超时 */
    int timeout() default -1;
    /* 是否为只读事务 */
    boolean readOnly() default false;
    /* 指定需要进行回滚的异常数组,当事务方法抛出包含的异常时将执行回滚 */
    Class<? extends Throwable>[] rollbackFor() default {};
    /* 指定需要进行回滚的异常名称数组,当事务方法抛出名称包含的异常时将执行回滚 */
    String[] rollbackForClassName() default {};
    /* 指定不需要进行回滚的异常数组,当事务方法抛出包含的异常时不执行回滚 */
    Class<? extends Throwable>[] noRollbackFor() default {};
    /* 指定不需要进行回滚的异常名称数组,当事务方法抛出名称包含的异常时不执行回滚 */
    String[] noRollbackForClassName() default {};
}

  @Transactional默认只回滚RuntimeExceptionError,设置rollbackFor=Exception.class可使事务在任何异常发生时都回滚。@Transactional不可修饰接口,但可修饰设置了代理的接口,只能修饰权限为public的方法。一般@Transactional用在Service层的方法,因为Service层的方法通常包含一组数据访问操作,符合事务处理的需求。示例:

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    /* 对于没有添加事务管理的方法,出现异常时将不会回滚 */
    /* 重复添加字段要求为unique的值时,第一次操作成功,第二次不成功 */
    public addUser1(User user) {
        userDao.add(user);
        userDao.add(user);
    }
    /* rollbackFor=Exception.class指定任何异常发生都将事务回滚 */
    @Transactional(timeout=10,rollbackFor=Exception.class)
    /* 重复添加字段要求为unique的值时,两个操作都不成功,因为添加了事务管理 */
    public addUser2(User user) {
        userDao.add(user);
        userDao.add(user);
    }
}

普通类中获取HttpSession

  获取方式:

/* 获取ServletRequestAttributes */
ServletRequestAttributes requestAttributes = 
    (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
/* 获取HttpServletRequest */
HttpServletRequest request = requestAttributes.getRequest();
/* 获取HttpSession */
HttpSession session = request.getSession();

/* 获取HttpServletResponse */
HttpServletResponse response = requestAttributes.getResponse();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值