侵权联系博主 及时删除 博主q(2209265211)
-
springboot简介
SpringBoot是由Pivotal团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。 -
特点
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置。
在controller层写一个helloworld程序
@RestController:表示带返回结果的Controller
@RequestMapping("/hello"):向浏览器发送localhost:8080/hello即可跳转到这个页面
-
springboot配置文件 config
官方推荐我们使用yaml的文件形式来配置 application.yaml
yaml的语法可以参考菜鸟教程 :https://www.runoob.com/w3cnote/yaml-intro.html
person:
name: 张三
age: 3
birth: 2021/4/14
map: {k1: v1,k2: v2,k3: v3}
list:
- music
- whh
set:
- 1
- 2
dog:
name: 旺财
age: 3
dog:
name: 小黑
age: 200
person类定义:
/*
@Component把普通pojo实例化到spring容器中
@ConfigurationProperties 相当于加载application.yaml中的 prefix后的东西
@PropertySource 加载自己定义的配置文件 classpath: 文件名.properties
@Autowired 自动注入
classpath 就是自己的resources文件夹下面的
*/
@Component
//@ConfigurationProperties(prefix = "person")
@PropertySource("classpath:test.properties")
public class Person {
@Value("${name}")
private String name;
@Value("${age}")
private int age;
@Value("${birth}")
private Date birth;
@Value("#{{k1:'v1',k2:'v2'}}")
private Map<String,Object> map;
@Value("${list}")
private List<Object> list;
@Value("${set}")
private Set<Object> set;
@Autowired
private Dog dog;
public Person() {
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Date getBirth() {
return birth;
}
public Map<String, Object> getMap() {
return map;
}
public List<Object> getList() {
return list;
}
public Set<Object> getSet() {
return set;
}
public Dog getDog() {
return dog;
}
public Person(String name, int age, Date birth, Map<String, Object> map, List<Object> list, Set<Object> set, Dog dog) {
this.name = name;
this.age = age;
this.birth = birth;
this.map = map;
this.list = list;
this.set = set;
this.dog = dog;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public void setList(List<Object> list) {
this.list = list;
}
public void setSet(Set<Object> set) {
this.set = set;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", map=" + map +
", list=" + list +
", set=" + set +
", dog=" + dog +
'}';
}
}
@Repository将EmployeeDao注入到spring容器中
@Repository
public class EmployeeDao {
//模拟数据库
private static Map<Integer, Employee> employees = null;
@Autowired
private DepartmentDao departmentDao;
static {
employees = new HashMap<Integer, Employee>();
employees.put(1001,new Employee(1001,"AA","A246542@qq.com",0,new Department(101,"教学部")));
employees.put(1002,new Employee(1002,"BB","B246542@qq.com",1,new Department(102,"市场部")));
employees.put(1003,new Employee(1003,"CC","C246542@qq.com",0,new Department(103,"教研部")));
employees.put(1004,new Employee(1004,"DD","D246542@qq.com",1,new Department(104,"运营部")));
employees.put(1005,new Employee(1005,"EE","E246542@qq.com",0,new Department(105,"后勤部")));
}
//主键自增
private static Integer initId = 1006;
//添加一个员工
public void save(Employee employee) {
if(employee.getId() == null) {
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
employees.put(employee.getId(),employee);
}
//获取所有员工信息
public Collection<Employee> getAll(){
return employees.values();
}
//通过id查询员工
public Employee getEmployeeById(Integer id) {
return employees.get(id);
}
//通过id删除员工
public void delete(Integer id) {
employees.remove(id);
}
}
//部门dao
@Repository
public class DepartmentDao {
//模拟数据库
private static Map<Integer, Department> departments = null;
static {
departments = new HashMap<Integer, Department>();
departments.put(101,new Department(101,"教学部"));
departments.put(102,new Department(102,"市场部"));
departments.put(103,new Department(103,"教研部"));
departments.put(104,new Department(104,"运营部"));
departments.put(105,new Department(105,"后勤部"));
}
//获取所有部门信息
public Collection<Department> getDepartments(){
return departments.values();
}
//通过id获取部门信息
public Department getDepartmentById(Integer id) {
return departments.get(id);
}
}
Department类与Employee类的定义
因为代码太多就不把getset构造方法导入
//部门表
public class Department {
private Integer id;
private String departmentName;
}
//员工表
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;// 0:女 1:男
private Department department;
private Date birth;
}
在前端上采用thymeleaf来操作数据
-
thymeleaf语法总结
参考官方文档 https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#preface
留下不会英语的泪
命名空间: xmlns:th=“http://www.thymeleaf.org” -
springboot整合thymeleaf
需要在pom.xml中导入如下依赖
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
其他就全是些和业务相关的东西没什么技术 就不再做记录
上面5 使用的是自己模拟的数据 接下来就连接数据库后可使用数据库中的数据
这里介绍使用原生的jdbc连接数据库 下面再介绍整合mybatis
连接数据库当然需要导入相应的包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
还需要配置相应的username 和password 和url
这里在application.yaml 中配置 当然也可以在application.properties中配置
spring:
datasource:
username: root
password: 123
#serverTimezone 时区的配置
url: jdbc:mysql://localhost:3306/ppp?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
然后在controller中验证是否连接即可
sql语句根据自己的数据库写即可
使用的是原生的jdbc连接jdbcTemplate功能不是很强大 前面写的一个web项目涉及到了一对多我只会使用mybatis来实现这个功能
@RestController
public class MyController {
@Autowired
JdbcTemplate jdbcTemplate;
@GetMapping("/index")
public List<Map<String,Object>> getAll(){
String sql = "select * from ppp.employee";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
System.out.println(maps);
return maps;
}
}
导入他们整合的包
<!--整合mybatis 需要的包 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
还是直接用一个例子来学习最好
整合mybatis就需要数据库 数据如下
CREATE TABLE `department` (
`id` int(11) primary key,
`departmentName` varchar(20)
)
INSERT INTO `department` VALUES (101, '教学部');
INSERT INTO `department` VALUES (102, '市场部');
INSERT INTO `department` VALUES (103, '教研部');
INSERT INTO `department` VALUES (104, '运营部');
INSERT INTO `department` VALUES (105, '开发部');
对应类pojo
public class Department {
private int id;
private String departmentName;
}
在配置文件中书写一下信息:
mybatis.type-aliases-package:扫描的包 数据库 对应的类
mybatis.mapper-locations:xxxMapper.xml的地址 *.xml直接扫描当前目录下的所有xml
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql://localhost:3306/ppp?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#整合mybatis
mybatis.type-aliases-package=com.yxx.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
Mapper类:
// @Mapper 表示了这是一个mybatis的mapper类
//@Repository 将该类注入spring容器
@Mapper
@Repository
public interface DepartmentMapper {
public List<Department> queryAll();
public Department queryById(@Param("id") int id);
public void updateById(Department department);
public void add(Department department);
public void del(@Param("id") int id);
}
mapper.xml
mapper namespace="com.yxx.mapper.DepartmentMapper namespace 必须是mapper类的路径这样才能相对应
<?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.yxx.mapper.DepartmentMapper">
<select id="queryAll" resultType="Department">
select * from department
</select>
<select id="queryById" resultType="Department">
select * from department where id = #{id}
</select>
<update id="updateById" parameterType="Department">
update department set departmentName = #{departmentName} where id = #{id}
</update>
<insert id="add" parameterType="Department">
insert into department(id,departmentName) values (#{id},#{departmentName})
</insert>
<delete id="del">
delete from department where id = #{id}
</delete>
</mapper>
接下来在controller中验证即可
// @RestController 带放回结果的Controller
@RestController
public class DepartmentController {
//自动注入即可 因为@Repository将DepartmentMapper注入到了spring容器中
@Autowired
private DepartmentMapper departmentMapper;
@GetMapping("/queryAll")
public List<Department> queryAll(){
List<Department> departments = departmentMapper.queryAll();
return departments;
}
@GetMapping("/queryById/{id}")
public Department queryById(@PathVariable("id") int id){
return departmentMapper.queryById(id);
}
@GetMapping("/updateById")
public String updateById(){
Department department = new Department(105,"开发部");
departmentMapper.updateById(department);
return "update-ok";
}
@GetMapping("/add")
public String add(){
Department department = new Department(107,"小麦部");
departmentMapper.add(department);
return "add-ok";
}
@GetMapping("/del")
public String del(){
departmentMapper.del(107);
return "del-ok";
}
}
正如你可能知道的两个应用程序的两个主要区域是“认证”和“授权”(或者访问控制)。这两个主要区域是Spring Security 的两个目标。“认证”,是建立一个他声明的主题的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统)。“授权”指确定一个主体是否允许在你的应用程序执行一个动作的过程。为了抵达需要授权的店,主体的身份已经有认证过程建立。这个概念是通用的而不只在Spring Security中。
Security是搞安全的框架 包含授权和认证 还有一个shiro安全框架
首先还是导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.4.5</version>
</dependency>
我们需要完成Security的授权和认证
我们在自己写的配置类中需要继承WebSecurityConfigurerAdapter 来实现他的方法来完成授权与认证
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人都可以访问 功能页只有具有权限的人才能访问
//.antMatchers("/level1/**").hasRole("vip1")设置的是url里的路径
//不是真实路径
//必须.hasRole("vip1")拥有这个权限才可以访问.antMatchers("/level1/**")
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限的话 默认跳到login页面
//loginPage定制登录页
http.formLogin().loginPage("/toLogin");
//注销 注销后跳到首页
http.csrf().disable();//关闭csrf功能 不关可能导致登出失败
http.logout().logoutSuccessUrl("/");
//开启记住我功能
http.rememberMe().rememberMeParameter("remember");
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//inMemoryAuthentication()从内存中读数据 正常应该在数据库中去读
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("root").password(new BCryptPasswordEncoder().encode("123")).roles("vip1", "vip2", "vip3").and()
.withUser("yxx").password(new BCryptPasswordEncoder().encode("123")).roles("vip2").and()
.withUser("ppp").password(new BCryptPasswordEncoder().encode("123")).roles("vip2", "vip3");
}
}
@EnableWebSecurity:表示我们开启WebSecurity的功能
其他的在代码注解中写的很完整
我还没去学 等以后学了在补充 先挖个坑
springboot整合swagger
swagger是什么?
Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。
Swagger 的优势
支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。
老规矩导入依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
导入该依赖后启动项目即可访问 localhost:8080/swagger-ui.html
在该路径下即可查看自己配置的东西
在配置类中配置相关信息:
@Configuration
@EnableSwagger2 //开启swagger2 就可以访问 http://localhost:8080/swagger-ui.html
//多个分组 只需要多个Docket即可
public class SwaggerConfig {
//配置swagger 的 Docket 的bean实例
@Bean
public Docket docket(Environment environment) {
//获取当前项目的环境
Profiles profiles = Profiles.of("dev");
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("yxx")
//enable 是否开启swagger2
.enable(flag)
.select()
//RequestHandlerSelectors,配置要扫描接口的方式
//basePackage 指定要扫描的包
//any 扫描全部
//none 不扫描
//withClassAnnotation 扫描类上的注解
//withMethodAnnotation 扫描方法上的注解
.apis(RequestHandlerSelectors.basePackage("com.yxx.controller"))
//paths() 过滤什么路径
//.paths(PathSelectors.ant("/index"))
.build();
}
@Bean
public Docket docket2() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("a");
}
@Bean
public Docket docket3() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("b");
}
//配置swagger的信息info
public ApiInfo apiInfo() {
Contact DEFAULT_CONTACT = new Contact("yxx", "", "2209265211@qq.com");
return new ApiInfo(" yxx Api Documentation", "学习", "2.0", "urn:tos", DEFAULT_CONTACT, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList());
}
}
还有一个@ApiXXX的东西是给swagger-ui.html上书写注释的东西 贴上代码更好理解
//@ApiXXX就是加注释 在swagger中能够看到这些注释
@ApiModel("用户类")//给类加注释
public class User {
@ApiModelProperty("用户名")//给类中属性
private String name;
@ApiModelProperty("密码")
private String password;
}
/*
@Api 给Controller加注释
@ApiOperation 给Controller中的方法加注释
@ApiParam 给Controller中的方法中的参数加注释
@ApiModel 给实体类加注释
@ApiModelProperty 给实体类的属性加注释
*/
//这个是controller中的代码
@Api("我的控制类")
@RestController
public class MyController {
@RequestMapping("/hello")
public String hello() {
return "hello";
}
//只要我们的接口 返回值是一个实体类 就会被扫描到swagger中
@PostMapping("/user")
public User user() {
return new User();
}
@ApiOperation("username控制")
@GetMapping("/username")
public String username(@ApiParam("用户名") String username) {
return "hello" + username;
}
}
实际效果出来如下:
异步任务 邮件任务 定时任务
好像并没有什么讲的 就几个注解
@EnableAsync //开启异步任务 在入口类中添加
@Async //表示这是一个异步方法
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
需要配置相关
spring.mail.username=XXX //自己的邮箱 写全路径 包括@XX.com
spring.mail.password=XXX //需要自己去自己的邮箱开启pop3服务 获取授权码
spring.mail.host=smtp.163.com
在test中测试即可
不知道为什么我用qq邮箱会出错 但用163就没问题
@Autowired
MailSender mailSender;
@Test
void contextLoads() {
//一个简单的邮件
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("springboot学习");
message.setText("springboot");
message.setTo("XXX");//目标邮箱
message.setFrom("XXX");//发送邮箱
mailSender.send(message);
}
@EnableScheduling //开启定时功能 在入口类中添加
@Service
public class ScheduledService {
//cron表达式
//秒 分 时 日 月 周几
@Scheduled(cron = "40 16 21 * * *") //表示这是一个定时方法
public void hello(){
System.out.println("你被执行了!");
}
}
cron表达式用起来非常不舒服 的是没办法你必须用