视频出处:动力节点springboot视频教程
为什么要使用Spring Boot?
Spring使用XML作为容器配置文件,在3.0之后加入了JavaConfig,使得可以用java类作为配置文件使用。
这一点就是Spring Boot移除SSM中大量配置文件所用到的重要技术。
JavaConfig:使用java类作为xml配置文件的代替,是配置Spring容器的纯java方法。在这个java类中可以创建java对象,把对象注入Spring容器中。
优点:
①创建maven工程,添加依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- 编译插件 --> <plugin> <artifactId>maven-compiler-plugin</artifactId> <!-- 插件的版本 --> <version>3.5.1</version> <!-- 编译级别 --> <configuration> <source>1.8</source> <target>1.8</target> <!-- 编码格式 --> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build>
②创建数据类
package com.tsccg.pojo; public class Student { private String name; private Integer age; private String sex; //get和set... //toString }
③resources 目录下创建 Spring 的配置文件 :beans.xml
声明一个Student对象:
<bean id="student" class="com.tsccg.pojo.Student"> <property name="name" value="张三"/> <property name="age" value="20"/> <property name="sex" value="男"/> </bean>
单元测试:
/** * 使用xml方式创建对象 */ @Test public void beanTest01() { ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) app.getBean("student"); System.out.println("xml方式创建对象:"+student); }
结果:
xml方式创建对象:Student{name='张三', age=20, sex='男'}
需要使用两个注解:
@Configuration
:放在类上,声明当前类为配置类。@Bean
:放在方法上,将方法返回的对象注入到容器中。创建配置类:
package com.tsccg.javaconfig; import com.tsccg.pojo.Student; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; /** * @Author: TSCCG * @Date: 2021/12/13 18:12 */ @Configuration//声明此类为配置类,在这个类中有很多方法, 方法的返回值是对象。 public class SpringConfig { /** * 创建Student对象并返回 * 通过@Bean注解将对象注入容器,对象默认id为方法名 */ @Bean public Student createStudent() { Student student = new Student(); student.setName("李四"); student.setAge(22); student.setSex("女"); return student; } /** * 自定义Bean对象id */ @Bean(name = "liSiStudent") public Student createStudent2() { Student student = new Student(); student.setName("李四"); student.setAge(22); student.setSex("女"); return student; } }
单元测试:
/** * 使用javaConfig创建Student对象 */ @Test public void beanTest02() { ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class); Student student = (Student) app.getBean("createStudent"); System.out.println("javaConfig方式创建对象:"+student); } /** * 自定义bean对象id */ @Test public void beanTest03() { ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class); Student student = (Student) app.getBean("liSiStudent"); System.out.println("自定义id:"+student); }
结果:
javaConfig方式创建对象:Student{name='李四', age=22, sex='女'} 自定义id:Student{name='李四', age=22, sex='女'}
@ImporResource是在配置类里导入其他的xml配置文件,等同于xml配置的
<import resource="classpath:xxx.xml"/>
用法:
①在beans.xml文件中声明一个Student对象
<bean id="wangWuStudent" class="com.tsccg.pojo.Student"> <property name="name" value="王五"/> <property name="age" value="18"/> <property name="sex" value="女"/> </bean>
②在配置类上添加@ImporResource
注解,导入beans.xml文件
@Configuration @ImportResource(value="classpath:beans.xml")//导入beans.xml配置文件,指定从类路径下导入 public class SpringConfig { ... }
③单元测试
/** * 配置类导入xml配置文件 */ @Test public void beanTest04() { ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class); Student student = (Student) app.getBean("wangWuStudent"); System.out.println("JavaConfig导入xml配置文件:"+student); }
结果:
JavaConfig导入xml配置文件:Student{name='王五', age=18, sex='女'}
④导入多个配置文件
@Configuration @ImportResource(value={"classpath:beans.xml","classpath:applicationContext.xml"}) public class SpringConfig { ... }
@PropertySource用于在配置类里读取properties属性配置文件,等同于xml配置里的:
<context:property-placeholder location="classpath:xxx.properties"/>
用法:
①在resources目录下创建属性配置文件config.properties
dog.name=小哈 dog.type=哈士奇 dog.age=1
②创建数据类
使用@Component注解创建对象并放入容器,使用@Value注解读取配置文件中的数据并注入对象属性
package com.tsccg.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * @Author: TSCCG * @Date: 2021/12/13 19:59 */ @Component("myDog")//创建对象并注入容器中 public class Dog { @Value("${dog.name}")//读取属性配置文件中的数据,注入到对象属性中 private String name; @Value("${dog.type}") private String type; @Value("${dog.age}") private Integer age; @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", type='" + type + '\'' + ", age=" + age + '}'; } }
③修改配置类
1)使用@PropertySource注解读取属性配置文件
2)使用@ComponentScan注解扫描数据类,等同于<context:component-scan base-package="com.tsccg.pojo"/>
@Configuration//声明此类为配置类。 @PropertySource(value="classpath:config.properties")//读取属性配置文件 @ComponentScan(basePackages = "com.tsccg.pojo")//组件扫描器 public class SpringConfig { ... }
④单元测试
/** * @PropertySource 读取属性配置文件 */ @Test public void beanTest05() { ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class); Dog myDog = (Dog) app.getBean("myDog"); System.out.println("外部属性配置文件注入:"+myDog); }
结果:
外部属性配置文件注入:Dog{name='小哈', type='哈士奇', age=1}
Spring Boot是Spring家族的一个成员,可以简化Spring和SpringMVC的使用。核心还是IOC容器。
特性:
翻译:
mybatis-spring-boot-starter
依赖即可。国外地址:https://start.spring.io/
国内地址:https://start.springboot.io/
步骤:
①新建项目
②初始化设置
③添加依赖
④设置项目路径并创建
⑤项目结构
启动类:Application.java
package com.tsccg; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
测试类:ApplicationTests.java
package com.tsccg; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class ApplicationTests { @Test void contextLoads() { } }
⑥项目依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--继承spring-boot-starter-parent,位于仓库中--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!--当前项目的坐标--> <groupId>com.tsccg</groupId> <artifactId>02-springboot-demo-first</artifactId> <version>0.0.1-SNAPSHOT</version> <!--项目描述,可删去--> <name>02-springboot-demo-first</name> <description>Demo project for Spring Boot</description> <!--jdk版本--> <properties> <java.version>1.8</java.version> </properties> <!--依赖,版本为继承的spring-boot-starter-parent指定版本--> <dependencies> <!--web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!--编译插件--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
web起步依赖相关jar:
⑦也可以通过浏览器打开初始化器页面
下载自动生成的项目文件,导入本地即可。
使用Maven向导的方式就是直接创建一个maven项目,按Spring Boot项目结构添加所需文件和配置。
使用Maven创建的好处是可以不用联网。
步骤:
①创建一个空的Maven项目
②修改pom.xml文件
1)添加spring-boot-starter-parent坐标
2)添加web启动依赖及其他配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--添加父坐标--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.tsccg</groupId> <artifactId>03-springboot-demo-second</artifactId> <version>1.0-SNAPSHOT</version> <!--添加其他所需配置--> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!--编译插件--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
③修改项目结构
1)创建启动类Application.java
,加入@SpringBootApplication 注解
package com.tsccg; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
2)在resources目录下创建static
、templates
文件夹,springboot核心配置文件application.properties
3)创建测试类ApplicationTests.java
,加入@SpringBootTest注解
package com.tsccg; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class ApplicationTests { @Test void contextLoads() { } }
在Spring Boot项目中,使用SpringMVC时,不需要提前在配置文件中进行配置,直接使用就行。
步骤:
①基于前面创建的Spring Boot项目,我们直接写一个Controller类:HelloController
②启动Application类的main方法
可以发现内嵌的Tomcat已启动,默认为8080端口。
③在浏览器访问 http://localhost:8080/hello
启动类Application上的@SpringBootApplication注解是Spring Boot项目的重要注解。
其为一个复合注解,内部主要包含@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解:
Spring Boot 的核心配置文件用于配置 Spring Boot 程序。
名字必须以 application
开始,后缀有两种格式:
.properties
:
student.name=张三 student.age=21
.yml
/.yaml
:
#属性与上级属性之间留两个空格,值与前面的冒号之间必须留一个空格 student: name: 张三 age: 21
.properties
文件(默认)基于前面2.3的web例子进行修改。
①修改application.properties属性配置文件,设置Tomcat启动时开放的端口号以及上下文路径
application.properties:
#设置端口号 server.port=8082 #设置上下文路径 server.servlet.context-path=/boot
②启动应用:
③在浏览器访问 http://localhost:8082/boot/hello
.yml
文件(推荐)同基于前面2.3的web例子进行修改。
①对原有的application.properties文件进行删除或修改文件名称
若两种格式的文件同时存在,则优先用application.properties
②在resource目录下创建一个application.yml文件,在其中设置端口号和上下文路径
#设置端口号与上下文路径 #属性与上级属性之间留两个空格,值与前面的冒号之间留一个空格 server: port: 8083 servlet: context-path: /boot2
③启动应用
若配置未生效则用maven执行clean-->install操作。
④在浏览器访问 http://localhost:8083/boot2/hello
在实际开发的过程中,我们的项目会经历很多的阶段(开发->测试->上线),每个阶段的配置也会不同。例如:端口、上下文路径、数据库等。
为了方便在不同的环境之间切换,SpringBoot 提供了多环境配置,具体操作如下:
基于2.3的web项目进行修改。
①分别为开发、测试、生产环境创建一个配置文件
命名必须以application-自定义环境标识.properties|yml
为准
②在application.yml中指定使用哪个环境的配置,如下:
启动应用,在浏览器访问 http://localhost:9081/dev/hello
③修改application.yml,指定为测试环境
重启应用,在浏览器中访问 http://localhost:9082/test/hello
SpringBoot 的核心配置文件中,除了使用内置的配置项之外,我们还可以添加自定义配置项,然后采用@Value或@ConfigurationProperties读取配置项的属性。
用法:@Value("${key}") , key 来自 application.properties(yml)
例子:基于2.3web案例进行修改
①在application.properties核心配置文件中加入内置配置项和自定义配置项
#内置配置项 server.port=8081 server.servlet.context-path=/read #自定义配置项 student.name=张三 student.age=18 wite=www.xxx.com
②修改HelloController
1)添加私有属性并用@Value注解读取application.properties文件的数据进行注入
2)添加处理器方法将属性响应到浏览器
@RestController public class HelloController { @Value("${server.port}") private String port; @Value("${student.name}") private String name; @Value("${student.age}") private Integer age; @Value("${wite}") private String wite; @RequestMapping("/data") public String readData() { return name + "由于年龄未到" + age + ",所以不能从" + port + "端口访问" + wite; } }
③启动应用,在浏览器访问 http://localhost:8081/read/data
@ConfigurationProperties:可以把配置文件中的数据映射为java对象,适用于自定义配置项较多的情况。用在类上或配置类方法上。
属性:prefix,用于匹配配置文件中某些配置项开头的内容,如:指定prefix为student,那么就会匹配student.name、student.age等以student开头的配置项。
prefix可以不指定,如果不指定,那么会去配置文件中寻找与该类的属性名一致的配置项,prefix的作用是区分同名配置。
案例演示:(基于上一个例子)
①创建一个java类Student
1)使用@Component注解创建对象并注入容器
2)使用@ConfigurationProperties注解从配置文件中读取配置数据为该类注入属性
package com.tsccg.pojo; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "student") public class Student { private String name; private Integer age; //get set //toString }
使用ConfigurationProperties 注解,IDEA 会出现一个警告,但是不影响程序的执行。在pom中加入如下依赖后,重启项目即可消除。
<!--处理使用@ConfigurationProperties 注解出现警告问题--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
②创建StudentController类
@RestController public class StudentController { @Resource//自动注入 private Student student; @RequestMapping("/student") public String readStudent() { return student.toString(); } }
③开启应用,在浏览器访问http://localhost:8081/read/student
Spring Boot默认不支持JSP,而是使用模板技术代替jsp。
若要使用jsp需要进行以下配置:
①添加依赖
<!--引入Spring Boot内嵌的Tomcat对JSP的解析包不加解析不了jsp页面--> <!--如果只是使用JSP页面可以只添加该依赖--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!--如果要使用servlet必须添加该以下两个依赖--> <!--servlet依赖的jar包--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!--jsp依赖jar包--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> <!--如果使用 JSTL 必须添加该依赖--> <!--jstl 标签依赖的 jar 包 start--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency>
②指定jsp文件编译后的存放目录
SpringBoot 要求 jsp 文件必须编译到指定的 META-INF/resources 目录下才能访问,否则访问不到。
在pom.xml的build标签配置如下信息
<resources> <resource> <!--源文件位置--> <directory>src/main/webapp</directory> <!--指定编译到 META-INF/resource,该目录不能随便写--> <targetPath>META-INF/resources</targetPath> <!--指定要把哪些文件编译进去,**表示 webapp 目录及子 目录,*.*表示所有文件--> <includes> <include>**/*.*</include> </includes> </resource> <!--把src/main/resources下面的所有文件,都包含到classes目录--> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources>
③在src/main/目录下创建存放jsp文件的目录:webapp ,并在项目中指定为Web Resource Directory,创建一个jsp文件index.jsp
④在index.jsp中获取请求作用域的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${data} </body> </html>
⑤在application.properties配置文件中配置SpringMVC中的视图解析器
server.port=9090 #视图前缀 spring.mvc.view.prefix=/ #视图后缀 spring.mvc.view.suffix=.jsp
⑥创建JspController,返回视图
package com.tsccg.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class JspController { @RequestMapping("/doSome") public String doSome(Model model) { //向请求作用域中放入数据 model.addAttribute("data","Spring Boot整合Jsp"); return "index"; } }
⑦开启应用,访问 http://localhost:9090/doSome
我们点进启动类中SpringApplication的run方法,发现run方法中返回了一个ConfigurationApplicationContext类型对象,继续点开ConfigurationApplicationContext,发现是一个接口,继承了ApplicationContext。
ApplicationContext为Spring的容器对象,通过该对象可以直接获取容器中的Bean对象。
当我们在不想启动整个项目的前提下测试部分代码时,可以通过main方法中的SpringApplication.run()语句获取返回的Spring容器对象,获取业务bean进行调用。
演示:
①创建业务接口 HelloService
package com.tsccg.service; public interface HelloService { void sayHello(String name); }
②创建业务接口实现类 HelloServiceImpl
package com.tsccg.service.impl; import com.tsccg.service.HelloService; import org.springframework.stereotype.Service; @Service(value = "helloService") public class HelloServiceImpl implements HelloService { @Override public void sayHello(String name) { System.out.println("Hello " + name); } }
③在启动类main方法中,获取容器对象,取出业务bean对象调用其方法
@SpringBootApplication public class Application { public static void main(String[] args) { //获取容器对象 ConfigurableApplicationContext app = SpringApplication.run(Application.class, args); //获取业务bean对象 HelloService helloService = (HelloService) app.getBean("helloService"); //调用方法 helloService.sayHello("张三"); } }
④启动应用
开发中可能会有这样的情景:需要在容器启动后执行一些内容,比如读取配置文件,数据库连接之类的。SpringBoot 给我们提供了两个接口来帮助我们实现这种需求,使用任意一个都可以
它们的执行时机为容器启动完成的时候,这两个接口中都有一个 run 抽象方法,我们只需要实现这个方法即可。这两个接口的不同之处在于 :
@FunctionalInterface public interface CommandLineRunner { void run(String... args) throws Exception; } @FunctionalInterface public interface ApplicationRunner { void run(ApplicationArguments args) throws Exception; }
演示使用:
以2.7中的例子为基础,进行修改。
①修改启动类
使启动类实现CommandLineRunner接口,实现其run方法
@SpringBootApplication public class Application implements CommandLineRunner { @Resource private HelloService helloService; 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("容器对象创建好后,执行的方法"); String result = helloService.sayHello("李四"); System.out.println("调用容器对象中的方法:" + result); } }
②开启应用
三个内容:
拦截器是SpringMVC中的一种对象,能够拦截对Controller的请求,实现对请求的预先处理。
①自定义拦截器,实现HandlerInterceptor接口
public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(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:mapping path="拦截的url" /> <bean class="拦截器类全限定名称"/> </mvc:interceptor> </mvc:interceptors>
在Spring Boot中使用拦截器与SpringMVC中使用的步骤大体一致,都是先自定义拦截器,然后将其注册到项目中。
只不过在Spring Boot中要把拦截器注册到@Configuration修饰的配置类中。
具体步骤:
①自定义拦截器
创建java类实现 HandlerInterceptor 接口,实现preHandle方法
package com.tsccg.handlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyLoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("执行了自定义拦截器的preHandle方法"); return true; } }
②注册拦截器
package com.tsccg.config; import com.tsccg.handlerInterceptor.MyLoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * 相当于SpringMVC配置文件 */ @Configuration public class MyAppConfig implements WebMvcConfigurer { /** * 注册拦截器 * @param registry 登记系统中可以使用的拦截器对象 */ @Override public void addInterceptors(InterceptorRegistry registry) { //拦截的url String path = "/user/**"; //放行的url String excludePath = "/user/login"; registry.addInterceptor(new MyLoginInterceptor()) .addPathPatterns(path).excludePathPatterns(excludePath); } }
③创建测试用的Controller
@RestController public class UserController { @RequestMapping("/user/account") public String account() { return "10000"; } @RequestMapping("/user/login") public String login() { return "登录界面"; } }
④启动应用
1)通过浏览器访问受拦截的url: http://localhost:8080/user/account
可见,在发送请求后,后台执行了自定义的拦截器方法
2)通过浏览器访问放行的url: http://localhost:8080/user/login
可见,在发送请求后,后台没有执行拦截器方法
ServletRegistrationBean用来注册Servlet对象
使用步骤:
①创建Servlet
public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.print("使用Servlet对象"); out.flush(); out.close(); } }
②注册Servlet
@Configuration public class MyAppConfig{ /** * 注册Servlet * @return */ @Bean public ServletRegistrationBean servletRegistrationBean() { //ServletRegistrationBean reg = new ServletRegistrationBean(new MyServlet(),"/myServlet"); ServletRegistrationBean reg = new ServletRegistrationBean(); //注册Servlet对象 reg.setServlet(new MyServlet()); //设置请求路径 reg.addUrlMappings("/myServlet"); return reg; } }
③启动应用,在浏览器中访问 http://localhost:8080/myServlet
FilterRegistrationBean 用来注册 Filter 对象
使用步骤:
①自定义过滤器,实现javax.servlet.Filter接口
public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("执行了自定义过滤器,方法:doFilter"); chain.doFilter(request,response); } }
②注册过滤器
@Configuration public class MyAppConfig{ /** * 注册过滤器对象 * @return */ @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean bean = new FilterRegistrationBean(); //注册自定义过滤器对象 bean.setFilter(new MyFilter()); //设置过滤的url bean.addUrlPatterns("/user/*"); return bean; } }
③创建Controller
@RestController public class MyController { @RequestMapping("/user/account") public String userAccount() { return "过滤器使用测试"; } @RequestMapping("/member/account") public String memberAccount() { return "过滤器使用测试2"; } }
④启动应用
1)访问过滤器指定范围内的地址: http://localhost:8080/user/account
2)访问过滤器指定范围外的地址: http://localhost:8080/member/account
CharacterEncodingFilter是框架提供的字符集过滤器,解决post方式请求中文字符乱码的问题。
在通过SpringMVC框架使用该过滤器时,需要在web.xml中注册该过滤器,配置其属性:
<!--注册字符集过滤器--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
使用的方式有两种:
1.在配置类中注册
2.在Spring Boot核心配置文件中设置
步骤:
①创建Servlet,在不设置utf-8的情况下响应中文字符
public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html");//不设置utf-8字符集 PrintWriter out = resp.getWriter(); out.print("====中文测试数据====");//响应中文字符 out.flush(); out.close(); } }
②注册Servlet
@Configuration public class MyAppConfig{ /** * 注册Servlet * @return */ @Bean public ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean bean = new ServletRegistrationBean(new MyServlet(),"/user/inf"); return bean; } }
③开启应用,在浏览器访问 http://localhost:8080/user/inf
可见,响应的中文字符发生乱码。
④在配置类中注册字符集过滤器
@Configuration public class MyAppConfig{ /** * 注册Servlet * @return */ @Bean public ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean bean = new ServletRegistrationBean(new MyServlet(),"/user/inf"); return bean; } /** * 注册过滤器 * @return */ @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean bean = new FilterRegistrationBean(); //创建框架提供的字符集过滤器类 CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("utf-8");//设置encoding属性为utf-8 filter.setForceEncoding(true);//设置请求对象和响应对象的字符编码集与encoding属性一致 bean.setFilter(filter);//注册字符集过滤器 bean.addUrlPatterns("/user/*");//设置过滤的url return bean; } }
⑤在application.properties中添加如下配置
server.servlet.encoding.enabled=false
⑥重启应用,重新访问
Spring Boot 项目默认启用了 CharacterEncodingFilter, 直接在application.properties中设置他的属性就可以:
#设置 spring boot 中 CharacterEncodingFitler 的属性值 server.servlet.encoding.enabled=true server.servlet.encoding.charset=utf-8 #强制 request, response 使用 charset 他的值 utf-8 server.servlet.encoding.force=true
重启应用,重新访问:
对象关系映射(Object Relational Mapping,简称ORM),是一种程序设计技术,用于实现面向对象程序语言里不同类型系统的数据之间的转换。
MyBatis就是ORM的一种,下面将展示在Spring Boot项目中使用MyBatis操作MySQL数据库。
建表:
步骤分析:
其中,创建Dao代理对象的方式有两种:
①创建Spring Boot项目,勾选Web、MyBatis、MySQL Driver起步依赖
②在application.properties中配置数据库连接信息
#项目端口号 server.port=9090 #数据库连接信息 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/db_mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=123456
③创建Student实体类
package com.tsccg.pojo; public class Student { private Integer id; private String name; private String email; private Integer age; //get set //toString }
④创建Controller
package com.tsccg.controller; @RestController public class StudentController { @Resource private StudentService studentService; @RequestMapping("/find") public String findStudent(Integer id) { Student student = studentService.findById(id); return student.toString(); } }
⑤创建Service
StudentService接口:
package com.tsccg.service; import com.tsccg.pojo.Student; public interface StudentService { Student findById(Integer id); }
接口实现类:
package com.tsccg.service.impl; import javax.annotation.Resource; @Service public class StudentServiceImpl implements StudentService { @Resource private StudentDao studentDao; @Override public Student findById(Integer id) { return studentDao.findById(id); } }
⑥创建Dao
StudentDao接口:
package com.tsccg.dao; import com.tsccg.pojo.Student; import org.apache.ibatis.annotations.Mapper; @Mapper//告诉MyBatis这是dao接口,创建此接口的代理对象。 public interface StudentDao { Student findById(Integer id); }
在同级目录下创建StudentDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tsccg.dao.StudentDao"> <!--根据id查询学生信息--> <select id="findById" parameterType="int" resultType="com.tsccg.pojo.Student"> select id,name,email,age from t_student where id = #{id} </select> </mapper>
⑦由于是在src/main/java目录下创建的mapper映射文件,故需要在pom.xml中指定把src/main/java目录中的xml文件包含到classpath中
在build标签内添加如下语句:
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources>
⑧开启应用,在浏览器访问 http://localhost:9090/find?id=1001
第一种方式需要在每一个Dao接口上都加@Mapper,当Dao接口较多时不方便。
而这种方式只需要在启动类上添加@MapperScan(basePackages = "com.tsccg.dao")即可。
@SpringBootApplication @MapperScan(basePackages = "com.tsccg.dao") //@MapperScan(basePackages = {"com.tsccg.dao","com.tsccg.dao2"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
我们在项目中更偏向于将mapper文件与java代码分开管理,就是将mapper文件都放在src/main/resources目录下,将java代码都放在src/main/java目录下。
有两种分离方式:
在resources目录下创建com.tsccg.dao目录,将mapper文件都放进去。
这种分离方式可以在项目编译后,将mapper文件与StudentDao.class文件放在一起,如下:
步骤:
①在resources目录下创建com.tsccg.dao目录,将mapper文件移动至该目录下。
注意,在resources目录下创建com.tsccg.dao目录时,必须用/
表示分层,如下:
不然会将com.tsccg.dao当作一个目录名,编译后不会将mapper文件与StudentDao.class放在一起。
②在pom.xml中注释掉原先设置的resources标签,不然会编译报错
③重启应用,通过浏览器重新访问
第二种方式可以告诉程序从什么位置找到mapper文件,无需让mapper文件与编译后的StudentDao.class位于同级目录。
步骤:
①在resources目录下创建自定义的子目录,如mapper,然后将mapper文件放入。
②在application.properties核心配置文件中指定mapper文件所在位置
#指定mapper文件的位置 mybatis.mapper-locations=classpath:mapper/*.xml #指定使用mybatis的日志 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
③同样需要在pom.xml中注释掉原先设置的resources标签,不然会编译报错
④重启应用,重新访问地址
在Spring Boot中使用事务很简单,底层用的还是Spring提供的事务管理。
使用步骤:
@EnableTransactionManagement
注解开启事务支持(默认开启,但最好添上)@Transactional
注解即可实例演示:
以4.1中的例子为基础进行修改。
①分别在入口类上和Service接口实现类上添加事务注解
②在Controller里添加删除方法
使用try...catch语句监控Service中是否抛出异常,响应相应信息。
@RestController public class StudentController { @Resource private StudentService studentService; @RequestMapping("/delete") public String deleteStudentById(Integer id) { try { //通过id删除学生信息 studentService.deleteById(id); return "删除成功"; } catch (Exception e) { e.printStackTrace(); return "删除失败"; } } }
③在Service接口中添加删除方法并在实现类中实现
StudentService:
public interface StudentService { //通过id删除学生信息 void deleteById(Integer id); }
StudentServiceImpl:
@Service @Transactional//开启事务 public class StudentServiceImpl implements StudentService { @Resource private StudentDao studentDao; @Override public void deleteById(Integer id) { studentDao.deleteById(id);//调用Dao删除数据 int a = 10 / 0;//抛出运行时异常 } }
④在Dao接口中定义删除方法并在Mapper文件中添加对应sql语句
StudentDao:
public interface StudentDao { void deleteById(Integer id); }
StudentDao.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tsccg.dao.StudentDao"> <delete id="deleteById" parameterType="int"> delete from t_student where id = #{id} </delete> </mapper>
⑤测试
开启应用,通过浏览器访问 http://localhost:9090/delete?id=1006
REST(Representational State Transfer),表现层资源状态转移。
REST是一种互联网软件架构设计的风格,并不是标准,可用也可不用。它只是提出了一组客户端与服务器交互时的架构理念和设计原则,基于这种理念和原则设计的接口可以更简洁,更有层次。说白了,就是一种统一的url命名格式,将CRUD操作的url命名规范化,统一化。
表现层资源状态转移 概念说明:
我们过去访问一个资源所用的url五花八门,如访问一个用户信息:
http://localhost:8080/findUserById?id=1001 GET //查询一个用户信息 http://localhost:8080/addUser POST //添加用户信息 http://localhost:8080/updateUser POST //更新用户信息 http://localhost:8080/deleteUserById?id=1001 GET //删除一个用户信息
以上这些url所操作的都是同一个资源,在url内就写明了对该资源的操作。
而REST是面向资源的,资源是通过url进行暴露的。REST中,url的设计只需要把资源通过合理的方式暴露出来即可,对资源的操作与url无关,操作是通过HTTP动词来体现的。
HTTP协议中,GET、POST、DELETE、PUT都是表示操作方式的动词。
它们分别对应四种基本操作:
REST风格提倡url地址使用统一的风格设计,用名词表示资源,以及访问资源的信息,在url中,使用/
分隔对资源的访问信息。
修改上面的url为REST风格:
http://localhost:8080/user/1001 GET //查询一个用户信息 http://localhost:8080/user POST //添加用户信息 http://localhost:8080/user/1001 DELETE //删除一个用户信息 http://localhost:8080/user PUT //更新用户信息
现在问题有两个问题:
在SpringMVC中 有一个过滤器,支持将POST请求转换为DELETE、PUT请求。
过滤器:org.springframework.web.filter.HiddenHttpMethodFilter
核心方法:
从过滤器方法中得出,我们可以在页面上用表单方式发送POST请求,在携带的请求参数中添加一个名为_method
的参数,值为DELETE
或PUT
。
如下:
<form action="/user" method="POST"> id:<input type="text" name="id"><br/> 姓名:<input type="text" name="name"><br/> <!--请求方式参数,用户不需要看到,故设置为隐藏--> <input type="hidden" name="_method" value="PUT"><br/> <input type="submit" value="更新"> </form>
然后在项目中注册该过滤器即可将POST请求转换为PUT请求。
在application.properties中注册HiddenHttpMethodFilter过滤器:
spring.mvc.hiddenmethod.filter.enabled=true
此外,我们也可以通过ajax发送DELETE或PUT请求,但只有部分浏览器支持。
在Spring Boot中开发RESTful主要由如下几个注解实现
① @PathVariable:获取拼接到url中的参数数据,是实现RESTful最主要的一个注解
② @GetMapping:接收和处理GET方式的请求,等同于 @RequestMapping(method=RequestMethod.GET)
③ @PostMapping:接收和处理POST方式的请求,等同于 @RequestMapping(method=RequestMethod.POST)
④ @DeleteMapping:接收和处理DELETE方式的请求,等同于 @RequestMapping(method=RequestMethod.DELETE)
⑤ @PutMapping:接收和处理PUT方式的请求,等同于 @RequestMapping(method=RequestMethod.PUT)
以4.4中的例子为基础进行修改。
①在application.properties中注册HiddenHttpMethodFilter过滤器:
#设置端口号 server.port=9090 #注册HiddenHttpMethodFilter过滤器 spring.mvc.hiddenmethod.filter.enabled=true
②编写前端页面
在resources/static目录下新建index.html,发送crud四种请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h3>查询</h3> <a href="/student/1001">查询</a> <hr> <h3>删除</h3> <form action="/student/1007" method="POST"> <input type="hidden" name="_method" value="DELETE"><br> <input type="submit" value="删除"><br/> </form> <hr> <h3>添加</h3> <form action="/student" method="POST"> id:<input type="text" name="id"><br/> 姓名:<input type="text" name="name"><br/> <input type="submit" value="添加"><br/> </form> <hr> <h3>更新</h3> <form action="/student" method="POST"> id:<input type="text" name="id"><br/> 姓名:<input type="text" name="name"><br/> <input type="hidden" name="_method" value="PUT"><br/> <input type="submit" value="更新"><br/> </form> </div> </body> </html>
③编写Controller
package com.tsccg.controller; @RestController public class StudentController { /** * 根据id获取学生信息 * @PathVariable * 1.作用:获取url中的数据 * 2.位置:处理器形参前 * 3.value:路径变量值 {studentId} */ @GetMapping("/student/{studentId}")//处理GET请求 public String findStudent(@PathVariable(value="studentId") Integer id) { return "执行查询操作,id="+id; } /** * 添加学生 */ @PostMapping("/student")//处理POST请求 public String addStudent(@RequestParam Map<String,String> student) { return "执行添加操作,student="+student; } /** * 根据id删除学生信息 */ @DeleteMapping("/student/{studentId}")//处理DELETE请求 public String deleteStudent(@PathVariable("studentId") Integer id) { return "执行删除操作,id="+id; } /** * 更新学生信息 */ @PutMapping("/student")//处理PUT请求 public String updateStudent(@RequestParam Map<String,String> student) { return "执行更新操作,student="+student; } }
④测试
开启应用,从浏览器访问 http://localhost:9090/index.html
在REST中,必须保证URL+请求方式是唯一的,若出现如下情况,会报错。
@GetMapping("/student/{studentId}") public String findStudentById(@PathVariable(value="studentId") Integer id) { return "根据id查询学生信息"; } @GetMapping("/student/{studentName}") public String findStudentByName(@PathVariable(value="studentName") String name) { return "根据姓名查询学生信息"; }
Redis是一个NoSQL数据库,常用作缓存使用。通过Redis客户端可以使用多种语言在程序中访问Redis数据。其中,java语言使用的客户端库有:Jedis、Lettuce、Redisson等。
那么在Spring Boot中,使用的Redis客户端库是什么呢?
创建一个Spring Boot项目,勾选Web和Redis起步依赖:
查看项目导入的Redis相关依赖:
可以看出,在Spring Boot中,默认使用的Redis客户端库为lettuce
①创建Spring Boot项目,勾选web和redis起步依赖
其中,Spring Boot会根据redis的起步依赖在容器中创建两个对象:
<!--Spring Boot会在容器中创建两个对象:RedisTemplate、SpringRedisTemplate--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
在程序中使用RedisTemplate类的方法 操作redis数据, 实际就是调用的lettuce 客户端中的方法
②在核心配置文件application.properties中配置连接redis信息
#配置端口号 server.port=9090 #配置redis spring.redis.host=localhost spring.redis.port=6379 #spring.redis.password=123
③创建Controller
注入RedisTemplate对象,通过该对象的以ops
开头的几个方法获取操作redis中各种类型数据的对象
如:
然后就可以通过获取的对象执行set/get方法,管理redis中的数据了。
package com.tsccg.controller; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController public class RedisController { //注入RedisTemplate对象 @Resource private RedisTemplate redisTemplate; //向redis中添加String类型数据 @PostMapping("/student/{name}") public String setKey(@PathVariable String name) { //获取管理redis中String类型的对象 ValueOperations valueOperations = redisTemplate.opsForValue(); //执行添加操作 valueOperations.set("name",name); return "添加了学生:"+name; } //从redis中获取添加的数据 @GetMapping("/student") public String getValue() { //获取管理redis中String类型的对象 ValueOperations valueOperations = redisTemplate.opsForValue(); //执行获取操作 return (String)valueOperations.get("name"); } }
④测试
1)开启windows版redis服务
2)开启项目服务,通过postman客户端软件,以POST方式发送: http://localhost:9090/student/小明
3)再以GET方式发送请求:http://localhost:9090/student
4)通过Redis Desktop Manager桌面工具查看刚刚插入的数据
发现在redis中添加的数据为序列化的数据。
⑤修改Controller,注入StringRedisTemplate对象
package com.tsccg.controller; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController public class RedisController { //修改注入StringRedisTemplate对象 @Resource private StringRedisTemplate stringRedisTemplate; //修改添加的数据为age @PostMapping("/student/{age}") public String setKey(@PathVariable String age) { //通过StringRedisTemplate对象获取操作Stirng类型数据的对象 ValueOperations valueOperations = stringRedisTemplate.opsForValue(); valueOperations.set("age",age); return "添加了年龄:"+age; } //修改获取的数据为age @GetMapping("/student") public String getValue() { ValueOperations valueOperations = stringRedisTemplate.opsForValue(); return (String)valueOperations.get("age"); } }
⑥重新测试
重启应用,重新发送添加请求:
再次查看redis库中存入的数据:
发现这次在redis中存入的数据是正常的。
RedisTemplate:把key和value经过序列化存到redis中,key和value是序列化的内容,不能直接识别。默认使用的是jdk的序列化方式,可以修改为其它的系列化方式。
StringRedisTemplate:把key和value作为String处理,使用的是String的序列化,可读性好。
序列化与反序列化:
为什么要进行序列化?
我们在实际项目开发中,使用的redis都是放在linux上的,而为了让数据对象可以从其它地方跨平台存放到linux系统上去,就必须将对象序列化。
序列化最终的目的就是为了让对象可以跨平台存储,可以通过网络传输。而我们进行跨平台存储和网络传输的方式就是IO,IO支持的数据格式就是字节数组。我们必须在把对象转换为字节数组前就指定一种规则(序列化),那么我们从IO流读取数据的时候再以这种规则把对象还原。(反序列化)
序列化的常见方式:
序列化只是一种拆装组装对象的规则,这种规则也多种多样。比如现在常用的序列化方式有:JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protofbuff 等。
jdk的序列化: 把java对象转为byte[], 二进制数据
json序列化:json序列化能将对象转换为 JSON 格式或从 JSON 格式转换为对象。例如把一个Student对象转换为JSON字符串{"name":"李四", "age":29} ),反序列化(将JSON字符串 {"name":"李四", "age":29} 转换为Student对象)
Redis数据序列化方式有:
其中,默认的序列化方式为jdk的序列化,将key和value转换为二进制字节数组。
①修改Controller
@RestController public class RedisController { @Resource private RedisTemplate redisTemplate; @PostMapping("/student/{key}/{value}") public String setKey(@PathVariable String key,@PathVariable String value) { // 使用RedisTemplate ,在存取值之前,设置序列化 //设置key的序列化方式为String redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化方式为String redisTemplate.setValueSerializer(new StringRedisSerializer()); ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set(key,value); return "添加:" + "key=" + key + ",value=" + value; } @GetMapping("/student/{key}") public String getValue(@PathVariable String key) { ValueOperations valueOperations = redisTemplate.opsForValue(); return (String)valueOperations.get(key); } }
②发送POST请求:http://localhost:9090/student/email/123@qq.com
③查看redis库:
①设置Idea自动生成序列化版本号
②创建实体类,实现序列化接口,在实体类中自动生成序列化版本号
③修改Controller,设置value为JSON序列化方式
@Resource private RedisTemplate redisTemplate; @PostMapping("/student") public String addJson() { //创建一个Student对象 Student student = new Student(); student.setName("Tom"); student.setAge(40); student.setEmail("tom@163.com"); //设置key的序列化方式为String redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化方式为JSON redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Student.class)); //添加操作 redisTemplate.opsForValue().set("myStudent",student); return "添加:"+student.toString(); } @GetMapping("/student") public String getValue() { //设置key的序列化方式为String redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化方式为JSON redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Student.class)); ValueOperations valueOperations = redisTemplate.opsForValue(); return valueOperations.get("myStudent").toString(); }
④发送post请求: http://localhost:9090/student (序列化)
⑤查看redis库
⑥发送get请求: http://localhost:9090/student 反序列化
创建一个普通maven模块作为父模块,模块名:16-dubbo-parent
进行如下操作:
1)删除src目录
2)修改pom.xml,指定打包方式为pom
3)继承spring-boot-starter-parent模块
4)添加dubbo和zookeeper起步依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--继承Spring Boot父模块--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> </parent> <groupId>com.tsccg</groupId> <artifactId>16-dubbo-parent</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging><!--指定打包方式为pom--> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--添加dubbo起步依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <!--添加zookeeper依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>2.7.8</version> <type>pom</type> <!--dubbo起步依赖中已经包含了log4j依赖,排除zookeeper依赖中包含的重复依赖--> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
创建一个普通maven模块,无父模块,在此模块中只定义公共的接口和实体类。
模块名:common-interface
GAV坐标:
<groupId>com.tsccg</groupId> <artifactId>common-interface</artifactId> <version>0.0.1-SNAPSHOT</version>
创建实体类Student,实现序列化接口
package com.tsccg.pojo; import java.io.Serializable; public class Student implements Serializable { private String name; private Integer age; private String email; //get set //toString }
创建公共接口 StudentService,定义方法
package com.tsccg.pojo.com.tsccg.service; import com.tsccg.pojo.Student; public interface StudentService { //获取Studnet数据 Student getStudent(); }
创建普通maven模块:server-consumer,继承父模块 16-dubbo-parent
然后进行如下操作:
①在pom.xml中添加依赖
1)声明Spring Boot的web起步依赖
2)添加公共接口模块依赖
<dependencies> <!--声明web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--添加公共接口模块依赖--> <dependency> <groupId>com.tsccg</groupId> <artifactId>common-interface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
②在resources目录下创建application.properties核心配置文件,配置dubbo
#服务暴露接口 server.port=8081 ##配置dubbo #服务名称 spring.application.name=server-consumer #扫描dubbo注解所在包 dubbo.scan.base-packages=com.tsccg.service #指定注册中心地址,此处用的是本地的zookeeper dubbo.registry.address=zookeeper://localhost:2181
③在java目录下创建com.tsccg.Application 启动类
添加开启Dubbo的注解:@EnableDubbo
package com.tsccg; import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableDubbo//开启dubbo public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
④创建Controller
使用@DubboReference注解远程注入StudentService对象
package com.tsccg.controller; import com.tsccg.pojo.Student; import com.tsccg.pojo.com.tsccg.service.StudentService; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class StudentController { @DubboReference(version = "1.0")//dubbo远程注入 private StudentService studentService; @GetMapping("/student") public String getStudent() { //调用服务方法 Student student = studentService.getStudent(); return student.toString(); } }
同服务消费者,创建一个普通maven模块:server-provider,继承父模块
进行如下操作:
①添加依赖
<dependencies> <!--声明web起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--公共接口依赖--> <dependency> <groupId>com.tsccg</groupId> <artifactId>common-interface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
②创建核心配置文件:application.properties,配置dubbo
#暴露服务接口 server.port=8080 ##配置dubbo #服务名称 spring.application.name=server-provider #扫描dubbo注解所在包 dubbo.scan.base-packages=com.tsccg.service #指定注册中心地址 dubbo.registry.address=zookeeper://localhost:2181
③创建启动类:Application,添加开启dubbo注解
package com.tsccg; import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableDubbo//开启dubbo public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
④创建服务实现类
package com.tsccg.service.impl; import com.tsccg.pojo.Student; import com.tsccg.pojo.com.tsccg.service.StudentService; import org.apache.dubbo.config.annotation.DubboService; //使用Dubbo提供的@DubboService注解,指定接口class为StudentService.class @DubboService(interfaceClass = StudentService.class,version = "1.0") public class StudentServiceImpl implements StudentService{ @Override public Student getStudent() { //创建一个Student对象 Student student = new Student(); student.setName("杰瑞"); student.setAge(30); student.setEmail("jerry@qq.com"); return student; } }
①开启zookeeper
②先后运行服务提供者和服务消费者应用
③在浏览器中发送请求: http://localhost:8081/student
Spring Boot 可以打包为 war 或 jar 文件。 以两种方式发布应用。
步骤:
1.创建一个Spring Boot项目,添加Web起步依赖
2.修改pom.xml
1)添加内嵌 Tomcat 对 jsp 的解析包依赖
<!--使用jsp--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
2)指定jsp编译目录
<build> <!--jsp 文件必须编译到指定的 META-INF/resources 目录下--> <resources> <resource> <!--源文件位置--> <directory>src/main/webapp</directory> <!--指定编译到 META-INF/resource,该目录不能随便写--> <targetPath>META-INF/resources</targetPath> <!--指定要把哪些文件编译进去,**表示 webapp 目录及子目录,*.*表示所有文件--> <includes> <include>**/*.*</include> </includes> </resource> <!--把src/main/resources下面的所有文件,都包含到classes目录--> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources> </build>
3)指定打包方式为war
4)指定打包后生成war包的名称
在build标签内添加如下语句:
<!--指定最终打包后的包名--> <finalName>myBoot</finalName>
5)完整的pom.xml内容
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.tsccg</groupId> <artifactId>17-package-war</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging><!--指定打包类型为war--> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--添加jsp依赖--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> </dependencies> <build> <!--jsp 文件必须编译到指定的 META-INF/resources 目录下--> <resources> <resource> <!--源文件位置--> <directory>src/main/webapp</directory> <!--指定编译到 META-INF/resource,该目录不能随便写--> <targetPath>META-INF/resources</targetPath> <!--指定要把哪些文件编译进去,**表示 webapp 目录及子目录,*.*表示所有文件--> <includes> <include>**/*.*</include> </includes> </resource> <!--把src/main/resources下面的所有文件,都包含到classes目录--> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources> <!--指定最终打包后的包名--> <finalName>myBoot</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3.创建webapp并引入项目,在其中创建index.jsp作为视图
4.配置视图解析器
在核心配置文件 application.properties中添加如下内容:
#前缀 spring.mvc.view.prefix=/ #后缀 spring.mvc.view.suffix=.jsp
5.创建Controller
package com.tsccg.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class WarController { @RequestMapping("/doSome") public String doSome(Model model) { model.addAttribute("data","war包"); return "index"; } }
6.测试,开启应用,在浏览器中访问 http://localhost:8080/doSome
7.让启动类继承SpringBootServletInitializer
只有继承了此类,重写其configure方法后,生成的war包才能单独部署到外部的服务器中。
SpringBootServletInitializer就是原有的web.xml文件的替代。使用了嵌入式Servlet,默认不支持jsp。
package com.tsccg; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication public class Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Application.class); } }
8.部署至外部独立服务器
1)将生成的war包部署到外部的Tomcat服务器中
通过maven执行clean---->package后,将target 目录下的 war 文件拷贝到 tomcat 服务器 webapps 目录中
2)启动Tomcat
3)在浏览器中访问 http://localhost:8080/myBoot/doSome
多出的/myBoot
是由于我们开启tomcat后,会自动将war文件解压缩,我们的项目文件都在解压缩的文件夹中。
以前面打war包的例子为基础进行修改。
1.修改pom.xml
1)指定打包方式为jar
默认打包类型就是jar,删除原先指定的war包语句即可
2)指定springboot-maven-plugin版本
打包jar,有jsp文件时,必须指定maven-plugin插件的版本是 1.4.2.RELEASE
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <!--指定maven-plugin插件的版本为1.4.2.RELEASE--> <version>1.4.2.RELEASE</version> </plugin> </plugins>
3)修改Controller
@RequestMapping("/doOther") public String doOther(Model model) { model.addAttribute("data","jar包"); return "index"; }
4)修改主启动类不继承SpringBootServletInitializer
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
2.执行打包,通过cmd窗口执行命令运行jar包,启动内置的Tomcat
1)通过maven执行clean-->package,生成myBoot.jar
2)进入myBoot.jar包所在目录,打开cmd窗口
3)运行启动命令,启动内置的Tomcat
java -jar myBoot.jar
4)在浏览器中发送请求 http://localhost:8080/doOther
war包必须部署到独立的外部服务器上,占用资源较多。但独立的服务器功能较多,这种方式能更好的利用服务器。
jar包可以通过内置的tomcat单独运行,占用资源少。但内置的服务器功能较少,性能不如war包方式。
在IDEA中直接运行主启动类的main方法。
1.打jar包
在IDEA中通过maven插件将项目打成jar包,可用java -jar xxx.jar
命令启动内置的Tomcat。
上线部署到Linux系统上时,可以将该命令封装到一个Shell脚本中,步骤如下:
①在jar包同级目录里创建一个shell脚本,编写如下内容
run.sh:
#!/bin/sh java -jar xxx.jar
②赋予权限
chmod 777 run.sh
③启动shell脚本
./run.sh
2.打war包
在IDEA中通过maven插件将项目打成war包,单独部署到tomcat等服务器的发布目录下运行