-
为什么要使用SpringBoot
因为spring,springmvc需要使用大量的配置文件
还需要配置各种对象,把使用的对象放入到spring容器中才能使用对象
需要了解其他框架配置的规则。
-
SpringBoot相当于是不需要配置文件的spring+springmvc,常用的框架和第三方库都已经配置好了。SpringBoot开发效率高
第一章 xml和javaConfig
1.1 javaConfig
-
javaconfig:使用java类作为xml配置文件的替代,是配置spring容器的纯java方式。在这个java类中可以创建java对象,把对象放入到spring容器中
-
使用两个注解:
- @Configuration :放在一个类的上面,表示这个类是作为配置文件使用的。
- @Bean:生命对象,把对象注入到容器中
-
package 中vo表示valueObject,ValueObject的值(状态)一旦创建以后就不会改变了
-
//使用javaConfig来代替bean标签 /* * Configuration:当前类是作为配置文件使用的,就是用来配置容器的 * 位置:在类的上面 * * javaConfig这个类就相当于beans.xml * */ @Configuration public class JavaConfig { /* * 创建方法,方法返回值是对象,在方法的上面加@Bean标签 * 方法的返回值和对象就会注入到容器中 * @Bean:把对象注入到spring容器中,作用相当于<bean> * 位置:方法上面 * */ @Bean(name="id")//name指定对象的id public Student createStudent(){ Student s1 = new Student(); s1.setName("lisi"); s1.setAge(30); return s1; } } //测试 @Test public void testJavaConfig(){ ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class); Student student = (Student) ac.getBean("createStudent");//可以用方法名,也可以用id System.out.println(student.getName()); }
1.2 @ImportResource:
作用是导入其他的xml配置文件,等于在xml中的
<import resource="其他配置文件"/>
//如果以前的spring用的是xml,现在想改成javaConfig方式,那么使用@ImportResource标签
@Configuration
@ImportResource(value="location"/{"location","location","location"})
1.3 @PropertySource:
读取properties属性配置文件,使用属性配置文件可以实现外部化配置,在程序代码之外提供数据
步骤:
- 在resource目录下,创建properties文件,使用k=v的格式提供数据
- 在PropertyResource指定properties文件的位置
- 使用@Value(value=“${key}”)获得值
//在vo中使用properties赋值
@Component("tiger") //创建对象的名字
public class Tiger{
@Value(value = "${tiger.name}") //值来自application.properties|yml配置文件
private String name;
@Value(value = "${tiger.age}")
private Integer age;
}
//在javaConfig中使用@PropertyResource标签
@Configuration
@PropertySource(value="classpath:config.properties")
@ComponentScan(value = "com.bjpowernode.vo")
public class JavaConfig{
@Bean
public Tiger createTiger(){
return new Tiger();
}
}
//test
@Test
public void testTiger(){
ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
Tiger tiger = (Tiger)ac.getBean("createTiger");
System.out.println(tiger)
}
第二章 SpringBoot入门
springboot的核心还是IOC容器
特点:
-
内嵌了tomcat,jetty,undertow
-
提供了starter起步依赖,简化应用的配置
比如mybatis框架,需要在Spring项目里,配置mybatis对象SqlSessionFactory,Dao的代理对象。
但在springboot项目中,在pom.xml里面,加入一个mybatis-spring-boot-starter依赖,就可以完成上述的配置
-
自动配置spring和第三方库
-
提供健康检查,统计外部化配置
-
不用生成代码。不用使用xml,做配置
2.1 创建springboot项目
第一种方式,使用spring提供的初始化器,就是用向导创建springboot应用,选择https://starter.spring.io
第二种方式,使用spring提供的初始化器,就是用向导创建springboot应用,选择https://starter.springboot.io,这个地址是国内的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWbICASD-1666596104892)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220503090945351.png)]
或者在游览器中使用地址,配置好后,会生成一个项目文件,下载下来,导入项目即可
第三种方式是使用maven项目,自己配置pom.xml文件
2.2 @SpringBootApplication注解
@SpringBootApplication
是复合注解,由以下注解符合完成
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
@SpringBootApplication
public class Ch03SpringbootMvcApplication {
public static void main(String[] args) {
SpringApplication.run(Ch03SpringbootMvcApplication.class, args);
}
}
其中:
- @SpringBootConfiguration的定义程序:
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
说明,有@SpringBootConfiguration注解的类,可以当作配置文件来用,可以使用@Bean声明对象,注入到容器
-
@EnableAutoConfiguration
启动自动配置,把java对象配置好,注入到spring容器中。例如可以把mybatis的对象创建好,放入到容器中
-
@ComponentScan
组件扫描器,找到注解,根据注解的功能创建对象,给属性赋值等等 组件扫描器默认扫描的包:@ComponentScan所在的类所在的包和子包
2.3springboot的配置文件
主要有两种格式,一种是properties,另一种yml格式,现在主推yml
配置文件名:application(名字不能自定义)
扩展名有:properties(k=v),yml(k:v)
例1:application.properties
#设置端口号
server.port=8082
#设置上下文路径:contextpath
server.servlet.context-path=/myboot
例2:application.yml
server:
port: 8082
servlet:
context-path: /myboot
当同时有yml和properties时,默认用properties
2.4 多环境配置
在实际开发的过程中,项目会经历多个阶段(开发->测试->上线),每个阶段的配置也会不同,,例如端口号,上下文根,数据库等。为了方便在不同环境之间切换,springboot提供了多环境。
为每个环境创建一个配置文件,命名必须以application-环境标识.properties|yml
创建开发环境的配置文件:application-dev.properties|yml
创建测试环境的配置文件:application-test.properties|yml
创建上线环境的配置文件:application-online.properties|yml
对于多个配置文件,如何切换选择?
在applicaiton.properties配置文件中配置:
spring.profiles.active=dev #就会自动指定application-dev.yml配置文件了
或者在application.yml配置文件中配置:
spirng:
profiles:
active: dev
2.5 @Value
@Value(“${key}”),key来自application.properties(yml)
@Controller
public class HelloController {
@Value("${server.port}")
private Integer port;
@Value("${server.servlet.context-path}")
private String context_path;
@Value("${school.name}")
private String name;
@Value("${school.website}")
private String site;
@RequestMapping("/data")
@ResponseBody
public String queryData(){
return "schoolname="+name+",site="+site+",访问地址="+context_path+",端口号="+port;
}
}
2.6 @ConfigurationProperties
@ConfigurationProperties 将整个文件映射成一个对象,用于自定义配置项比较多的情况
#配置文件
#自定义key-value
school.name=powernode
school.website=www.bjpowernode.com
school.addr=beijing
//vo包中
@ConfigurationProperties(prefix = "school") //会去配置文件中找前缀为school的对应值,一一赋值
public class SchoolInfo {
private String name;
private String website;
private String addr;
2.7 SpringBoot中使用JSP
SpringBoot框架并不推荐使用jsp,默认本身并不支持jsp,需要配置才能使用jsp。
使用jsp需要配置:
1)加入一个处理jsp的依赖,负责编译jsp文件
<dependceny>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependceny>
2)如果需要使用servlet,jsp,jstl的功能
<dependceny>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependceny>
<dependceny>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependceny>
<dependceny>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependceny>
3)创建一个存放jsp的目录,一般叫做webapp
index.jsp
4)需要在pom.xml指定文件编译后的存放目录
META-INF/resources #名字千万不能错
5)创建Controller,访问jsp
6)在application.properties文件中配置视图解析器
2.8 SpringBoot中使用ApplicationContext
在main()方法中SpringApplication.run()方法获取返回的spring容器对象,再获取业务bean进行调用。
SpringApplication.run(Ch06SpringbootJspApplication.class, args);
//run方法的原型
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
ConfigurableApplicationContext是接口,继承了ApplicationContext,所以它也是容器
使用方式:
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void sayHello(String name) {
System.out.println("执行了业务方法的sayHello:"+name);
}
}
@SpringBootApplication
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Ch07SpringbootContainerApplication.class, args);
UserService service = (UserService) ctx.getBean("userService");
service.sayHello("zhangsan");
}
//最终的执行结果:
>>>执行了业务方法的sayHello:zhangsan
2.9 CommandLineRunner接口
假如需要在容器启动后执行一些内容,比如读取配置文件,数据库连接之类的。SpringBoot提供了两个接口来帮助我们实现这种需求。着两个接口分别为CommandLineRunner和ApplicationRunner。他们的执行实际为容器启动完成的时候。
这两个接口的不同之处在于:ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中的run方法的参数为String数组。
public class Application implements CommandLineRunner {
public static void main(String[] args) {
System.out.println("容器对象创建之前");
//创建容器对象
SpringApplication.run(Application.class,args);
System.out.println("容器对象创建之后");
}
@Override
public void run(String... args) throws Exception {
System.out.println("在容器对象创建好后,执行的方法");
}
}
//执行结果:
>>>
容器对象创建之前
在容器对象创建好后,执行的方法
容器对象创建之后
第三章 web组件
3.1 拦截器
拦截器是SpringMVC中的一种对象,能拦截对Controller的请求
拦截器框架中有系统的拦截器,还可以自定义拦截器。实现对请求预先处理。
实现自定义的拦截器:
-
创建类实现springmvc框架的HandlerInterceptor接口
public interface HandlerInterceptor{ default boolean preHandler(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception{ return true; } default void postHandler()HttpServletRequest request,HttpServletResponse response,Object handler,@Nullable ModelAndView modelAndView) throws Exception{} default void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,@Nullable Exception ex) throws Exception{} }
-
需要在SpringMVC的配置文件中,声明拦截器
<mvc:interceptors> <mvc:interceptor> <mvc:path="url"/> <bean class="拦截器类的全限定名称"/> </mvc:interceptor> </mvc:interceptors>
在是springboot中注册拦截器
//首先定义拦截器
public class LoginInceptor implements HandlerInterceptor {
/*
* @param request
* @param response
* @param handler 被拦截的控制器对象
* @return boolean
* true:通过拦截
* false:请求阶段
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行了拦截器的prehandler");
return true;
}
}
//然后将拦截器加入到容器中
@Configuration
public class MyAppConfig implements WebMvcConfigurer {
/*添加拦截器对象,注入到容器中*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//创建拦截器对象
LoginInceptor inceptor = new LoginInceptor();
//指定拦截的请求uri地址
String [] path = {"/user/**"};
//指定不拦截的请求uri地址
String [] path2 = {"/user/login"};
registry.addInterceptor(inceptor).addPathPatterns(path).excludePathPatterns(path2); //拦截哪些请求,不拦截哪些请求
}
}
//最后访问这些地址时,就会有的拦截有的不拦截了。
3.2 Servlet
在springboot框架中使用Servlet对象:
使用步骤:
-
创建Servlet类。创建类继承HttpServlet
-
注册Servlet,让框架能找到Servlet
//创建Servlet //首先创建package和类名 pulic MyServlet{ public doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{ resp.setContextType("text/html;charset=utf-8"); PrintWriter pw = resp.getWriter(); pw.println("msg"); pw.flush(); pw.close(); } } //然后加入到容器中 @Configuration public WebApplicationConfig{ @Bean public ServletRegistrationBean servletRegistrationBean(){ //两个参数,第一个是自定义的Servlet,第二个是请求的地址 ServletRegistraionBean bean = new ServletRegistrationBean(new MyServlet,"/myservlet"); return bean; //第二种方式注册Servlet ServletRegistraionBean bean = new ServletRegistrationBean(); bean.setServlet(new MyServlet()); bean.addUrlMapping("/login"."/test"); return bean } }
3.3 过滤器Filter
Filter是Servlet规范中的中过滤器,可以处理请求,对请求的参数,属性进行调整。
实现步骤:
-
创建Filter对象
-
用FilterRegistrationBean来注册Filter
//创建过滤器 class MyFilter implements Filter{ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("执行了过滤器"); filterChain.doFilter(servletRequest,servletResponse); } } //注册过滤器 @Configuration public class WebApplicationConfig { @Bean public FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new MyFilter()); //指定过滤器 bean.addUrlPatterns("/myfilter"); //指定过滤地址 return bean; } }
3.3.1 字符集过滤器
CharacterEncodingFilter:解决post请求中乱码的问题
在springmvc框架中,是在web.xml中注册过滤器的。
//在springboot中配置字符集过滤器
@Configuration
public class WebApplicationConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
filter.setForceEncoding(true);
bean.setFilter(filter);
bean.addUrlPatterns("/*");
System.out.println("执行了字符集过滤器");
return bean;
}
}
#在springboot中默认已经配置了CharacterEncodingFilter。编码默认ISO-8859-1
#设置enabled=false 作用是关闭系统配置好的默认过滤器,使用自定义的过滤器
server.servlet.encoding.enabled=false
既然springboot中默认已经配置了CharacterEncodingFilter。编码默认ISO-8859-1,可以直接修改默认编码。
#开启系统配置好的默认过滤器,默认就是开启
server.servlet.encoding.enabled=true
#指定使用的编码方式
server.servlet.encoding.charset=utf-8
#强制request,response都使用charset属性的值
server.servlet.encoding.force=true
第四章 ORM操作Mysql
通过Springboot+Mybatis实现对数据库的操作,ORM object relation mapping 对象关系映射
使用步骤:
-
mybatis起步依赖:完成mybatis对象自动配置,对象放在容器中
-
pom.xml指定把src/main/java目录中的xml文件包含奥classpath中
-
创建实体类Student
-
创建dao接口StudentDao,创建一个学生查询方法
/* * @Mapper:告诉Mybatis这是dao接口,创建此接口的代理对象 * 位置:在类的上面 * */ @Mapper public interface StudentDao { Student selectById(@Param("stuId") Integer id); }
-
创建dao接口对应的Mapper文件,xml文件,写sql语句
-
创建Service层对象,创建StudentService接口和实现类,调用dao对象的方法,完成数据库的操作
-
创建Controller对象,访问Service
-
写application.properties文件,配置数据库连接信息
#连接数据库,mysql驱动新版的驱动类 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=Syp960722..
4.1 @Mapper注解
@Mapper:放在dao接口的上面,每个接口都需要使用这个注解
/*
* @Mapper:告诉Mybatis这是dao接口,创建此接口的代理对象
* 位置:在类的上面
* */
@Mapper
public interface StudentDao {
Student selectById(@Param("stuId") Integer id);
}
4.2 @MapperScan注解
主类上添加注解包扫描:
//@MapperSca这个注解会扫描所有此包下的文件并把他们当作dao接口
@SpringBootApplication
@MapperScan("com.bjpowernode.dao","com.bjpowernode.mapper")
public class Ch13SpringbootMapperApplication {
public static void main(String[] args) {
SpringApplication.run(Ch13SpringbootMapperApplication.class, args);
}
}
4.3 将Mapper和Dao接口分开存储
分开后需要在配置文件中指定mapper的位置
#可以将mapper文件放到resource文件下新建的mapper文件夹下。
#指定mapper文件地址
mybatis.mapper-location=classpath:mapper/*.xml
#开启mybatis日志
mybatis.configuration.log-imp=org.apache.ibatis.logging.stdout
4.4 springboot中的事务
Spring框架中的事务:
-
管理事务的对象:事务管理器(接口,接口有额还能多实现类)
例如:使用jdbc或mybatis访问数据库,使用的事务管理器:DataSourceTransactionManager
-
声明式事务:在xml配置文件或者使用注解说明事务控制的内容
控制事务:隔离界别,传播行为,超时时间
-
事务处理方式:
1)Spring框架中的@Transactional
2)aspectj框架可以在xml配置文件中,声明事务控制的内容
SpringBoot中使用事务:上述两种方式都可以
1)在业务方法的上面加入@Transactional,加入注解后,方法有事务功能了
2)明确的在著启动类的上面,加入@EnableTransactionManager
4.4.1 mybatis反向工程
通过一个GeneratorMapper.xml配置文件自动生成mapper文件,mapper的接口文件和实体类。
步骤:
-
加入反向工程的插件
<plugin> <!--mybatis代码自动生成插件--> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.6</version> <configuration> <!--配置文件的位置--> <configurationFile>GeneratorMapper.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin>
-
配置generatorMapper.xml配置文件
<!--该文件与src目录同一目录下--> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 指定连接数据库的 JDBC 驱动包所在位置,指定到你本机的完整路径 --> <classPathEntry location="D:\java\tools\mysql-connector-java-8.0.28.jar"/> <!-- 配置 table 表信息内容体,targetRuntime 指定采用 MyBatis3 的版本 --> <context id="tables" targetRuntime="MyBatis3"> <!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 --> <commentGenerator> <property name="suppressAllComments" value="true"/> </commentGenerator> <!-- 配置数据库连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8" userId="root" password="Syp960722.."> </jdbcConnection> <!-- 生成 model 类,targetPackage 指定 model 类的包名, targetProject 指定 生成的 model 放在 idea 的哪个工程下面--> <javaModelGenerator targetPackage="com.bjpowernode.model" targetProject="src/main/java"> <property name="enableSubPackages" value="false"/> <property name="trimStrings" value="false"/> </javaModelGenerator> <!-- 生成 MyBatis 的 Mapper.xml 文件,targetPackage 指定 mapper.xml 文件的 包名, targetProject 指定生成的 mapper.xml 放在 idea 的哪个工程下面 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <!-- 生成 MyBatis 的 Mapper 接口类文件,targetPackage 指定 Mapper 接口类的包 名, targetProject 指定生成的 Mapper 接口放在 eclipse 的哪个工程下面 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.bjpowernode.dao" targetProject="src/main/java"> <property name="enableSubPackages" value="false"/> </javaClientGenerator> <!-- 数据库表名及对应的 Java 模型类名 --> <table tableName="student" domainObjectName="Student" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> </context> </generatorConfiguration>
-
在idea右侧的maven中的插件部分执行generator的生成命令即可
4.4.2 使用事务
/*
* @EnableTransactionManagement:启用事务管理机制
* */
@SpringBootApplication
@MapperScan(basePackages = "com.bjpowernode.dao")
@EnableTransactionManagement
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
@Service
public class StudentServiceImpl implements StudentService {
@Resource
private StudentMapper studentMapper;
/*
* @Transactional:表示方法有事务支持
* 默认:使用库的隔离级别,REQUIRED传播行为:超时时间-1
* 抛出运行时异常,回滚事务
* */
@Transactional
@Override
public int addStudent(Student student) {
System.out.println("业务方法addStudent");
int row = studentMapper.insert(student);
System.out.println("执行sql语句");
//抛出一个运行时异常,目的是回滚事务
// int m =10/0;
return row;
}
}
第五章 接口架构风格——RESTful
这里的接口不是interface,而是API :应用程序接口
接口:可以指访问servlet,controller的url,调用其他程序的函数
架构风格:api组织方式
例如:http://localhost:9002/mytrans/some?id=15&name=zhangsan&age=20 就是一个架构风格
而用RESTful风格则http地址为:http://localhost:9002/mytrans/some/15/zhangsan/20
在地址上提供了访问的资源名称some,在其后使用了get方式传递参数。
5.1 REST架构风格
REST:Representational State Transfer,简称REST,表现层状态转移
REST是一种风格,但不是标准
表现层状态转移:
表现层激素hi视图层,显示资源的,通过视图页面,jsp等等显示操作资源的结果
状态:资源变化(比如name=zhangsan&age=20,就可以知道改变后的结果是加入了一条name是张三,age是20的数据 )
转移:资源可以变化的。资源能创建,new状态,资源创建后可以查询资源,能看到资源的内容,资源内容可以被修改。
**一句话说明REST:**使用url表示资源,使用http动作操作资源。
用REST表示资源和对资源的操作。在互联网中,表示一个资源或者操作。
资源用url表示。
GET:查询资源 – sql select
处理单个资源:
http://localhost:9002/mytrans/student/1001 //student是指定操作资源,是student表
处理多个资源:
http://localhost:9002/mytrans/student/1001/1002
POST:创建资源 – sql update
http://localhost:9002/mytrans/student/1002
在post请求中传递数据
<form action="http://localhost:9002/mytrans/student" method="post">
姓名:<input type="text" name="name"/>
年龄:<input type="text" name="age"/>
</form>
PUT:更新资源 – sql update
<form action="http://localhost:9002/mytrans/student/1" method="post"> <!--1表示要更新的是谁-->
姓名:<input type="text" name="name"/>
年龄:<input type="text" name="age"/>
<input type="hidden" name="_method" value="PUT"/>
</form>
DELETE:删除资源 – sql delete
<a href="http://localhost:9002/mytrans/student/1">删除1的数据</a>
5.2 注解
@PathVariable:从url中获取数据
@GetMapping:支持get请求方式,等同于@RequestMapping(method=RequestMenthod.GET)
@PostMapping:支持post请求方式,等同于@RequestMapping(method=RequestMenthod.POST)
@PutMapping:支持put请求方式,等同于@RequestMapping(method=RequestMethod.PUT)
@DeleteMapping:支持delete请求方式,等同于@RequestMapping(method=RequestMethod.DELETE)
@RestController:复合注解,是@Controller和ResponseBody组合
在类的上面使用@RestController,表示当前累着的所有方法都加入了@ResponseBody
@RestController
public class MyRestController {
/*
* @PathVariable:获取url中的数据
* 属性:value,路径变量名
* 位置:放在控制器方法的形参前面
* http://localhost:8080/myboot/student/1001
* {stuId}会获取1001,@PathVariable会把stuId的值赋给后面的stuId
* */
@GetMapping("/student/{stuId}")
public String queryStudent(@PathVariable(value = "stuId") Integer stuId){
return "学生Id为:"+stuId;
}
@PostMapping("/student/{name}/{age}")
public String createStudent(@PathVariable("name") String name,
@PathVariable("age") Integer age){
return "创建资源的名字为"+name+",年龄为"+age;
}
/*
* 当路径形变量名和形参名一样,@PathVariable中的value可以省略
* */
@PutMapping("student/{stuId}/{age}")
public String modifyStudent(@PathVariable Integer stuId,
@PathVariable Integer age){
return "更新资源,执行put请求方式:id="+stuId+",age="+age;
}
@DeleteMapping("student/{stuId}")
public String removeStudent(@PathVariable Integer stuId){
return "删除资源,执行delete,stuId="+stuId;
}
}
//post提交页面
<form method="post" action="/student/zhangsan/20">
<input type="submit" value="提交">
</form>
5.3 在页面中或者ajax中,支持put,delete请求
在springmvc中有一个过滤器,支持post请求转为put,delete请求
springmvc中需要在web.xml文件中启用这个过滤器,在spring中则已经启用了,只需要在配置文件中说明即可
org.springframework.web.filter.HiddenHttpMethodFilter
实现步骤:
-
application.properties(yml):开启使用HiddenHttpMethodFilter过滤器
spring.mvc.hiddenmethod.filter.enabled=true
-
在请求页面中,包含_method参数,值为put,delete,表示希望将post转为的请求类型。但表面上还是post请求方式
<form action="student/test" method="post"> <input type="hidden" name="_method" value="put"/> <input type="submit" value="测试请求方式" </form>
第六章 Springboot集成Redis
Redis是一个中间件,是一个独立的服务器
java中的客户端:jedis,lettuce,redisson
Spring,Springboot中有一个RedisTemplate,处理和redis交互。
RedisTemplate使用lettuce客户端库
<!--redis起步依赖:直接在项目中使用RedisTemplate(StringRedisTemplate)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
data-redis使用的是 lettuce 客户端库
在程序中使用RedisTemplate类的方法操作redis数据,实际就是调用的lettuce客户端中的方法
@Controller
public class RedisController {
/*
* 注入RedisTemplate
* RedisTemplate 泛型
* RedisTemplate<String,String>
* RedisTemplate<Object,Object>
*
* 注意:RedisTemplate对象的名称 redisTemplate,不要改;
* */
@Resource
private RedisTemplate redisTemplate;
//添加数据到redis
@RequestMapping("/redis/addString")
@ResponseBody
public String addToRedis(String name,String value){
//操作Redis中string类型的数据,先获得ValueOperations对象
ValueOperations valueOperations = redisTemplate.opsForValue();
//添加数据到redis
valueOperations.set("myname","lisi");
return "向redis添加string类型数据";
}
//从redis获取数据
@RequestMapping("/redis/queryFromRedis")
@ResponseBody
public String queryFromRedis(String name){
ValueOperations valueOperations = redisTemplate.opsForValue();
String value= (String) valueOperations.get(name);
return "从redis中获取数据"+value;
}
}
6.1 StringRedisTemplate和RedisTemplate
StringRedisTemplate:把k,v作为String处理,使用的是String的序列化,可读性好
RedisTemplate:把k,v经过了序列化存储到redis。k,v是序列化后的内容,不能直接识别
//序列化
@RequestMapping("/redis/addstr")
@ResponseBody
public String addString(String k,String v){
//使用RedisTemplate序列化
// 设置 key 使用String序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置value的序列化
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.opsForValue().set(k,v);
return "key, value 的序列化";
}
//使用json序列化,把java对象转为json对象
@PostMapping("/redis/addjson")
public String addJson(){
Student student = new Studnet(1001,"zhangsan",20);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JackSon2JsonRedisSerializer(Student.class));
redisTemplate.opsForValue.set("mystudent",student)
}
//反序列化
@PostMapping("/redis/getjson")
public String addJson(){
Student student = new Studnet(1001,"zhangsan",20);
redisTemplate.setKeySerializer(new StringRedisSerializer());
//这里会自动反序列化
Object obj = redisTemplate.setValueSerializer(new JackSon2JsonRedisSerializer(Student.class));
redisTemplate.opsForValue.get("mystudent");
}
第七章 Springboot集成Dubbo
7.1 公共接口项目
//实体类
public class Student implements Serializable {
private static final long serialVersionUID = -2639080719916610531L;
private Integer id;
private String name;
private Integer age;
//接口类
public interface StudentService {
Student queryStudent(Integer id);
}
7.2 服务提供者
- 添加依赖项
<!--加入接口项目-->
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>ch17-interface-api</artifactId>
<version>1.0.SNAPSHOT</version>
</dependency>
<!--在springboot中加入dubbo依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!--在springboot中加入zookeeper依赖
这个依赖里包含两个依赖:
1.curator
2.zookeeper
-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.8</version>
<type>pom</type>
</dependency>
-
实现接口中的方法,暴漏服务提供者
//使用dubbo中的注解暴露服务 @DubboService(interfaceClass = StudentService.class,version = "1.0",timeout = 5000) public class StudentServiceImpl implements StudentService { @Override public Student queryStudent(Integer id) { Student student = new Student(); student.setId(1); student.setName("zhangsan"); student.setAge(20); return student; } }
-
配置信息
#配置服务名称dubbo:application name="名称" spring.application.name=studentservice-provider #配置扫描的包,扫描@DubboService dubbo.scan.base-packages=com.bjpowernode.service #配置dubbo协议 #dubbo.protocol.name=dubbo #dubbo.protocol.port=20880 #注册中心 dubbo.registry.address=zookeeper://localhost:2181
-
在springboot主程序加入注解
//@EnableDubbo包括@EnableDubboConfig和@DubboComponentScan @SpringBootApplication @EnableDubbo public class Ch17ServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(Ch17ServiceProviderApplication.class, args); } }
-
<!--日志依赖多次添加会报错,应该排除一下--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>2.7.8</version> <type>pom</type> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
7.3 服务消费者
-
添加依赖
<!--dubbo依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <!--注册中心--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>2.7.8</version> <type>pom</type> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <!--公共项目,服务接口--> <dependency> <groupId>com.bjpowernode</groupId> <artifactId>ch17-interface-api</artifactId> <version>1.0.SNAPSHOT</version> </dependency>
-
消费者消费服务
//@RestController是Response和controller注解的合体,需要依赖spring-boot-starter-web @RestController public class DubboController{ //注入服务接口,如果不加interfaceClass,默认为下面的StudentService类型 @DubboInference(interfaceClass=StudentService.class,version="1.0") @DubboInference(version="1.0") private StudentService service; @RequestMapping("/query") public String queryStudent(Integer id){ Student stu = service.qeruyStudent(id); return stu.toString(); } }
-
配置文件
#消费者名称 dubbo.application.name=consumer-dubbo #注册中心 dubbo.registry.address=zookeeper://localhost:2181
-
springboot主程序文件
//不要忘了EnableDubbo注解 @SpringBootApplication @EnableDubbo public class Ch17ServiceConsumerApplication { public static void main(String[] args) { SpringApplication.run(Ch17ServiceConsumerApplication.class, args); } }
第八章 springboot打包
8.1 springboot打包为war
-
在pom.xml中的build部分指定打包后的名字
<build> <finalName>myboot</finalName> </build>
-
打包后的war需要部署在独立的servlet上,而不是springboot内嵌的servlet,所以需要主启动类继承SpringbootServletInitializer
继承了SpringBootServletInitializer就可以使用外部tomcat。
8.2 springboot打包为jar
打包jar,有jsp文件时,必须指定maven-plugin插件的版本为1.4.2.RELEASE
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
第九章 Thymeleaf 模板
9.1 Thymeleaf
Thymeleaf是一个模板引擎,采用java语言开发的,基于HTML的。
模板是做视图层工作的,显示数据的。
Java生态下的模板引擎有:Thymeleaf,Freemaker,Velocity,Beetl等。
springboot使用Thymeleaf来代替jsp
9.2 thymeleaf的配置信息(大多是默认)
#在开发阶段,关闭模板缓存,让修改立即生效
spring.thymeleaf.cache=false
#编码格式
spring.thymeleaf.encoding=utf-8
#模板的类型(默认为html,模板是html文件)
spring.thymeleaf.mode=HTML
#模板的前缀和后缀
spring.thymeleaf.prefix=classpath:/templates
spring.thymeleaf.suffix=.html
9.3 表达式
-
标准变量表达式
语法:${key}
作用:获取key对应的文本数据,key是request作用域中的key,使用request.setAttribute(),model.addAttribute()
在页面中的html标签,使用th:text="${key}"来获取数据
<div style="margin-left: 400px"> <p th:text="${stu.getName}">名字</p> <p th:text="${stu.getAge}">年龄</p> </div>
-
选择变量表达式(星号变量表达式)
语法:*(key)
作用:获取这个key对应的数据,*(key)需要和th:object这个属性一起使用
目的:简单获取对象的属性值
<div th:object="${stu}"> <p th:text="*{getName}">名字</p> <p th:text="*{getAge}">年龄</p> </div>
-
链接表达式
语法:@{url}
作用:表示链接,可以
<script src="...">,<link href="...">,<a href="...">,<form acion="...">,<img src="...">
<h3>链接绝对地址</h3> <a th:href="@{http://www.baidu.com}">链接到百度</a> <h3>链接相对地址</h3> <a th:href="@{/tpl/queryAccount}">相对地址没有参数</a> <h3>链接相对地址,使用字符串链接传递参数</h3> <a th:href="@{'/tpl/queryAccount?id='+${userId}}">获取model中数据</a> <h3>推荐使用的传参方式</h3> <a th:href="@{/tpl/queryAccount(id=${userId})}">获取model中数据</a> <h3>传递多个参数</h3> <a th:href="@{/tpl/queryAccount(id=${userId},name=${userName})}">获取model中数据</a>
9.4 属性
属性是放在html元素中的,就是html元素的属性,加入了th前缀,属性的作用不变,加入th,属性的值就由模板引擎处理了,在属性可以使用变量表达式
例如:
<form action="/loginServlet" method="post"></form>
<form th:action="/loginServlet" th:method="${methodAttr}"></form>
th:action
th:method
th:href
th:src
th:text
th:style
th:value
th:each
9.5 循环
List循环和Array循环
<div th:each="集合循环成员,循环的状态变量:${key}">
<p th:text="${集合循环成员}"></p>
</div>
<div th:each="user,userStat:${userList}">
<p th:text="${userStat.index}">当前循环的下标</p>
<p th:text="${userStat.count}">当前循环的下标+1</p>
<p th:text="${userStat.size}">循环的大小</p>
<p th:text="${user.id}"></p>
</div>
Map循环
<div th:each="map,userStat:${myMap}">
<p th:text="${map.key}"></p>
<p th:text="${map.value.id}"></p>
<br/>
<hr/>分割线
</div>
9.6 th:if 和th:unless
<div th:if="${10>0}">显示文本内容</div>
<div th:unless="${10 < 0}">显示文本内容</div>
空字符串为真
null为假
9.7 th:switch
<div th:switch="${sex}">
<p th:case="m">显示男</p>
<p th:case="f">显示女</p>
</div>
9.8 th:inline 内联
th:inline 有三个取值类型(text,javascript和none)
-
内联text:在html标签外,获取表达式的值
<div th:inline="text"> <!--可以省略th:inline--> <p>显示姓名是:[[${key}]]</p> </div> <p>显示姓名是:[[${key}]]</p>
-
内联javascript
<script type="text/javascript" th:inline="javascript"> var myname = [[${name}]] var myage = [[${age}]] </script>
9.9 字面量
1. 文本字面量
用单引号''包围起来的字符串为文本字面量
<p th:text="'城市是'+${city}+' 用户登录'+${islLogin}"></p>
其中,'城市是'和' 用户登录'就是文本字面量
2. 数字字面量
<p th:if="10>5"></p>
10和5就是数字字面量
3. 布尔字面量
<p th:if="${isLogin== true}"></p>
4. null字面量
<p th:if="${isLogin== null}"></p>
5.
9.10 字符串的连接
<p th:text="'城市是'+${city}+' 用户登录'+${islogin}"></p>
<p th:text="|城市是${city},用户登录${isLogin}|"></p>
9.11 运算符
算术运算符:+-*/%
关系运算符:>,<,>=,<=,(gt,lt,ge,le)
相等判断:==,!=,(eq,ne)
三元运算符
<p th:text="${sex=='m'?(isLogin?'男已经登录':'男没有登录'):'女'}"></p>
性别是男? 是的话判断是否登录,不是为女
9.12 Thymeleaf基本对象
模板引擎提供了一组内置的对象,这些内置的对象可以直接在模板中使用,这些对象由#开始引用。
-
#request 表示 HttpServletRequest
<div style="margin-left: 400px"> getRequestURL=<span th:text="${#request.getRequestURL()}"></span> getRequestURI=<span th:text="${#request.getRequestURI()}"></span> getQueryString=<span th:text="${#request.getQueryString()}"></span> getContextPath=<span th:text="${#request.getContextPath()}"></span> getServerName=<span th:text="${#request.getServerName()}"></span> getServerPort=<span th:text="${#request.getServerPort()}"></span> </div>
-
#session 表示 HttpSession 对象
-
session 表示 HttpSession 对象
model.addAttribute("modelData","modelData");
request.setAttribute("requestData","requestData");
request.getSession().setAttribute("requestSessionData","requestSessionData");
//直接使用session
session.setAttribute("sessionData","sessionData");
<div style="margin-left: 400px">
<p th:text="${modelData}"></p>
<p th:text="${#request.getAttribute('requestData')}"></p>
<p th:text="${#session.getAttribute('requestSessionData')}"></p>
<p th:text="${session.get('sessionData')}"></p>
</div>
9.13 Thymeleaf内置工具类
-
#dates
<p th:text="${dates.format(mydate)}"></p> <p th:text="${dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}"></p> <p th:text="${dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}"></p> <p th:text="${dates.year(mydate)}"></p> <p th:text="${dates.month(mydate)}"></p> <p th:text="${dates.mothName(mydate)}"></p> <p th:text="${dates.createNow()}"></p>
-
#numbers
数字格式化 <p th:text="${#numbers.formatCurrency(mynum)}"></p> 数字货币格式化 <p th:text="${#numbers.formatDecimal(mynum,5,2)}"></p> 5位,2位小数
-
#strings
<p th:text="${#strings.toUpperCase(mystr)}"></p> <p th:text="${#strings.indexOf(mystr,'power')}"></p> <p th:text="${#strings.subStrings(mystr,start,end)}"></p> 不包括end <p th:text="${#strings.concat(mystr,'otherstr')}"></p>
-
#lists
<p th:text="${#lists.size(mylist)}"></p> <p th:if="${#lists.contains(mylist,'a')}"></p> <p th:if="${#lists.isEmpty(mylist)}"></p>
-
null处理
<p th:text="${zoo?.dog?.name}"></p> 如果zoo为null,就不取,如果dog为null,就不取
9.14 自定义模板
模板是内容复用,定义一次,在其他的模板文件中多次使用。
定义语法:
th:fragment="模板自定义名称"
<div th:fragment="head">
<p>
</p>
</div>
引用模板:
1) ~{templatename :: selector}
templatename: 模板文件名称
selector自定义模板名称
2) templatename :: selector
templatename: 模板文件名称
selector自定义模板名称
对于使用模板,有包含模板(th:include),插入模板(th:insert)
<div th:insert="~{head :: top}">
<就会把模板内容替代这部分内容/>
</div>
<div th:include="~{head :: top}">
</div>
<模板内容会替代上面的所有内容/>
第十章 总结
10.1 注解
Spring+SpringMVC+SpringBoot
创建对象:
@Controller:类上,创建控制器对象,注入到容器
@RestController : 类上,Response和Controller的复合
@Service : 业务层的实现类上
@Repository:放在dao层的实现类上。但一般不用,因为使用Mybatis,mybatis通过代理自动生成dao对象。
@Component : 将创建对象放入容器
赋值:
@Value("value"):简单类型的赋值,在属性上
@Value("lisi")
private String name
还可以使用@Value获取配置文件的数据(properties或yml)
@Value("${server.port}")
private Integer port
@Autowired:引用类型赋值自动注入,支持byName,byType,默认是byType。放在属性上面,也可以放在构造方法上面,推荐后者。
@Qualifer : 引用类型赋值,使用byName方式
@Autowired和Qualifer都是Spring提供的
@Resource : 来自jdk中的定义,Javax.annotation。 实现引用类型自动注入,支持byName,byType,默认byName,失败后会用byType。
其他:
@Configuration : 放在类上,表明是个配置类,,相当于xml文件
@Bean : 放在方法上面,把方法返回值放入容器
@ImportResource : 加载其他xml配置文件,把文件中的对象注入到spring容器
@PropertySource : 读取其他的properties属性配置文件
@ComponentScan : 扫描器,指定包名,扫描注解
@Responsebody : 放在方法上面,表示返回的是数据,不是视图
@Requestbody : 把请求体中的数据读取出来,转为java对象使用
@ControllerAdvice : 控制器增强,放在类上面,表示此类提供了方法,可以对Controller增强功能
@ExceptionHandler : 处理异常,放在方法上面
@Transacal : 处理事务,放在service实现类的public方法上,表示此方法有事务
springboot中使用的注解
@SpringbootApplication : 放在启动类上,,包含了@springbootconfiguration,@EnableAutoConfiguration,@ComponentScan
Mybatis相关注解
@Mapper : 放在类上,让Mybatis找到接口,创建它的代理对象
@MapperScan : 放在主类上,指定扫描包,把包中所有接口都创建代理对象,并注入到容器中
@Param : 放在dao接口的方法的形参前面,作为命名参数使用的。
Dubbo注解
@DubboService : 在提供者端使用的,暴露服务,放在接口实现类上面
@DubboReference : 在消费者端使用,引用远程服务,放在属性上面
@EnableDubbo : 放在主类上面,表示当前引用启动Dubbo功能。
me :: selector}
templatename: 模板文件名称
selector自定义模板名称
2) templatename :: selector
templatename: 模板文件名称
selector自定义模板名称
对于使用模板,有包含模板(th:include),插入模板(th:insert)
<模板内容会替代上面的所有内容/>
# 第十章 总结
## 10.1 注解
Spring+SpringMVC+SpringBoot
```java
创建对象:
@Controller:类上,创建控制器对象,注入到容器
@RestController : 类上,Response和Controller的复合
@Service : 业务层的实现类上
@Repository:放在dao层的实现类上。但一般不用,因为使用Mybatis,mybatis通过代理自动生成dao对象。
@Component : 将创建对象放入容器
赋值:
@Value("value"):简单类型的赋值,在属性上
@Value("lisi")
private String name
还可以使用@Value获取配置文件的数据(properties或yml)
@Value("${server.port}")
private Integer port
@Autowired:引用类型赋值自动注入,支持byName,byType,默认是byType。放在属性上面,也可以放在构造方法上面,推荐后者。
@Qualifer : 引用类型赋值,使用byName方式
@Autowired和Qualifer都是Spring提供的
@Resource : 来自jdk中的定义,Javax.annotation。 实现引用类型自动注入,支持byName,byType,默认byName,失败后会用byType。
其他:
@Configuration : 放在类上,表明是个配置类,,相当于xml文件
@Bean : 放在方法上面,把方法返回值放入容器
@ImportResource : 加载其他xml配置文件,把文件中的对象注入到spring容器
@PropertySource : 读取其他的properties属性配置文件
@ComponentScan : 扫描器,指定包名,扫描注解
@Responsebody : 放在方法上面,表示返回的是数据,不是视图
@Requestbody : 把请求体中的数据读取出来,转为java对象使用
@ControllerAdvice : 控制器增强,放在类上面,表示此类提供了方法,可以对Controller增强功能
@ExceptionHandler : 处理异常,放在方法上面
@Transacal : 处理事务,放在service实现类的public方法上,表示此方法有事务
springboot中使用的注解
@SpringbootApplication : 放在启动类上,,包含了@springbootconfiguration,@EnableAutoConfiguration,@ComponentScan
Mybatis相关注解
@Mapper : 放在类上,让Mybatis找到接口,创建它的代理对象
@MapperScan : 放在主类上,指定扫描包,把包中所有接口都创建代理对象,并注入到容器中
@Param : 放在dao接口的方法的形参前面,作为命名参数使用的。
Dubbo注解
@DubboService : 在提供者端使用的,暴露服务,放在接口实现类上面
@DubboReference : 在消费者端使用,引用远程服务,放在属性上面
@EnableDubbo : 放在主类上面,表示当前引用启动Dubbo功能。