剖析SpringBoot登录源码
源码地址:https://github.com/zhangzhishun/spring-boot-restfulcrud
一、Spring Boot 简介
- 简化Spring应用开发的一个框架;
- 整个Spring技术栈的一个大整合;
- J2EE开发的一站式解决方案;
二、环境准备
- 环境约束
- jdk1.8:Spring Boot 推荐jdk1.7及以上;java version “1.8.0_112”
- maven3.x:maven 3.3以上版本;
- Apache Maven 3.3.9 IntelliJIDEA2017:IntelliJIDEA 2017.2.2 x64、STS
- SpringBoot 1.5.9.RELEASE:1.5.9;
- 统一环境;
(1)MAVEN设置;
给maven 的settings.xml配置文件的profiles标签添加
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
2、IDEA设置
整合maven进来;
三、分析HelloWord项目
- Spring Boot HelloWorld
功能:浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串;
(1)创建一个maven工程;(jar)
(2)导入spring boot相关的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
(3)编写一个主程序;启动Spring Boot应用
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
(4)编写相关的Controller、Service
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}
(5)运行主程序测试
(6)简化部署
<!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
将这个应用打成jar包,直接使用java -jar的命令进行执行;
四、分析Login登录项目
- 目录树
├─src Java源程序
│ ├─main 主程序
│ │ ├─java
│ │ │ └─com
│ │ │ └─atguigu
│ │ │ └─springboot
│ │ │ ├─component
│ │ │ │ └─LoginHandlerInterceptor 登陆检查
│ │ │ │ └─MyErrorAttributes 给容器中加入我们自己定义的ErrorAttributes
│ │ │ │ └─MyLocaleResolver 可以在连接上携带区域信息
│ │ │ ├─config
│ │ │ │ └─MyMvcConfig 使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
│ │ │ │ └─MyServerConfig注册三大组件:ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean 配置嵌入式的Servlet容器:EmbeddedServletContainerCustomizer
│ │ │ ├─controller
│ │ │ │ └─EmployeeController员工控制器
│ │ │ │ └─LoginController登陆控制器
│ │ │ │ └─MyExceptionHandler异常处理
│ │ │ ├─dao
│ │ │ │ └─DepartmentDao Dao部门数据层
│ │ │ │ └─EmployeeDao Dao员工数据层
│ │ │ ├─entities
│ │ │ │ └─Department 部门类
│ │ │ │ └─Employee 员工类
│ │ │ ├─exception
│ │ │ │ └─UserNotExistException 用户不存在
│ │ │ ├─filter
│ │ │ │ └─MyFilter
│ │ │ ├─listener
│ │ │ │ └─MyListener
│ │ │ └─servlet
│ │ │ │ └─MyServlet
│ │ └─resources
│ │ ├─i18n 国际化工具
│ │ │ └─login_en_US.properties
│ │ │ └─login_zh_CN.properties
│ │ │ └─login_en_US.properties
│ │ ├─public
│ │ │ └─index.html 测试首页
│ │ ├─resources
│ │ │ └─favicon.ico 图标
│ │ ├─static 静态css
│ │ │ └─asserts
│ │ │ ├─css
│ │ │ │ └─bootstrap.min.css
│ │ │ │ └─dashboard.css
│ │ │ │ └─signin.css
│ │ │ ├─img
│ │ │ │ └─bootstrap-solid.svg
│ │ │ └─js
│ │ │ │ └─bootstrap.min.js
│ │ │ │ └─Chart.min.js
│ │ │ │ └─feather.min.js
│ │ │ │ └─jquery-3.2.1.slim.min.js
│ │ │ │ └─popper.min.js
│ │ └─templates html页面
│ │ ├─commons
│ │ │ └─bar.html
│ │ ├─emp
│ │ │ └─add.html
│ │ │ └─list.html
│ │ │ └─error
│ │ │ └─dashboard.html
│ │ │ └─login.html
│ │ │ └─success.html
│ │ └─application.properties
│ │ └─springmvc.xml
│ └─test 测试java
│ └─java
│ └─com
│ └─example
│ └─login
│ └─lLoginApplicationTests
├─HELP.md 帮助文档
├─login.iml
├─mvnw
├─mvnw.cmd
├─pom.xml pom配置文件
- 分析登陆过程
(1)登录界面html,向/user/login发起post请求
<form class="form-signin" th:action="@{/user/login}" method="post">
<img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" src="asserts/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>
<!--判断-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="password" class="form-control" placeholder="Password" 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>
(2)LoginController处理/user/login发起得post请求,重定向到main.html
@PostMapping(value = "/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> map, HttpSession session){
if(!StringUtils.isEmpty(username) && "123456".equals(password)){
//登陆成功,防止表单重复提交,可以重定向到主页
session.setAttribute("loginUser",username);
return "redirect:/main.html";
}else{
//登陆失败
map.put("msg","用户名密码错误");
return "login";
}
}
(3)MyMvcConfig处理"/main.html"请求,转到dashboard.html页面
registry.addViewController("/main.html").setViewName("dashboard");
- 分析增加员工过程
(1)Get请求来到员工添加页面,返回emp文件夹下的add.html页面
//来到员工添加页面
@GetMapping("/emp")
public String toAddPage(Model model){
//来到添加页面,查出所有的部门,在页面显示
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts",departments);
return "emp/add";
}
(2)Post请求将员工添加,然后返回emp文件夹下的list.html页面
//员工添加
//SpringMVC自动将请求参数和入参对象的属性进行一一绑定;要求请求参数的名字和javaBean入参的对象里面的属性名是一样的
@PostMapping("/emp")
public String addEmp(Employee employee){
//来到员工列表页面
System.out.println("保存的员工信息:"+employee);
//保存员工
employeeDao.save(employee);
// redirect: 表示重定向到一个地址 /代表当前项目路径
// forward: 表示转发到一个地址
return "redirect:/emps";
}
- 分析删除员工列表过程
//员工删除
@DeleteMapping("/emp/{id}")
public String deleteEmployee(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}
- 分析修改员工过程
//员工修改;需要提交员工id;
@PutMapping("/emp")
public String updateEmployee(Employee employee){
System.out.println("修改的员工数据:"+employee);
employeeDao.save(employee);
return "redirect:/emps";
}
- 分析查看员工列表过程
//查询所有员工返回列表页面
@GetMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAll();
//放在请求域中
model.addAttribute("emps",employees);
// thymeleaf默认就会拼串
// classpath:/templates/xxxx.html
return "emp/list";
}