第一个SpringBoot程序
jdk1.8
maven3.6.1
SpringBoot最新
IDEA
官方:提供了一个快速生成的网站,IDEA集成了这个网站(首选)
https://start.spring.io/
原理
https://mp.weixin.qq.com/s/hzRwZvjYSX-dy-9Drz94aQ
pom.xml
- spring-boot-dependencies:核心依赖在父工程中
- 我们在写入或者引入一些SpringBoot依赖时,不需要指定版本,就是因为有这些版本仓库
启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
SpringBoot的启动场景,比如spring-boot-starter-web,就会自动导入web环境所有依赖
SpringBoot会将所有场景都变成启动器
需要什么功能,找到对应的启动器就可以
主程序
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
注解
@SpringBootConfiguration:SpringBoot的配置
@Configuration:spring配置类
@Component:说明是个spring组件
@EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
@Import({Registrar.class)}:注册
@Import({AutoConfigurationImportSelector.class}):自动配置导入选择
SpringApplication
这个类主要做了以下四件事情:
1、推断应用的类型是普通的项目还是Web项目
2、查找并加载所有可用初始化器 , 设置到initializers属性中
3、找出所有的应用程序监听器,设置到listeners属性中
4、推断并设置main方法的定义类,找到运行的主类
yaml
SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的
-
application.properties -
-
application.yml -
name: cc
student:
name: cc
age: 3
student2: {name: cc,age: 3}
pets:
- cat
- dog
- pig
pets2: [cat,dog,pig]
给属性赋值的几种方法
用@value给实体类每个字段赋值,或者用properties文件关联,或者yaml文件关联:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
1.实体类
@ConfigurationProperties(prefix = “person”):和配置文件赋值的对象绑定(给属性赋值)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
2.application.yaml
person:
name: cc
age: 3
happy: false
birth: 2022/02/12
maps: {k1: v1,k2: v2}
lists:
- code
- girl
- music
dog:
name: 旺财
age: 3
3.测试
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
JSR303校验
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.6.3</version></dependency>
@Validatedpublic class Person { @Email(message="邮箱格式错误") private String name;
多环境切换
多配置文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本;
例如:
application-test.properties 代表测试环境配置
application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件;
我们需要通过一个配置来选择需要激活的环境:
spring.profiles.active=dev#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;
我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
yaml的多文档块
和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件,更加方便了 !
server: port: 8081 spring: profiles: active: prod
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件:
优先级1:项目路径下的config文件夹配置文件优先级2:项目路径下配置文件优先级3:资源路径下的config文件夹配置文件优先级4:资源路径下配置文件
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
分析自动配置原理
我们以**HttpEncodingAutoConfiguration(Http编码自动配置)**为例解释自动配置原理;
一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!
- 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
- 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
- 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
- 配置文件能配置什么就可以参照某个功能对应的这个属性类
精髓
1、SpringBoot启动会加载大量的自动配置类
2、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
**xxxxAutoConfigurartion:自动配置类;**给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
SpringBoot Web开发
静态资源导入
1、在SpringBoot中可以使用以下方式处理静态资源:
- webjars 访问方式:localhost:8080/webjars/
- public,static,/**,resources 访问方式:localhost:8080/
2、优先级
resources > static(默认)> public
首页如何定制
新建一个 index.html ,在我们上面的3个目录中任意一个
Thymeleaf
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
我们首先得按照SpringBoot的自动配置原理看一下我们这个Thymeleaf的自动配置规则,在按照那个规则,我们进行使用。
我们去找一下Thymeleaf的自动配置类:ThymeleafProperties
@ConfigurationProperties( prefix = "spring.thymeleaf")public class ThymeleafProperties { private static final Charset DEFAULT_ENCODING; public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html"; private boolean checkTemplate = true; private boolean checkTemplateLocation = true; private String prefix = "classpath:/templates/"; private String suffix = ".html"; private String mode = "HTML"; private Charset encoding;}
我们可以在其中看到默认的前缀和后缀!
我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。
使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可!
@RequestMapping("/t1")public String test1(Model model){
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>Title</title></head><body><div th:text="${msg}"></div></body></html>
注意命名空间:
xmlns:th="http://www.thymeleaf.org"
扩展使用SpringMVC
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解;我们去自己写一个;我们新建一个包叫config,写一个类MyMvcConfig;
全面接管SpringMVC
官方文档:
If you want to take complete control of Spring MVCyou can add your own @Configuration annotated with @EnableWebMvc.
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个@EnableWebMvc。
我们发现所有的SpringMVC自动配置都失效了!回归到了最初的样子;
当然,我们开发中,不推荐使用全面接管SpringMVC
总结一句话:@EnableWebMvc将WebMvcConfigurationSupport组件导入进来了;
而导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能!
在SpringBoot中会有非常多的扩展配置,只要看见了这个,我们就应该多留心注意~
员工管理系统
首页实现
1、config包下编写MyMvcConfig类
@Configurationpublic class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/index.html").setViewName("index"); }}
2、静态资源用thymeleaf接管
xmlns:th="http://www.thymeleaf.org"
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
3、application.properties
#关闭模板引擎的缓存spring.thymeleaf.cache=false
页面国际化
1、编写Login bundle
在resources文件夹下建i18n文件夹
可视化编写
2、静态资源用thymeleaf接管
th:text="#{login.tip}"
[[#{login.remember}]]
<body class="text-center"> <form class="form-signin" action="dashboard.html"> <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72"> <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1> <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus=""> <input type="password" class="form-control"th:placeholder="#{login.password}" required=""> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me"> [[#{login.remember}]] </label> </div> <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button> <p class="mt-5 mb-3 text-muted">? 2017-2018</p> <a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a> </form></body>
3、给中英文按钮增加链接
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a><a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
4、自定义国际化组件LocaleResolver
public class MyLocalResolver implements LocaleResolver {
5、将组件配置到容器中(@Bean)
@Configurationpublic class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/index.html").setViewName("index"); }
登录功能
编写控制类
@Controllerpublic class LoginController { @RequestMapping("/user/login") public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
MyMvcConfig中添加视图解析
registry.addViewController("/main.html").setViewName("dashboard");
登录拦截:
public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginUser = request.getSession().getAttribute("loginUser"); if(loginUser==null){ request.setAttribute("msg","没有权限,请先登录"); request.getRequestDispatcher("/index.html").forward(request,response); return false; }else { return true; } }}
配置拦截器: MyMvcConfig重写addInterceptors
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login", "/css/**","/js/**","/img/**"); }
展示员工列表
1、提取公共页面
th:fragment=“sidebar”
th:replace="~{common/commons::sidebar}"
如果要传递参数,可以直接使用()传参,接收判断即可
2、列表循环展示
@RequestMapping("/emps")public String list(Model model){ Collection<Employee> employees = employeeDao.getAll(); model.addAttribute("emps",employees); return "emp/list";}
增加员工
@GetMapping("/emp")public String toAddpage(Model model){
#时间日期格式化spring.mvc.format.date=yyyy-MM-dd
<form th:action="@{/emp}" method="post"> <div class="form-group"> <label>LastName</label> <input type="text" name="lastName" class="form-control" placeholder="海绵宝宝"> </div> <div class="form-group"> <label>Email</label> <input type="email" name="email" class="form-control" placeholder="1176244270@qq.com"> </div> <div class="form-group"> <label>Gender</label><br> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="gender" value="1"> <label class="form-check-label">男</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="gender" value="0"> <label class="form-check-label">女</label> </div> </div> <div class="form-group"> <label>department</label> <select class="form-control" name="department.id"> <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option> </select> </div> <div class="form-group"> <label>Birth</label> <input type="text" name="birth" class="form-control" placeholder="2022-2-14"> </div> <button type="submit" class="btn btn-primary">添加</button></form>
修改员工
隐藏域:
<input type="hidden" name="id" th:value="${emp.getId()}">
<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a>
删除员工
404
templates文件夹下建error文件夹,新建404.html,自动跳转
x-admin 后台模板
回顾
整合JDBC
https://mp.weixin.qq.com/s/2gO3010iV34uGUs4FCGvmA
1、我去新建一个项目测试:springboot-data-jdbc ; 引入相应的模块!基础模块
2、项目建好之后,发现自动帮我们导入了如下的启动器:
<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>
3、编写yaml配置文件连接数据库;
spring: datasource: username: root password: 123456
4、配置完这一些东西后,我们就可以直接去使用了,因为SpringBoot已经默认帮我们进行了自动配置;去测试一下
@RestControllerpublic class JDBCController { @Autowired JdbcTemplate jdbcTemplate;
整合Druid数据源
配置数据源
1、添加上 Druid 数据源依赖。
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version></dependency>
2、切换数据源;之前已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源,但可以 通过 spring.datasource.type 指定数据源。
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
3、可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等设置项;
spring: datasource: username: root password: 123456
4、导入Log4j 的依赖
5、现在需要程序员自己为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了;我们需要 自己添加 DruidDataSource 组件到容器中,并绑定属性;
@Configurationpublic class DruidConfig { @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druidDataSource() { return new DruidDataSource(); }}
配置Druid数据源监控
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。
所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理;
@Configurationpublic class DruidConfig { @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druidDataSource() { return new DruidDataSource(); }
整合Mybatis框架
1、导入 MyBatis 所需要的依赖
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version></dependency>
2、配置数据库连接信息
spring.datasource.username=rootspring.datasource.password=123456spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&useSSL=true&characterEncoding=utf-8spring.datasource.driver-class-name=com.mysql.jdbc.Driver#整合mybatismybatis.type-aliases-package=com.cc.pojomybatis.mapper-locations=classpath:mybatis/mapper/*.xml
3、测试数据库是否连接成功!
4、创建实体类,导入 Lombok!
5、创建mapper目录以及对应的 Mapper 接口
@Mapper
6、对应的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.cc.mapper.UserMapper"> <select id="queryUserList" resultType="User"> select * from mybatis.user </select> <select id="queryUserById" resultType="User"> select * from mybatis.user where id = #{id} </select> <insert id="addUser" parameterType="User"> insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{psw}); </insert> <update id="updateUser" parameterType="User"> update mybatis.user set name = #{name},pwd=#{pwd} where id = #{id}; </update> <delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id}; </delete></mapper>
7、maven配置资源过滤问题
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource></resources>
8、编写Controller 进行测试!
@RestControllerpublic class UserController { @Autowired private UserMapper userMapper; @GetMapping("/queryUserList") public List<User> queryUserList(){ List<User> userList = userMapper.queryUserList(); return userList; }
SpringSecurity
shiro SpringSecurity
认识SpringSecurity
Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!
记住几个类:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。
“认证”(Authentication)
身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。
身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。
“授权” (Authorization)
授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。
这个概念是通用的,而不是只在Spring Security 中存在。
实战测试
实验环境搭建
1、新建一个初始的springboot项目web模块,thymeleaf模块
2、导入静态资源
3、controller跳转
@Controllerpublic class RouterController { @RequestMapping({"/","/index"}) public String index(){ return "index"; } @RequestMapping("/toLogin") public String toLogin(){ return "views/login"; } @RequestMapping("/level1/{id}") public String level1(@PathVariable("id") int id){ return "views/level1/"+id; } @RequestMapping("/level2/{id}") public String level2(@PathVariable("id") int id){ return "views/level2/"+id; } @RequestMapping("/level3/{id}") public String level3(@PathVariable("id") int id){ return "views/level3/"+id; }}
4、测试实验环境是否OK!
认证和授权
1、引入 Spring Security 模块
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency>
2、编写 Spring Security 配置类
参考官网:https://spring.io/projects/spring-security
查看我们自己项目中的版本,找到对应的帮助文档:
https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5 #servlet-applications 8.16.4
3、定制请求的授权规则
4、在configure()方法中加入以下配置,开启自动配置的登录功能!
5、定义认证规则,重写configure(AuthenticationManagerBuilder auth)方法
6、测试,发现会报错!
There is no PasswordEncoder mapped for the id “null”
7、原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码
权限控制和注销
1、开启自动配置的注销的功能
2、我们在前端,增加一个注销的按钮,index.html 导航栏中
<a class="item" th:href="@{/logout}"> <i class="address card icon"></i> 注销</a>
3、我们可以去测试一下,登录成功后点击注销,发现注销完毕会跳转到登录页面!
4、但是,我们想让他注销成功后,依旧可以跳转到首页,该怎么处理呢?
5、测试,注销完毕后,发现跳转到首页OK
6、我们现在又来一个需求:用户没有登录的时候,导航栏上只显示登录按钮,用户登录之后,导航栏可以显示登录的用户信息及注销按钮!还有就是,比如kuangshen这个用户,它只有 vip2,vip3功能,那么登录则只显示这两个功能,而vip1的功能菜单不显示!这个就是真实的网站情况了!该如何做呢?
我们需要结合thymeleaf中的一些功能
sec:authorize=“isAuthenticated()”:是否认证登录!来显示不同的页面
Maven依赖:
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.4.RELEASE</version></dependency>
7、修改我们的 前端页面
导入命名空间
xmlns:sec=“http://www.thymeleaf.org/extras/spring-security”
修改导航栏,增加认证判断
<div class="right menu"> <div sec:authorize="!isAuthenticated()"> <a class="item" th:href="@{/toLogin}"> <i class="address card icon"></i> 登录 </a> </div> <div sec:authorize="isAuthenticated()"> <a class="item"> 用户名:<span sec:authentication="name"></span> 角色:<span sec:authentication="authorities"></span> </a> </div> <div sec:authorize="isAuthenticated()"> <a class="item" th:href="@{/logout}"> <i class="sign-out icon"></i> 注销 </a> </div>
8、重启测试,我们可以登录试试看,登录成功后确实,显示了我们想要的页面;
9、如果注销404了,就是因为它默认防止csrf跨站请求伪造,因为会产生安全问题,我们可以将请求改为post表单提交,或者在spring security中关闭csrf功能;我们试试:在 配置中增加 http.csrf().disable();
10、我们继续将下面的角色功能块认证完成!
<div class="column" sec:authorize="hasRole('vip1')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 1</h5> <hr> <div><a th:href="@{/level1/1}"><i class="bullhorn icon"></i> Level-1-1</a></div> <div><a th:href="@{/level1/2}"><i class="bullhorn icon"></i> Level-1-2</a></div> <div><a th:href="@{/level1/3}"><i class="bullhorn icon"></i> Level-1-3</a></div> </div> </div> </div></div><div class="column" sec:authorize="hasRole('vip2')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 2</h5> <hr> <div><a th:href="@{/level2/1}"><i class="bullhorn icon"></i> Level-2-1</a></div> <div><a th:href="@{/level2/2}"><i class="bullhorn icon"></i> Level-2-2</a></div> <div><a th:href="@{/level2/3}"><i class="bullhorn icon"></i> Level-2-3</a></div> </div> </div> </div></div><div class="column" sec:authorize="hasRole('vip3')"> <div class="ui raised segment"> <div class="ui"> <div class="content"> <h5 class="content">Level 3</h5> <hr> <div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div> <div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div> <div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div> </div> </div> </div>
11、测试一下!
12、权限控制和注销搞定!
记住我
现在的情况,我们只要登录之后,关闭浏览器,再登录,就会让我们重新登录,但是很多网站的情况,就是有一个记住密码的功能,这个该如何实现呢?很简单
1、开启记住我功能
2、我们再次启动项目测试一下,发现登录页多了一个记住我功能,我们登录之后关闭 浏览器,然后重新打开浏览器访问,发现用户依旧存在!
思考:如何实现的呢?其实非常简单
我们可以查看浏览器的cookie
3、我们点击注销的时候,可以发现,spring security 帮我们自动删除了这个 cookie
4、结论:登录成功后,将cookie发送给浏览器保存,以后登录带上这个cookie,只要通过检查就可以免登录了。如果点击注销,则会删除这个cookie,具体的原理我们在JavaWeb阶段都讲过了,这里就不在多说了!
定制登录页
现在这个登录页面都是spring security 默认的,怎么样可以使用我们自己写的Login界面呢?
1、在刚才的登录页配置后面指定 loginpage
http.formLogin().loginPage("/toLogin");
2、然后前端也需要指向我们自己定义的 login请求
<a class="item" th:href="@{/toLogin}"> <i class="address card icon"></i> 登录</a>
3、我们登录,需要将这些信息发送到哪里,我们也需要配置,login.html 配置提交请求及方式,方式必须为post:
<form th:action="@{/login}" method="post"> <div class="field"> <label>Username</label> <div class="ui left icon input"> <input type="text" placeholder="Username" name="username"> <i class="user icon"></i> </div> </div> <div class="field"> <label>Password</label> <div class="ui left icon input"> <input type="password" name="password"> <i class="lock icon"></i> </div> </div> <div class="field"> <input type="checkbox" name="remember">记住我 </div>
4、这个请求提交上来,我们还需要验证处理,怎么做呢?我们可以查看formLogin()方法的源码!我们配置接收登录的用户名和密码的参数!
http.formLogin() .usernameParameter("username") .passwordParameter("password") .loginPage("/toLogin") .loginProcessingUrl("/login");
5、在登录页增加记住我的多选框
<input type="checkbox" name="remember"> 记住我
6、后端验证处理!
Swagger
- 号称世界上最流行的API框架
- RestFul API文档在线自动生成工具=>API文档与API定义同步更新
- 直接运行,可以在线测试API接口
- 支持多种语言:(Java、PHP…)
在项目中使用Swagger需要springfox
SpringBoot集成Swagger
1、新建SpringBoot-web项目
2、导入相关依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version></dependency><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version></dependency>
3、编写一个hello工程
4、配置swagger==>Confige
@Configuration@EnableSwagger2
5、测试运行 http://localhost:8080/swagger-ui.html
配置Swagger
Swagger的bean实例docket
@EnableSwagger2
Swagger配置扫描接口
Docket.select()
@Beanpublic Docket docket(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .enable(false) .select()
配置是否启动Swagger
.enable(false)
如果为false,则Swagger不能在浏览器中访问
只希望我的Swagger在生产环境中使用,在发布的时候不使用?
- 判断是不是生产环境 flag=false
- 注入enable(flag)
@Beanpublic Docket docket(Environment environment){
配置API文档分组
.groupName("cc")
如何配置多个分组:多个Docket实例即可
@Beanpublic Docket docket1(){ return new Docket(DocumentationType.SWAGGER_2).groupName("A");}@Beanpublic Docket docket2(){ return new Docket(DocumentationType.SWAGGER_2).groupName("B");}@Beanpublic Docket docket3(){ return new Docket(DocumentationType.SWAGGER_2).groupName("C");}
加注释
实体类
接口方法:
@ApiOperation("hello控制类")@GetMapping("/hello")public String hello(){ return "hello";}
参数
@GetMapping("/hello")public String hello(@ApiParam("用户名") String username){ return "hello"+username;}
测试
restful风格传值
@GetMapping("/hello2/{username}")public String hello2(@ApiParam("用户名") @PathVariable("username") String username){ return "hello"+username;}
总结
通过Swagger给一些难理解的属性或接口增加注释信息
接口文档实时更新
可以在线测试
【注意点】在正式发布时候关闭Swagger(出于安全考虑)而且节省运行内存
任务
异步任务
1、写一个service,线程停止三秒
@Servicepublic class AsyncService { public void hello(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("数据正在处理"); }}
2、写一个controller,调用业务
@RestControllerpublic class AsyncController { @Autowired AsyncService asyncService; @RequestMapping("/hello") public String hello(){ asyncService.hello();
3、测试
发现服务器请求三秒后返回ok
开启多线程的异步方法
业务实现runnable接口重写run方法,controller创建线程对象代理接口实现类对象,调用start()开启线程
@Servicepublic class AsyncService implements Runnable{ @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("数据正在处理"); }}
@RestControllerpublic class AsyncController { @Autowired AsyncService asyncService; @RequestMapping("/hello") public String hello(){ Thread thread = new Thread(asyncService); thread.start(); return "ok"; }}
测试:
发现浏览器迅速显示ok,但控制台的"数据正在处理"仍然需要三秒才输出。
使用Spring
@Async @EnableAsync
@Servicepublic class AsyncService {
邮件任务
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId></dependency>
spring.mail.username=xxx你的邮箱地址spring.mail.password=xxxx授权码spring.mail.host=smtp.qq.com#开启加密验证spring.mail.properties.mail.smtp.ssl.enable=true
@SpringBootTestclass Springboot09TestApplicationTests { @Autowired JavaMailSenderImpl mailSender; @Test void contextLoads() {
@Testvoid contextLoads2() throws MessagingException {
定时任务
TaskScheduler 任务调度者
TaskExecutor 任务执行者
@EnableScheduling 开启定时功能的注解
@Scheduled 什么时候执行
Cron表达式:
30 15 10 * * ? 每天10点15分30秒执行一次
30 0/5 10,18 * * ? 每天10点和18点,每隔5分钟执行一次
0 15 10 ? * 1-6 每个月周一到周六10点15分执行一次
@Servicepublic class ScheduledService {
分布式Dubbo+Zookeeper
RPC 远程过程调用
RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
RPC两个核心模块:通讯,序列化。
Dubbo
Apache Dubbo |?d?b??| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
dubbo官网 http://dubbo.apache.org/zh-cn/index.html
环境搭建:
https://mp.weixin.qq.com/s/sKu9-vH7NEpUd8tbxLRLVQ
Dubbo-admin是一个监控管理后台,查看注册了哪些服务,哪些服务被消费了
Dubbo:jar包
|