<bean
id="bean的唯一标识"
class="bean的全类名"
scope="bean的作用范围,有singleton(默认)和prototype"
name="为bean取的别名"
/>
<bean ...>
<property name="" ref=""/>
bean>
<bean ...>
<property name="" value=""/>
bean>
<bean ...>
<constructor-arg name="" index="" type="" ref=""/>
bean>
<bean ...>
<constructor-arg name="" index="" type="" value=""/>
bean>
标签删除;
标签中添加 autowire 属性。在
或
标签内部写 array
、 list
、 set
、 map
、 props
标签。
管理第三方bean步骤:
<context:property-placeholder location="" system-properties-mode="NEVER"/>
${key}
@Configuration
注解,将其标识为一个配置类,替换applicationContext.xml
;@ComponentScan
替换
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
@Scope
:设置该类创建对象的作用范围,可用于设置创建出的bean是否为单例对象@PostConstruct
:设置该方法为初始化方法@PreDestroy
:设置该方法为销毁方法注解开发只提供了自动装配的注解实现。
@Autowired
:为引用类型属性设置值,自动装配;@Qualifier
:为引用类型属性指定注入的beanId,即可以在多个实现类中指定注入Bean的 Id;@Value
:为 基本数据类型 或 字符串类型 属性设置值;@PropertySource
:加载properties文件中的属性值,属性值可以使用 @Value("${key}")
注入。@Bean
注解将方法的返回值制作为Spring管理的一个bean对象@Bean
:设置该方法的返回值作为spring管理的bean@Import({JdbcConfig.class})
引入第三方bean@Import
:导入配置类@Value
注解引入值,在第三方bean的方法中传递参数进去即可;要整合的内容:
第一件事是:Spring要管理MyBatis中的SqlSessionFactory
第二件事是:Spring要管理Mapper接口的扫描
整合步骤:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class}) //加载配置类
spring-context
、aspectjweaver
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
@Before("pt()")
@Component
、@Aspect
@EnableAspectJAutoProxy
execution(* com.itheima.service.*Service.*(..))
- 前置通知
- 后置通知
- 环绕通知(重点)
- 返回后通知
- 抛出异常后通知
@EnableAspectJAutoProxy
:配置类定义上方,开启注解格式AOP功能@Aspect
:切面类定义上方,设置当前类为AOP切面类@Pointcut
:切入点方法定义上方,设置切入点方法@Before
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行@Before
@After
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行@AfterReturning
:通知方法定义上方,设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法正常执行完毕后执行@AfterThrowing
:通知方法定义上方,设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行@Around
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行,对原始方法的调用通过 pjp.proceed();
实现@Transactional
,可以写在接口类上、接口方法上、实现类上和实现类方法上,建议写在实现类或实现类的方法上@EnableTransactionManagement
@EnableTransactionManagement
:配置类定义上方,设置当前Spring环境中开启注解式事务支持;@Transactional
:业务层接口上方、业务层实现类上方、业务方法上方,为当前业务层方法添加事务(如果设置在类或接口上方则类或接口中所有方法均添加事务)@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
SpringMvcConfig
,添加注解:@Configuration
@ComponentScan("com.itheima.controller")
@Controller
注解,定义方法添加 @RequestMapping("/save")
注解设置当前控制器方法请求访问路径,添加注解 @ResponseBody
设置返回数据为jsonpublic class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
) p
ublic class SpringConfig {
}
@Controller
:SpringMVC控制器类定义上方,设定SpringMVC的核心控制器bean;@RequestMapping
:SpringMVC控制器类或方法定义上方,设置当前控制器方法请求访问路径;@ResponseBody
:SpringMVC控制器类或方法定义上方,设置当前控制器方法响应内容为当前返回值,无需解析@ComponentScan
:类定义上方,设置spring配置类扫描路径,用于加载使用注解格式定义的bean;excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes)、includeFilters:加载指定的bean,需要指定类别(type)和具体项(classes)@@RequestMapping("/book")
、 @RequestMapping("/user")
进行区分@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
@RequestParam
注解@RequestParam
:SpringMVC控制器方法形参定义前面,绑定请求参数与处理器方法形参间的关系@EnableWebMvc
注解@RequestBody
注解@EnableWebMvc
:SpringMVC配置类定义上方,开启SpringMVC多项辅助功能@RequestBody
:SpringMVC控制器方法形参定义前面,将请求中请求体所包含的数据传递给请求参数——用于接收 json 数据@RequestParam
:用于接收url地址传参,表单传参@DateTimeFormat
:SpringMVC控制器方法形参前面,设定日期时间型数据格式@ResponseBody
,如果加了该注解,会直接将页面名称 page.jsp 当字符串返回前端@ResponseBody
注解,文本数据return回去即可@ResponseBody
注解和 @EnableWebMvc
注解,将实体类对象或集合对象 return 即可@ResponseBody
:SpringMVC控制器方法定义上方和控制类上,设置当前控制器返回值作为响应体,写在类上,该类的所有方法都有该注解功能。方法上有 @ReponseBody
注解后
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
按照不同的请求方式代表不同的操作类型:
@RequestMapping
提到类上面,用来定义所有方法共同的访问路径 /books
、/user
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
设置当前控制器方法请求访问路径与请求动作@RestController
注解替换 @Controller
与 @ResponseBody
注解写在 Controller 类上方@PathVariable
解决方法形参的名称和路径{}中的值不一致问题与多个参数的区分问题@PathVariable
:SpringMVC控制器方法形参定义前面,绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应@RestController
:基于SpringMVC的RESTful开发控制器类定义上方,设置当前控制器类为RESTful风格,等同于 @Controller
与 @ResponseBody
两个注解组合功能@GetMapping @PostMapping @PutMapping @DeleteMapping
:基于SpringMVC的RESTful开发控制器方法定义上方,设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping
对应GET请求@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
//设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry){
//当访问/pages/????时候,从/pages目录下查找内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
同时注意让 SpringMvcConfig 配置类扫描到 config 包中的 SpringMvcSupport 类。
流程:
spring-jdbc
、spring-test
mybatis
、mysql-connector-java
、druid
、mybatis-spring
junit
spring-webmvc
、javax.servlet-api
、jackson-databind
tomcat7-maven-plugin
@Configuration
@ComponentScan({"com.itheima.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.itheima.domain");
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.itheima.dao");
return mapperScannerConfigurer;
}
}
@Configuration
@ComponentScan({"com.itheima.controller", "com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
// Web 项目入口配置类
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
// 加载 Spring 配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
// 加载 SpringMvc 配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
// 配置 SpringMVC 请求地址拦截规则
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 设置 post 请求中文乱码过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
}
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@PostMapping
public Result save(@RequestBody Book book){
boolean flag = bookService.save(book);
return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);
}
@PutMapping
public Result update(@RequestBody Book book){
boolean flag = bookService.update(book);
return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id){
boolean flag = bookService.delete(id);
return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
}
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
Book book = bookService.getById(id);
Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
String msg = book != null ? "" : "数据查询失败,请重试!";
return new Result(code, book, msg);
}
@GetMapping
public Result getAll(){
List<Book> list = bookService.getAll();
Integer code = list != null ? Code.GET_OK : Code.GET_ERR;
String msg = list != null ? "" : "数据查询失败,请重试!";
return new Result(code,list,msg);
}
}
目的:出现异常的时候,也会返回一个 Result 标准结果对象回去,在 msg 属性中添加异常信息。
// 自定义业务异常类
public class BusinessException extends RuntimeException{
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public BusinessException(Integer code, String message){
super(message);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause){
super(message,cause);
this.code = code;
}
}
// 自定义系统异常类
public class SystemException extends RuntimeException{
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public SystemException(Integer code, String message){
super(message);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause){
super(message,cause);
this.code = code;
}
}
@Override
public Book getById(Integer id) {
// 模拟业务异常,包装成自定义异常
if(id == 1){
throw new BusinessException(Code.BUSINESS_ERR,"请不要用你的技术挑战我的耐性");
}
// 模拟系统异常,将可能出现的异常包装转换成自定义异常
try {
int i = 1 / 0;
} catch (Exception e){
throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请重试!",e);
}
return bookDao.getById(id);
}
@RestControllerAdvice
public class ProjectExceptionAdvice {
// @ExceptionHandler 用于设置当前处理器类对应的异常类型
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex){
//其他处理:记录日志、发送消息给运维、发送邮件给开发人员
// 接替 controller 返回结果
return new Result(ex.getCode(),null,ex.getMessage());
}
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException ex){
return new Result(ex.getCode(),null,ex.getMessage());
}
// 除了自定义的异常处理器,保留对 Exception 类型的异常处理
@ExceptionHandler(Exception.class)
public Result doOtherException(Exception ex){
//其他处理
return new Result(Code.SYSTEM_UNKNOW_ERR, null, "系统繁忙,请稍后再试");
}
}
@RestControllerAdvice
:Rest风格开发的控制器增强类定义上方,为Rest风格开发的控制器类做增强——此注解自带 @ResponseBody
注解与 @Component
注解,具备对应的功能@ExceptionHandler
:专用于异常处理的控制器方法上方,设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {
@Override
//原始方法调用前执行的内容
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true;
}
@Override
//原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
@Override
//原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
System.out.println("afterCompletion...");
}
}
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books");
}
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*" );
}
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//配置多拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
exclusion>
exclusions>
dependency>
- 在 pom.xml 中引入 jetty 的起步依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jettyartifactId>
dependency>
SpringBoot 程序的配置文件名必须是 application
application.properties
> application.yml
> application.yaml
lesson: SpringBoot
server:
port: 80
enterprise:
name: itcast
age: 16
tel: 138****8888
subject:
- java
- 前端
- 大数据
@Value
注解:@RestController
@RequestMapping("/books")
public class BookController {
@Value("${lesson}")
private String lesson;
@Value("${server.port}")
private Integer port;
@Value("${enterprise.subject[0]}")
private String subject_00;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println(lesson);
System.out.println(port);
System.out.println(subject_00);
return "hello , spring boot!";
}
}
Environment
对象 :SpringBoot 还可以使用 @Autowired
注解注入 Environment
对象的方式读取数据, SpringBoot
会将配置文件中所有的数据封装到 Environment
对象中,如果需要使用哪个数据只需要通过调用 Environment
对象的 getProperty(String name)
方法获取@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private Environment env;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println(env.getProperty("lesson"));
System.out.println(env.getProperty("enterprise.name"));
System.out.println(env.getProperty("enterprise.subject[0]"));
return "hello , spring boot!";
}
}
bean
的创建交给 Spring
管理:在类上添加 @Component
注解@ConfigurationProperties
注解表示加载配置文件:在该注解中也可以使用 prefix
属性指定只加载指定前缀的数据BookController
中进行注入application.yml
中使用 ---
来分割不同的配置;#设置启用的环境
spring:
profiles:
active: pro #表示使用的是生产环境的设置
---
#开发
spring:
config:
activate:
on-profile: dev
server:
port: 80
---
#生产
spring:
config:
activate:
on-profile: pro
server:
port: 81
---
#测试
spring:
config:
activate:
on-profile: test
server:
port: 82
java –jar xxx.jar –-spring.profiles.active=test
- 临时修改端口号
java –jar xxx.jar –-server.port=88
@Service
注解test/java
下创建 com.itheima
包,在该包下创建测试类 SpringbootQuickstartApplicationTests
(默认创建工程时生成有),将 BookService 注入到该测试类中@SpringBootTest
class SpringbootQuickstartApplicationTests {
@Autowired
private BookService bookService;
@Test
void testSave() {
bookService.save();
}
}
SpringbootMybatisApplicationTests
:@SpringBootTest
class SpringbootMybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void testGetById() {
Book book = bookDao.getById(1);
System.out.println(book);
}
}
application.yml
配置文件中配置如下内容:\spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: 1234
testGetById
测试报错:在 Spring 容器中没有 BookDao 类型的 bean ,原因 ⇒ Mybatis
会扫描接口并创建接口的代码对象交给 Spring
管理,但是现在并没有告诉 Mybatis
哪个是 dao
接口,即没有最开始的指定 Mapper
⇒ 在 BookDao
接口上使用 @Mapper
:@Mapper
public interface BookDao {
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
}
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.16version>
dependency>
application.yml
配置文件中通过 spring.datasource.type
来配置使用什么数据源配置spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: 1234
type: com.alibaba.druid.pool.DruidDataSource
<dependency>
<groupId>com.itheimagroupId>
<artifactId>maven_03_pojoartifactId>
<version>1.0-SNAPSHOTversion>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.itheimagroupId>
<artifactId>maven_04_daoartifactId>
<version>1.0-SNAPSHOTversion>
<exclusions>
<exclusion>
<groupId>com.itheimagroupId>
<artifactId>maven_03_pojoartifactId>
exclusion>
exclusions>
dependency>
,A不知道有C的存在
,A知道有C的存在,主动将其排除掉 <packaging>pompackaging>
<modules>
<module>../maven_02_ssmmodule>
<module>../maven_03_pojomodule>
<module>../maven_04_daomodule>
modules>
compile
指令,所有被其管理的项目都会被执行编译操作
<parent>
<groupId>com.itheimagroupId>
<artifactId>maven_01_parentartifactId>
<version>1.0-SNAPSHOTversion>
<relativePath>../maven_01_parentrelativePath>
parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
dependencyManagement>
标签不真正引入jar包,而是配置可供子项目选择的jar包依赖;子项目要想使用它所提供的这些jar包,需要自己添加依赖,并且不需要指定
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
dependency>
<properties>
<spring.version>5.2.10.RELEASEspring.version>
<junit.version>4.12junit.version>
<mybatis-spring.version>1.3.0mybatis-spring.version>
properties>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
jdbc.properties
的属性 <properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_dbjdbc.url>
properties>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=${jdbc.url}
jdbc.username=root
jdbc.password=root
<build>
<resources>
<resource>
<directory>../maven_02_ssm/src/main/resourcesdirectory>
<filtering>truefiltering>
resource>
resources>
build>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resourcesdirectory>
<filtering>truefiltering>
resource>
resources>
build>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-war-pluginartifactId>
<version>3.2.3version>
<configuration>
<failOnMissingWebXml>falsefailOnMissingWebXml>
configuration>
plugin>
plugins>
build>
<profiles>
<profile>
<id>env_depid>
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_dbjdbc.url>
properties>
<activation>
<activeByDefault>trueactiveByDefault>
activation>
profile>
<profile>
<id>env_proid>
<properties>
<jdbc.url>jdbc:mysql://127.2.2.2:3306/ssm_dbjdbc.url>
properties>
profile>
<profile>
<id>env_testid>
<properties>
<jdbc.url>jdbc:mysql://127.3.3.3:3306/ssm_dbjdbc.url>
properties>
profile>
profiles>
install
查看env_dep环境是否生效:即安装项目,到压缩文件里找 jdbc.properties 里面的 url 配置的到底是哪个
标签mvn install -P env_test
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.12.4version>
<configuration>
<skipTests>falseskipTests>
<excludes>
<exclude>**/BookServiceTest.javaexclude>
excludes>
configuration>
plugin>
plugins>
build>
私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题
Sonatype公司的一款maven私服产品:Nexus
下载地址:https://help.sonatype.com/repomanager3/download
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.16version>
dependency>
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
username: root
password: xxxx
BaseMapper
接口// @Mapper
public interface UserDao extends BaseMapper<User> {
}
@MapperScan
注解扫描 Dao 包下面的所有接口,就不用在每个 Dao 接口上写 @Mapper
注解@MapperScan("com.example.dao")
@SpringBootApplication
public class Mybatisplus01QuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(Mybatisplus01QuickstartApplication.class, args);
}
}
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {
@Autowired
private UserDao userDao;
//查询所有
@Test
void testGetAll() {
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
}
在测试类中进行新增操作:
//增
@Test
void testSave() {
User user = new User();
user.setName("黑马程序员");
user.setPassword("itheima");
user.setAge(12);
user.setTel("13800001111");
userDao.insert(user);
}
//删
@Test
void testDelete(){
userDao.deleteById(1608813761737584642L);
}
//改
@Test
void testUpdate(){
User user = new User();
user.setId(1L);
user.setName("Tom666");
user.setPassword("tom666");
userDao.updateById(user);
}
//根据Id查询
@Test
void testGetById() {
User user = userDao.selectById(2L);
System.out.println(user);
}
//查询所有
@Test
void testGetAll() {
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper)
- IPage:用来构建分页查询条件:IPage是一个接口,其有一个实现类为Page
- Wrapper:用来构建条件查询的条件,目前我们没有可直接传为Null
- IPage:返回值,你会发现构建分页条件和方法的返回值都是IPage
//分页查询
@Test
void testSelectPage() {
//1.创建 IPage 分页对象,设置分页参数
IPage<User> page = new Page<>(1, 3);
//2.执行分页查询
userDao.selectPage(page,null);
//3.获取分页结果
System.out.println("当前页码值:" + page.getCurrent());
System.out.println("每页条目数:" + page.getSize());
System.out.println("一共多少页:" + page.getPages());
System.out.println("一共多少条记录:" + page.getTotal());
System.out.println("当前页数据:" + page.getRecords());
}
@Configuration
public class MybatisPlusConfig {
//将分页拦截器插件配置成 Spring 管理的 bean 对象
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
//创建分页拦截器对象
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
mybatis-plus:
configuration:
#打印 sql 日志到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus-boot-starter
、druid
、lombok
Mapper
注解Data
注解
<configuration>
configuration>
# mybatis-plus日志控制台输出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: off # 关闭mybatisplus启动图标
spring:
main:
banner-mode: off # 关闭SpringBoot启动图标(banner)
@Test
void testGetAll(){
QueryWrapper qw = new QueryWrapper();
qw.lt("age",18);
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
@Test
void testGetAll(){
QueryWrapper<User> qw = new QueryWrapper<User>();
qw.lambda().lt(User::getAge, 10);//添加条件
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 30);
lqw.gt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Data
public class UserQuery extends User {
private Integer age2;
}
@Test
void testGetAll(){
//模拟页面传递过来的查询数据
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//if(null != uq.getAge2()){
// lqw.lt(User::getAge, uq.getAge2());
//}
//if( null != uq.getAge()) {
// lqw.gt(User::getAge, uq.getAge());
//}
// 简化
lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.select(User::getId,User::getName,User::getAge);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
QueryWrapper<User> lqw = new QueryWrapper<User>();
//lqw.select("count(*) as count");
//SELECT count(*) as count FROM user
//lqw.select("max(age) as maxAge");
//SELECT max(age) as maxAge FROM user
//lqw.select("min(age) as minAge");
//SELECT min(age) as minAge FROM user
//lqw.select("sum(age) as sumAge");
//SELECT sum(age) as sumAge FROM user
lqw.select("avg(age) as avgAge");
//SELECT avg(age) as avgAge FROM user
List<Map<String, Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("count(*) as count,tel");
lqw.groupBy("tel");
List<Map<String, Object>> list = userDao.selectMaps(lqw);
System.out.println(list);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.eq(User::getName, "Jerry").eq(User::getPassword, "jerry");
User loginUser = userDao.selectOne(lqw);
System.out.println(loginUser);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.between(User::getAge, 10, 30);
//SELECT id,name,password,age,tel FROM user WHERE (age BETWEEN ? AND?)
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.likeLeft(User::getName, "J");
//SELECT id,name,password,age,tel FROM user WHERE (name LIKE ?)
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll(){
LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>();
/**
* condition :条件,返回boolean,
当condition为true,进行排序,如果为false,则不排序
* isAsc:是否为升序,true为升序,false为降序
* columns:需要操作的列
*/
lwq.orderBy(true,false, User::getId);
userDao.selectList(lwq)
}
@TableField
: 模型类属性定义上方,设置当前属性对应的数据库表中的字段关系@TableName
:模型类定义上方,设置当前类对应于数据库表关系@TableId
:模型类中用于表示主键的属性定义上方,设置当前类中主键属性的生成策略 @TableId(type = IdType.AUTO)
private Long id;
mybatis-plus:
global-config:
db-config:
id-type: assign_id
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
@TableField
进行关系映射,如果一致,则会自动对应@TableLogic
@TableLogic(value="0",delval="1")
//value为正常数据的值,delval为删除数据的值
private Integer deleted;
@Mapper
public interface UserDao extends BaseMapper<User> {
//查询所有数据包含已经被删除的数据
@Select("select * from tbl_user")
public List<User> selectAll();
}
mybatis-plus:
global-config:
db-config:
# 逻辑删除字段名
logic-delete-field: deleted
# 逻辑删除字面值:未删除为0
logic-not-delete-value: 0
# 逻辑删除字面值:删除为1
logic-delete-value: 1
@TableLogic
:模型类中用于表示删除字段的属性定义上方,标识该字段为进行逻辑删除的字段 @Version
private Integer version;
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor() {
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加乐观锁拦截器
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
@Test
void testUpdate() {
User user = userDao.selectById(3L);
User user2 = userDao.selectById(3L);
user2.setName("Jock aaa");
userDao.updateById(user2);
user.setName("Jock bbb");
userDao.updateById(user);
}
@SpringBootTest
class Mybatisplus04GeneratorApplicationTests {
private IUserService userService;
@Test
void testFindAll() {
List<User> list = userService.list();
System.out.println(list);
}
}
未解决问题:报错 Failed to determine a suitable driver class,未找到原因