在整合SSM的过程中,发现会花很多时间去整理配置文件,如spring相关的的applicationContext.xml,springweb相关的springmvc.xml,mybatis相关的sqlConfig.xml和sql映射文件,以及web.xml中的配置等,比较繁琐,配置也容易出问题。另外虽然使用maven管理包可以解决以前手动粘贴复制导包的窘境,但是maven导包还需要考虑包之间是否有冲突是否兼容的问题。以上的缺点spring考虑到了就推出了springboot,它的基本理念是"约定大于配置",大大简化开发人员前期的配置,让更多精力用于开发,下面简单入门记录一下。
传统SSM开发痛点
(1)pom.xml需要配置大量依赖,繁琐且容易出错,需考虑版本号、版本兼容、版本冲突的问题。
(2)测试需要有容器的支持,如打包发送到tomcat中,无法独立运行,不利于开发测试。
Springboot简介
springboot是一个基于spring的项目快速构建工具,可以大大提高项目构建和开发的效率,它向前承接了SSM的开发,使其变得简化,向后则是springcloud微服务的基础。它具有如下优点。
(1)pom中需要配置的文件大大减少,利用了pom文件的继承和传递技术,会有一些顶级父pom文件给我们使用,如下就是web相关的顶级父pom依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
(2)"约定大于配置",不做任何配置或只需要少量的配置就可以开始开发,会根据导入的包,自动生成配置文件。
(3)内置servlet容器,web开发测试像独立运行一个main方法一样简单。
Springboot入门案例
使用IDEA创建一个maven工程,使用quick start方式启动。
(1)pom文件,spring-boot-starter-parent这个pom文件是springboot的,里面定义的内容被当前pom文件导入,包含了当前springboot下最合适的jar包版本,无需再担心版本问题。此外它还定义了大量声明式依赖,如果需要引入需要手动添加。
<!-- 继承springboot-parent,引入springboot的父pom文件 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <!-- 以前需要配置很多依赖包,这里只需要配置一个starter-web,就会将spring相关的包自动导入,非常简便 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
(2)resources下无需写配置文件,就可以运行springboot。
(3)书写启动类,使用@SpringBootApplication复合注解,具体参考代码注释。
package com.boe; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * 开发主类,其中包含main方法 */ @SpringBootApplication public class SpringbootDemo01 { /** * @SpringBootApplication注解是一个复合注解,它由如下几部分组成 * @SpringBootConfiguration:自动读取springboot配置文件(它也是一个复合注解,包含@Configuration注解),如application.properties,banner.txt,bootstrap.properties * @EnableAutoConfiguration:根据当前引入的包自动生成配置信息,注解工作时会加载spring-boot-autoconfigure-1.5.9.RELEASE.jar包,解析META-INF/下的spring-factories配置文件 * @ComponentScan:默认将当前类所在包及其子孙包,加入到springIOC的包扫描,相当如<context:component-scan></context:component-scan>的配置 */ public static void main(String[] args) { System.out.println("hello springboot"); //启动springboot,加载类时发现其有@SpringBootApplication注解,触发注解的功能 //完成自动读取配置文件,自动生成配置文件和添加包扫描等功能。 SpringApplication.run(SpringbootDemo01.class,args); } }
(4)写一个controller控制类
package com.boe.controller; import com.boe.service.FirstService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/first") //测试springmvc public class FirstController { //自动注入service,测试spring di @Autowired FirstService service; @ResponseBody @RequestMapping("/test01.action") public String test01(){ System.out.println("controller is running"); //service service.print(); return "hello springboot"; } }
(5)写一个service类
package com.boe.service; import org.springframework.stereotype.Service; @Service("service") public class FirstService { public void print(){ System.out.println("service is running"); }; }
(6)开启启动类,发现web可以正常访问,其中访问的端口号(8099)和context-path(yangchaolin)可以单独设置的。
Springboot配置
虽然springboot无需配置也可以启动,但是必要时也可以通过配置来修改默认配置。
(1)application.properties或application.yml。
它是springboot的核心配置文件,有两种格式,均可以使用,后者yml容易出错,需要注意空格。
properties配置:
# 配置端口号
#server.port=8099
# 内置servlet运行时使用的应用名
#server.context-path=/yangchaolin
yml配置,注意格式:
# 书写非常严格,port和context-path前后都有空格
server:
port: 8099
context-path: /yangchaolin
# 可以配置属性,使用@Value可以将值引用
id: 2
name: herry
age: 36
(2)banner横幅
可以设置springboot启动时的字符画,如我修改成了clyang。
.__ ____ | | ___.__._____ ____ ____ _/ ___| |< | |\__ / / ___ \___| |_\___ | / __ | | / /_/ > \___ >____/ ____|(____ /___| /\___ / / / / //_____/
(3)bootstrap.properties
用来配置加载系统配置,加载顺序优先于application.xml或application.yml,后续补充
常用注解
springboot下使用@Configuration可以将当前类作为配置类,类似applicationContext.xml,可以配合其他注解进行使用。
(1)@Configuration+@ComponentScan(包名),可以指定包扫描,如果不指定就将当前类所在包及其子孙包加入包扫描,一般用于扫描dao层的mapper包。
package com.boe.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * 当前包需要放在SpringbootDemo01所在包及其子包下面,需要被扫描到才能使用@Configuration注解生效 */ @Configuration @ComponentScan("com.baidu") public class MyConfig { /** * @Configuration 理解为以前spring配置文件applicationContext.xml * @ComponentScan("com.baidu") 理解为以前的<context:component-scan base-package="com.baidu" /> */ }
(2)@Configuration+@Bean,可以将方法返回的对象注册为bean交给spring管理,后续可以调用,如springcloud微服务调用使用的RestTemplate就用这种方式创建。
package com.boe.config; import com.boe.domain.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 测试使用@Bean注解 */ @Configuration public class UserConfig { //使用@Bean,让其返回一个bean,相当如配置<bean id="" class=""> @Bean("user") //可以指定bean id public User getUserInstance(){ return new User(); } }
controller测试类
package com.boe.controller; import com.boe.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * 测试@Bean的controller */ @Controller @RequestMapping("/user") public class UserController { //测试是否user已经加入到spring bean中 @Autowired User user; @ResponseBody @RequestMapping("/test01.action") public String test01(){ System.out.println(user); return "user已经纳入spring管理"; } }
测试结果,访问地址,控制台打印出user对象,说明配置生效。
浏览器端
控制台端
(3)@Value,可以将核心配置文件中读取到的属性,通过@Value("${属性名}")的方式注入。
package com.boe.domain; import org.springframework.beans.factory.annotation
.Value; /** * 测试@Bean注解的实体类 */ public class User { //可以使用@Value直接导入值 //@Value("1") @Value("${id}") private int id; //@Value("messi") @Value("${name}") private String name; //@Value("32") @Value("${age}") private int age; public User() { } public User(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } ......省略 }
在上面的基础上,在核心配置文件中添加属性值,再次测试发现导入了数值。
# 可以配置属性,使用@Value可以将值引用
id: 2
name: herry
age: 36
控制台输出了实际值,ok。
(4)@ImportResource,可以额外加载一个配置文件使用。
package com.boe.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; /** * 测试使用@ImportResource注解 */ @Configuration @ImportResource(locations = "classpath:/myspring.xml") //读取自己定义的spring配置文件 public class DeptConfig { }
其中myspring.xml配置信息就是配置了一个bean。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 测试@ImportResource注解 --> <bean id="dept" class="com.boe.domain.Dept" ></bean> </beans>
测试的控制类
package com.boe.controller; import com.boe.domain.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * 测试使用@ImportResource注解 */ @Controller @RequestMapping("/dept") public class DeptController { //注入dept @Autowired Dept dept=null; @ResponseBody @RequestMapping("/test01.action") public String test01(){ System.out.println(dept); return "使用@ImportResource注解读取自定义配置文件生效"; } }
浏览器访问后,控制台和浏览器都正常输出,ok。
浏览器端
控制台端
springboot整合mybatis
ssm里springmvc和spring是一家的,但是mybatis不是,因此需要单独拿出来整合。
(1)pom文件需要添加如下配置。
<!-- mybatis整合需要单独导包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.8</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <!--数据源使用德鲁伊--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.14</version> </dependency>
(2)application.properties中配置数据库连接
# 指定驱动名
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 指定url
spring.datasource.url=jdbc:mysql://localhost:3306/mydb2
# username
spring.datasource.username=root
# password
spring.datasource.password=root
# mybatis映射文件地址,idea放在resource/mapper下
mybatis.mapper-locations=classpath:mappers/*.xml
# 配置包的别名 ?
# mybatis.type-aliases-package=com.boe.domain
# 是否启动驼峰命名规则
mybatis.configuration.map-underscore-to-camel-case=false
(3)指定映射文件和对应接口
映射文件
<?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.boe.dao.UserMapper">
<!--如果设置了包的别名,可以省略为User--> <select id="findUser" resultType="com.boe.domain.User"> SELECT * FROM user; </select> </mapper>
对应接口
package com.boe.dao; import com.boe.domain.User; import org.springframework.stereotype.Repository; import java.util.List; @Repository("usermapper") public interface UserMapper { public List<User> findUser(); }
(4)启动类中使用@MapperScan添加接口扫描
package com; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.boe.dao") //扫描包,UserMapper就在这个包下。 public class MainApp { public static void main(String[] args) { //启动springboot SpringApplication.run(MainApp.class,args); System.out.println("spring boot已启动"); } }
测试,以下为service层和controller层。
controller层
package com.boe.controller; import com.boe.domain.User; import com.boe.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; @Controller @RequestMapping("/user") public class UserController { //注入service层 @Autowired UserService userService = null; //查询user @ResponseBody @RequestMapping("/findUser.action") public List<User> findUser() { List<User> user = userService.queryUser(); System.out.println("controller is runnint"); System.out.println(user); return user; } }
service层
package com.boe.service; import com.boe.dao.UserMapper; import com.boe.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service("userService") public class UserService { //注入mapper @Autowired UserMapper userMapper=null; //查询user public List<User> queryUser(){ System.out.println("service is running"); return userMapper.findUser(); }; }
启动springboot后,访问对应地址,发现能访问到db,控制台输出结果。
浏览器端
控制台端
springboot中使用jsp
springboot原生视图不是使用jsp实现的,如果配置视图解析器访问jsp,浏览器不知道如何处理这个文件,会直接下载处理,为了能让springboot能使用jsp,需要在pom文件中添加如下依赖,如果还涉及json返回的,还需要添加jackson相关的包。
<!--springboot内置tomcat不支持jsp,需要导入如下包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <!-- 部署war包需要将其设置provided --> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>7.0.52</version> <scope>provided</scope> </dependency> <!--springboot内置tomcat不支持jsp,需要导入如上包-->
<!-- json字符串返回相关包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
配置对应视图解析器。
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
测试controller类
package com.boe.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/jsp") public class JspController { @RequestMapping("/test01.action") public String test01(Model model){ System.out.println("jsp controller is running"); //默认保存在request域中 model.addAttribute("name","messi"); return "test"; } }
测试用jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>test jsp</title> </head> <body> <h2>this is jsp from springboot</h2> <h2>${name}</h2> </body> </html>
访问jsp页面测试。
springboot项目部署注意事项
springboot项目测试是在内置的容器中运行的, 打成war包在tomcat运行会出现动态资源访问不到的情况,出现这种情况需要在启动类添加如下配置。
(1)添加@ServletComponentScan注解
(2)启动类需要继承自SpringBootServletInitializer类,通过类的doc文档可以查看到最后提示如果需要部署war包,需要它。
Note that a WebApplicationInitializer is only needed if you are building a war file and deploying it. If you prefer to run an embedded container then you won't need this at all
启动类
package com; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import javax.servlet.annotation.ServletSecurity; @SpringBootApplication @MapperScan("com.boe.dao") //配置扫描dao层接口 @ServletComponentScan //配置这个注解打war包才可以运行,并让如下类继承自SpringBootServletInitializer public class MainApp extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(MainApp.class,args); System.out.println("spring boot已启动"); } }
(3)打包类型选择war,打包后扔tomcat容器运行不能访问动态资源的问题会解决。
以上对springboot入门的整理,springboot比较适合单体项目的快速开发,如果需要做大型分布式项目需要用到springcloud,后续添加。
参考博文:
(1)https://blog.csdn.net/snow_7/article/details/88391192
(2)https://www.cnblogs.com/youngchaolin/p/11825510.html 依赖传递