因为spring springMVC 需要使用大量的配置文件,还需要配置各种对象,需要将使用的对象放入到spring容器中才能使用对象,
需要了解其他框架的配置规则
springBoot就相当于 不需要配置文件的spring + springMVC,常用的框架和第三方库已经配置好了,直接使用即可
使用springBoot开发效率高
使用javaConfig这种java类替代xml配置文件,是配置spring容器的纯java的方式。在这个类中可以创建java对象,
把对象放入spring容器中
要是用这个代替xml配置文件,需要使用以下两个注解:
@Configuration:放在一个类上面,表示这个类是作为配置文件使用的
@Bean:声明对象,把对象注入到容器中,作用相当于Bean标签,@Bean(name="Student") name属性是对象的名称,
相当于bean标签中的id属性,如果不指定对象的名称,默认是方法名
@ImportResource:作用是导入其他的xml配置文件,等同于xml配置文件中
这个标签。在需要使用的javaConfig类上边加这个注解 @ImportResource(value="classpath:xxx.xml"),如果有
多个配置文件需要导入,则可以 @ImportResource(value={"classpath:xxx.xml","classpath:aaa.xml"})
@PropertyResource:用来读取properties属性配置文件
使用@PropertyResource(value="xxx.properties")读取配置文件信息的时候,下边必须加
@ComponentScan(basePackages="com.ww.bean")来指定扫描哪些包下的类(这些类要使用配置文件中的信息)
创建一个普通的maven项目,然后自己添加依赖
复合注解:由以下三个注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
(1)@SpringBootConfiguration
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
说明:使用了@SpringBootConfiguration注解标注的类,可以作为配置文件使用,可以使用@Bean声明对象,注入到容器中
(2)@EnableAutoConfiguration
启用自动配置,把java对象配置好,注入到spring容器中。例如可以把mybatis的对象创建好放入到容器中
(3)@ComponentScan
组件扫描器,找到注解,根据注解的功能创建对象,给属性复制等。默认扫描的包:@ComponentScan所在的类所在的包及其子包
k=v
(1)设置端口号和应用的上下文
#设置端口号
server.port=8080
#设置访问应用的上下文路径
server.servlet.context-path=/study
#激活使用哪个配置文件
spring.profiles.active=application-dev.yml
k: v
:后边必须加一个空格
server:
port: 8080
servlet:
context-path: /study2
#激活使用哪个配置文件
spring:
profiles:
active: application-dev.yml
有开发环境 测试环境 上线的环境,每个环境有不同的配置信息,例如端口号、上下文件、数据库url、用户名、密码等
使用多环境配置文件,可以方便切换不同的配置
使用方式:创建多个配置文件,名称规则:application-环境名称.properties
创建开发环境配置环境:application-dev.properties(application-dev.yml)
创建测试的配置环境:application-test.properties(application-test.yml)
(1)@Value
application.properties配置文件中写:
school.name=郫县男子职业技术学校
school.website=www.uestc.com
school.address=成都郫都区
site=哈哈哈
@Controller
public class HelloController {
@Value("${school.name}")
private String name;
@Value("${school.website}")
private String website;
@Value("${school.address}")
private String address;
@Value("${site}")
private String site;
@RequestMapping("/data")
@ResponseBody
public String data(){
return "name="+name+" website="+website+" address="+address+" site="+site;
}
}
(2)@ConfigurationProperties
application.properties配置文件中写:
school.name=郫县男子职业技术学校
school.website=www.uestc.com
school.address=成都郫都区
site=哈哈哈
@Component
@ConfigurationProperties(prefix = "school")
public class School {
private String name;
private String website;
private String address;
private String site;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSite() {
return site;
}
public void setSite(String site) {
this.site = site;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", website='" + website + '\'' +
", address='" + address + '\'' +
", site='" + site + '\'' +
'}';
}
}
@Controller
public class HelloController {
@Resource
private School school;
@RequestMapping("/school")
@ResponseBody
public String school(){
return school.toString();
}
}
这两个接口都有一个run方法,执行时间在容器对象创建好后,自动执行run()方法,可以完成自定义的在容器对象创建好的一些操作
@FunctionalInterface
public interface CommandLineRunner {
void run(String... args) throws Exception;
}
@FunctionalInterface
public interface ApplicationRunner {
void run(ApplicationArguments args) throws Exception;
}
拦截器是springMVC中的一种对象,能拦截对controller的请求。
拦截器框架中有系统的拦截器,还可以自定义拦截器,实现对请求的预先处理。
如果要自定义拦截器的话:
(1)需要创建类实现HandlerInterceptor接口
(2)需要在springBoot中注册拦截器
//注册拦截器
@Configuration
public class MyAppConfig implements WebMvcConfigurer {
//添加拦截器对象,注入到容器中
@Override
public void addInterceptors(InterceptorRegistry registry) {
//创建拦截器对象
HandlerInterceptor interceptor=new LoginInterceptor();
//指定拦截的请求uri地址
String path []={"/user/**"};
//指定不拦截的地址
String excludePath []={"/user/login"};
registry.addInterceptor(interceptor).addPathPatterns(path).excludePathPatterns(excludePath);
}
}
(1)创建Servlet类,继承HttpServlet
(2)注册Servlet
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//使用HttpServletResponse输出数据,应答结果
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.print("执行的是servlet");
out.flush();
out.close();
}
}
@Configuration
public class ServletConfig {
//定义方法,注册Servlet对象
@Bean
public ServletRegistrationBean servletRegistrationBean(){
//第一个参数是 Servlet对象,第二个参数是url地址
ServletRegistrationBean bean = new ServletRegistrationBean(new MyServlet(), "/servlet");
return bean;
}
}
Filter是Servlet规范中的过滤器,可以处理请求,对请求的参数、属性进行调整。经常在过滤器中处理字符编码
//自定义过滤器
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("执行了MyFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
}
//注册Filter
@Configuration
public class MyFilterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new MyFilter());
bean.addUrlPatterns("/user/*");
return bean;
}
}
characterEncodingFilter:解决post请求中乱码的问题
(1)自己写过滤器
//配置字符集过滤器
@Configuration
public class ServletConfig {
//注册过滤器
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean reg = new FilterRegistrationBean();
//使用框架中的过滤器类
CharacterEncodingFilter filter = new CharacterEncodingFilter();
//指定使用的编码方式
filter.setEncoding("utf-8");
//指定request response都使用encoding的值
filter.setForceEncoding(true);
reg.setFilter(filter);
//指定过滤的url地址
reg.addUrlPatterns("/*");
return reg;
}
}
//修改application.properties,让自定义的过滤器起作用
#关闭系统中配置好的过滤器,使用自定义的CharacterEncodingFilter
server.servlet.encoding.enabled=false
(2)修改application.properties文件【推荐】
#指定使用的编码方式
server.servlet.encoding.charset=utf-8
#强制request response 都使用charset属性的值
server.servlet.encoding.force=true
需要在application.properties配置文件中配置各种信息
server.port=8080
server.servlet.context-path=/orm
#连接数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=*******
#指定mapper文件的位置
mybatis.mapper-locations=classpath:mapper/*.xml
#指定mybatis的日志
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
@Mapper//告诉mybatis这是dao接口,创建此接口的代理对象
public interface StudentDao {
Student selectById(Integer id);
}
在每个接口上都加入@Mapper注解,十分不方便,可以采用在主程序上加@MapperScan(basePackages = "指定的包")来扫描
@SpringBootApplication
@MapperScan(basePackages = "com.cw.dao")
public class Springboot02Application {
public static void main(String[] args) {
SpringApplication.run(Springboot02Application.class, args);
}
}
(1)管理事务的对象:事务管理器(接口,接口有很多实现类)
例如:使用mybatis访问数据库,使用的事务管理器:DataSourceTransactionMapper
(2)声明式事务:在xml配置文件或者使用注解说明使用事务控制的内容
控制事务:隔离级别、传播行为、超时时间
(3)事务的处理方式:
spring框架中的 @Transactional(在业务方法的上边加入这个注解,方法就有事务功能了)
aspectj框架可以在xml配置文件中,声明事务控制的内容
在业务方法的上边加入这个注解,方法就有事务功能了
在主启动类上加@EnableTransactionManager
@Service
public class DogServiceImpl implements DogService {
@Resource
private DogDao dogDao;
@Transactional//开启事务
@Override
public int addDog(Dog dog) {
System.out.println("业务方法addDog");
int ret = dogDao.insertDog(dog);
System.out.println("执行sql语句");
//抛出一个运行时异常,目的是回滚事务
//int m=10/0;
return ret;
}
}
指的是API的组织方式
(1)
一种互联网软件架构设计的风格,但他并不是标准,它只是提出了一组客户端和服务器交互时的架构理念和设计原则
使用URL表示资源,使用http动作操作资源
(2)
基于这种理念和原则设计的接口可以更简洁,更有层次。
(3)
在URL中使用名词表示资源以及访问资源的信息,在URL中使用"/"来分隔对资源的信息:
GET:查询资源
http://localhost:8080/myboot/student/1001/1 处理单个资源:单数形式
http://localhost:8080/myboot/students/1001/1 处理多个资源:使用复数形式
POST:创建资源
http://localhost:8080/myboot/student
PUT:更新资源
DELETE:删除资源
删除1001数据
(4)需要的分页、排序等参数,依然放在URL的后面,例如:
http://localhost:8080/myboot/students?page=1&pageSize=10
(1)@PathVariable
从URL中获取数据
(2)@GetMapping
支持get请求方式,等同于@RequestMapping(method=RequestMethod.GET)
(3)@PostMapping
支持post请求方式,等同于@RequestMapping(method=RequestMethod.PUT)
(4)@PutMapping
支持put请求方式,等同于@RequestMapping(method=RequestMethod.PUT)
(5)DeleteMapping
支持delete请求方式,等同于@RequestMapping(method=RequestMethod.DELETE)
(6)@RestController
符合注解,是@Controller和@ResponseBody组合。在类的上面使用@RestController,表示当前类的所有方法都加入了
@ResponseBody
@RestController
public class MyRestController {
/**
* 查询id=1001的学生
* /student/1001
* {stuId}:定义路径变量
* @PathVariable : 获取url中的数据
* 属性: value=路径变量名, value可以省略 直接写路径变量名
* 位置: 放在控制器方法的形参前面
* @return
*/
@GetMapping("/student/{stuId}")
public String queryStudent(@PathVariable(value = "stuId") Integer studentId){
return "查询学生studentId="+studentId;
}
/**
* 创建资源 post请求
* http://localhost:8080/orm/student/张三/12
*/
@PostMapping("/student/{name}/{age}")
public String createStudent(@PathVariable("name") String name,
@PathVariable("age") Integer age){
return "创建资源 student: name="+name+" age="+age;
}
/**
* 更新资源
* 当路径变量名和形参名一致时,@PathVariable中的value属性可以省略
*/
@PutMapping("/student/{id}/{age}")
public String modifyStudent(@PathVariable Integer id,
@PathVariable Integer age){
return "更新资源,执行put请求: id="+id+" age="+age;
}
@DeleteMapping("/student/{id}")
public String removeStudentById(@PathVariable Integer id){
return "删除资源,执行delete: id="+id;
}
}
(1)作用:
在springMVC中有一个过滤器 HiddenHttpMethodFilter ,把请求中的post请求转为put delete请求
(2)步骤:
在application.properties中开启使用HiddenHttpMethodFilter过滤器
在请求页面中,包含_method参数,它的值是put delete,发起这个请求的方式是post
#启用支持put delete
spring.mvc.hiddenmethod.filter.enabled=true
<form action="student/test" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="测试put请求方式">
</form>
<form action="student/test" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="测试delete请求方式">
</form>
(1)Redis是一个NoSQL数据库,常用作缓存使用(cache)。Redis是一个中间件(一个独立的服务器)
(2)先从Redis中查找数据,没有找到再从数据库中查找,然后加入Redis
(3)Redis的数据类型:string hash set zset list
(4)java中著名的Redis客户端:jedis lettuce Redisson
(5)spring/springBoot中有一个RedisTemplate(StringRedisTemplate),处理和redis交互
(6)服务端启动后不要关闭,客户端访问redis中的数据
<!--redis起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
#指定redis (host ip)
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=123456
StringRedisTemplate:把 k,v 都是作为String处理,使用的是String的序列化,可读性好
RedisTemplate:把 k,v 经过了序列化存储到redis, k,v 是序列化的内容,不能直接识别到。默认使用的是JDK的序列化
@RestController
public class RedisController {
/**
* 注入RedisTemplate
*
* RedisTemplate 泛型:
* RedisTemplate
* RedisTemplate
@Resource
private RedisTemplate redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
//添加数据到redis
@PostMapping("/addString")
public String addToRedis(String name,String value){
//操作redis中的string类型的数据,要先获取ValueOperations对象
ValueOperations valueOperations = redisTemplate.opsForValue();
//添加数据到redis
valueOperations.set("myName","张三");
return "向redis中添加string类型的数据";
}
//使用rest 添加数据到redis
@PostMapping("/add/{key}/{value}")
public String add(@PathVariable String key,
@PathVariable String value){
//操作redis中的string类型的数据,要先获取ValueOperations对象
ValueOperations valueOperations = stringRedisTemplate.opsForValue();
//添加数据到redis
valueOperations.set(key,value);
return "使用stringRedisTemplate";
}
//从redis中获取数据
@GetMapping("/getKey")
public String getData(String key){
//操作redis中的string类型的数据,要先获取ValueOperations对象
ValueOperations valueOperations=redisTemplate.opsForValue();
Object o = valueOperations.get(key);
return "key:"+key+" value:"+o;
}
//使用rest 从redis中获取数据
@GetMapping("/get/{key}")
public String get(@PathVariable String key){
//操作redis中的string类型的数据,要先获取ValueOperations对象
ValueOperations valueOperations=stringRedisTemplate.opsForValue();
Object o = valueOperations.get(key);
return "key:"+key+" value:"+o;
}
}
/**
* 设置 RedisTemplate 序列化
* 可以设置key的序列化,可以设置value的序列化
* 可以同时设置key和value的序列化
*/
@PostMapping("/addStr")
public String addString(String k,String v){
//使用RedisTemplate
//设置key使用String的序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置value使用String的序列化
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.opsForValue().set(k,v);
return "定义RedisTemplate对象的key value的序列化";
}
/**
* 使用json序列化,把java对象转为json存储
*/
@PostMapping("/addJson")
public String addJson(){
Student student = new Student();
student.setId(1001);
student.setName("张三");
student.setAge(190);
redisTemplate.setKeySerializer(new StringRedisSerializer());
//把值作为json序列化
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Student.class));
redisTemplate.opsForValue().set("myStudent",student);
return "json的序列化";
}
链接: https://github.com/apache/dubbo-spring-boot-project
独立的maven项目:定义了接口和数据类
public class Student implements Serializable {
private static final long serialVersionUID=1234567899876543211L;
private Integer id;
private String name;
private Integer age;
}
public interface StudentService {
Student queryStudent(Integer id);
}
创建的springboot项目
(1)pom.xml
com.cw
spring-boot-dubbo
1.0-SNAPSHOT
org.apache.dubbo
dubbo-spring-boot-starter
3.1.1
org.apache.dubbo
dubbo-dependencies-zookeeper
3.1.1
pom
org.slf4j
slf4j-log4j12
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
实现接口
/**
* 使用dubbo中的注解暴露服务
*/
//@Component //可以不加
@DubboService(interfaceClass = StudentService.class,version = "1.0",timeout = 5000)
public class StudentServiceImpl implements StudentService {
@Override
public Student queryStudent(Integer id) {
Student student = new Student();
if (1001==id){
student.setId(1001);
student.setName("1001-张三");
student.setAge(20);
} else if (1002==id) {
student.setId(1002);
student.setName("1002-李四");
student.setAge(200);
}
return student;
}
}
(3)application.properties
# 配置服务名称
spring.application.name=StudentService-provider
# 配置扫描的包,扫描@DubboService
dubbo.scan.base-packages=com.cw.service
# 配置dubbo协议
#dubbo.protocol.name=dubbo
#dubbo.protocol.port=12345
## 注册中心
dubbo.registry.address=zookeeper://localhost:2181
(4)启动类
@SpringBootApplication
@EnableDubbo //启用dubbo
public class SpringBootServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootServiceProviderApplication.class, args);
}
}
(1)pom.xml
com.cw
spring-boot-dubbo
1.0-SNAPSHOT
org.apache.dubbo
dubbo-spring-boot-starter
3.1.1
org.apache.dubbo
dubbo-dependencies-zookeeper
3.1.1
pom
org.slf4j
slf4j-log4j12
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
(2)创建controller
@RestController
public class DubboController {
/**
* @DubboReference:引用远程服务,把创建好的代理对象,注入给studentService
* 不使用interfaceClass,默认就是引用类型的数据类型
*/
//@DubboReference(interfaceClass = StudentService.class,version = "1.0")
@DubboReference(version = "1.0")
private StudentService studentService;
@GetMapping("/query")
public String queryStudent(){
Student student = studentService.queryStudent(1001);
return "调用远程接口,获取对象: "+student;
}
}
(3)application.properties
#指定服务名称
spring.application.name=consumer-application
#指定注册中心
dubbo.registry.address=zookeeper://localhost:2181
(1)@Controller:放在类的上面,创建控制对象,注入到容器中
(2)RestController:放在类的上面,创建控制对象,注入到容器中。作用:复合注解,是@Controller和@ResponseBody,
使用这个注解类,里面的控制器方法的返回值都是数据
(3)@Service:放在业务层的实现类的上面,创建service对象,注入到容器中
(4)@Repository:放在dao层的实现类上面,创建dao对象,放入到容器中。我们现在因为使用MyBatis框架代理生成dao对象,
所以没有使用这个注解。
(5)@Component:放在类上面,创建此类的对象,放入到容器中
(1)@Value:简单类型的赋值,例如:在属性的上面使用 @Value("张思") private String name。
还可以使用@Value获取配置文件(application.properties)中的数据 @Value("${server.port}") private int port
(2)@Autowired:给引用类型自动注入的,支持byName byType,默认是byType。放在属性的上面,也可以放在构造
方法的上面,推荐放在构造方法的上面
(3)@Qualifer:给引用类型赋值,使用byName
(4)@Resource:来自JDK的定义,实现引用类型的自动注入,支持byName byType,默认是byName,如果byName
失败,再使用byType注入,在属性的上面使用
(1)@Configuration:放在类的上面,表示这是一个配置类,相当于xml配置文件作用
(2)@Bean:放在方法的上面,把方法的返回值对象,注入到spring容器中
(3)@ImportResource:加在其他的xml配置文件,把文件中的对象注入到spring容器中
(4)@PropertySource:读取其他的properties属性的配置文件
(5)@ComponentScan:扫描器,指定包名,扫描注解
(6)@ResponseBody:放在方法的上面,表示方法的返回值是数据,不是视图
(7)@RequestBody:把请求中的数据读取出来,转为java对象使用
(8)@ControllerAdvice:控制器增强,放在类上面,表示此类提供了方法,可以对controller增强功能
(9)@ExceptionHandler:处理异常的,放在方法上面
(10)@Transcational:处理事务的,放在service实现类的public方法上面,表示此方法有事务
(1)@Mapper:放在类上面,让MyBatis找到接口,创建他的代理对象
(2)@MapperScan:放在主类的上面,指定扫描的包,把这个包中所有的接口都创建代理对象。对象注入到容器中
(3)@Param:放在dao接口的方法的形参前面,作为命名参数使用的
(1)@DubboService:在提供者端使用的,暴露服务的,放在接口的实现类上面
(2)@DubboReference:在消费者端使用,引用远程服务,放在属性上面使用
(3)@EnableDubbo:放在主类上面,表示当前引用启用Dubbot功能