目录 [TOC]
martinfowler关于微服务的论文
1. 项目搭建 Demo IDEA:new project,然后spring initializr
springBoot的作用简单说就是:简化开发
写Demo时,直接再springBootApplication启动类 同级目录 创建 controller service dao等即可
比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.yue.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @Controller public class HelloController { @ResponseBody @RequestMapping("/hello") public String hello(){ return "SpringBoot for WebCrud"; } @RequestMapping("/success") public String success(Map<String,Object> map){ map.put("user","胖子"); return "success"; } }
启动后
浏览器通过http://localhost:8080/hello 显示 SpringBoot for WebCrud
字样
可以在 application.properties 通过 server.port=8080
修改端口
热部署
首先需自动编译
打开顶部工具栏 File -> Settings -> Default Settings -> Build -> Compiler 然后勾选 Build project automatically
同时按住 Ctrl + Shift + Alt + / 然后进入Registry ,勾选自动编译并调整延时参数。
pom文件 添加热部署插件
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > <scope > runtime</scope > </dependency >
2. 自动配置初探 pom.xml 版本控制都在spring-boot-dependencies-2.3.0.RELEASE.pom
starter 启动器 启动器:就是SpringBoot的启动场景
根据场景,使用对应的启动器就可以,starters 参考文档
主程序 @SpringBootApplication
spring-boot-autoconfigure/2.3.0.RELEASE/spring-boot-autoconfigure-2.3.0.RELEASE.jar!/META-INF/spring.factories 核心配置文件
1 Properties properties = PropertiesLoaderUtils.loadProperties(resource);
所有的资源加载到配置类中
总结
SpringBoot在启动的时候,从类路径下的META-INF/spring.factories
获取指定的值:
将这些自动配置的类导入容器,自动配置就会生效
结论 SpringBoot所有自动配置是在启动的时候扫描并加载:spring.factories
所有的自动配置类都在这里面,但是不一定会生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!
3. 基础配置 yaml 也可以写做:yml
application.yaml
和application.properties
可以作为Spring的配置文件,来更改SpringBoot的默认配置
application.yaml
写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server: port: 8080 student: name: shangsan sex: 0 person: {name: lisi ,age: 18 }pets: - cat - dog - pig pets: [cat ,dog ,pig ]
application.properties
写法
1 2 3 4 server.port =8080 student.name =zhangsan student.sex =0
Demo:配置文件读取
代码
application.yaml
配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server: port: 8080 person: name: 小明 sex: 男 happy: true brithday: 2019 /11/02 maps: {k1: v1 ,k2: v2 ,k3: v3 } dog: name: 黑黑 age: 6 friends: - 小明 - 小明2 - 小明3
实体类
Person.java
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package com.chasing.pojo;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.Date;import java.util.Map;@Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private String sex ; private Boolean happy; private Date brithday; private Map<String,Object> maps; private Dog dog; public Person () {} public Person (String name, String sex, Boolean happy, Date brithday, Map<String, Object> maps, Dog dog) { this .name = name; this .sex = sex; this .happy = happy; this .brithday = brithday; this .maps = maps; this .dog = dog; } }
Dog.java
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.chasing.pojo;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import java.util.List;@Component public class Dog { private String name; private Integer age; private List friends; public Dog () { } public Dog (String name, Integer age, List friends) { this .name = name; this .age = age; this .friends = friends; } }
测试,利用自带的测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.chasing;import com.chasing.pojo.Dog;import com.chasing.pojo.Person;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest class Springboot02ConfigApplicationTests { @Autowired private Person p1; @Test void contextLoads () { System.out.println(p1); } }
运行:
结果:
1 2 Person{name='小明' , sex='男' , happy=true , brithday=Sat Nov 02 00 :00 :00 CST 2019 , maps={k1=v1, k2=v2, k3=v3}, dog=Dog{name='黑黑' , age=6 , friends=[小明, 小明2 , 小明3 ]}}
在实际使用中,推荐使用yml
的方式
JSR303校验
加入pom依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-validation</artifactId > </dependency >
使用
@Component
@Validated //@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。
@ConfigurationProperties(prefix = "blackdog")
public class Dog {
//2.在属性上进行校验 这里的意思是年龄超过51 报错信息为‘年龄错了’
@Max(value = 5l,message = "年龄错了")
private Integer age;
private List friends;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 其他校验注解 ```java @NotNull(message="名字不能为空") private String userName; @Max(value=120,message="年龄最大不能查过120") private int age; @Email(message="邮箱格式错误") private String email; 空检查 @Null 验证对象是否为null @NotNull 验证对象是否不为null, 无法查检长度为0的字符串 @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. @NotEmpty 检查约束元素是否为NULL或者是EMPTY. Booelan检查 @AssertTrue 验证 Boolean 对象是否为 true @AssertFalse 验证 Boolean 对象是否为 false 长度检查 @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 @Length(min=, max=) string is between min and max included. 日期检查 @Past 验证 Date 和 Calendar 对象是否在当前时间之前 @Future 验证 Date 和 Calendar 对象是否在当前时间之后 @Pattern 验证 String 对象是否符合正则表达式的规则 .......等等 除此以外,我们还可以自定义一些数据校验规则
配置文件的加载及优先级 1。 springboot启动会扫描以下位置的application.properties或者application.yml作为默认的配置文件
也可以通过指定配置spring.config.location来改变默认配置,一般在项目已经打包后,我们可以通过指令 java -jar xxxx.jar –spring.config.location=D:/kawa/application.yml来加载外部的配置
多环境切换 方式一:
建立一个 application配置文件
建立其他配置文件(名字格式必须是application-xxx
)
比如 开发环境是application-dev.yaml
,``application-dev.test`是测试环境1
3.文件中通过 来指定配置文件,来方便的切换
方式二:
只写一个配置文件application.yml
通过active
来指定配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 server: port: 8080 spring: profiles: active: dev --- server: port: 8084 spring: profiles: test --- server: port: 8086 spring: profiles: dev
静态资源优先级 resources > static > public
首页:在resources、 static、 public中刃任意一个放如index.html即可
templates下的文件只能通过 controller来进行跳转
Thymeleaf 配置Thymeleaf
pom引入
1 2 3 4 5 <!--thymeleaf--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Html引入
1 <html lang ="en" xmlns:th ="http://www.thymeleaf.org" >
在setting中开始输入提示
Demo
test.HTML
HelloController.java
test.HTML
1 2 3 4 5 6 7 8 9 10 11 <!DOCTYPE html > <html lang ="en" xmlns:th ="http://www.thymeleaf.org" > <head > <meta charset ="UTF-8" > <title > SpringBoot</title > </head > <body > <h1 > Done</h1 > <h1 th:text ="${msg}" > </h1 > </body > </html >
HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.chasing.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controller public class HelloController { @RequestMapping("hello") public String hello (Model modle) { modle.addAttribute("msg" ,"i can ! " ); return "test" ; } }
结果
s’sss
4. 员工管理系统 4.1 准备工作 概要
安装lombok
编写实体类 Department.java Employee.java
部门和员工类
编写Dao DepartmentDao.java EmployeeDao.java
(不用装数据库,暂时在Dao中模拟数据)
导入前台模板
使用lombok
简化开发
LomBok作用:简单说就是通过加注解 的方式,帮你自动生成 toString\Getter\Setter\构造函数\equals方法等等,不用我们手动去编写,代码也看起来更加简洁
pom引入
1 2 3 4 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </dependency >
安装lombok插件。(两种情况) 现在新版本的IDEA可能在商场里搜不到lombok
插件,先试着搜插件,若能搜到就Install 。进入第三步
若搜索不到
进入该网址下载lombok 插件,要根据你的IDEA版本下载
下载后安装lombok
然后找到你下载的lombok 进行安装即可,提示restart就restart
使用lombok 根据需要在类上加注解,即可
注解含义
1 2 3 4 5 6 7 8 9 10 常用注解: @Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。@Getter :使用方法同上,区别在于生成的是getter方法。@ToString :注解在类,添加toString方法。@EqualsAndHashCode : 注解在类,生成hashCode和equals方法。@NoArgsConstructor : 注解在类,生成无参的构造方法。@RequiredArgsConstructor : 注解在类,为类中需要特殊处理的字段生成构造方法,比如final 和被@NonNull 注解的字段。@AllArgsConstructor : 注解在类,生成包含类中所有字段的构造方法。@Data : 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final 属性,则不会为该属性生成setter方法。@Slf4j : 注解在类,生成log变量,严格意义来说是常量。
创建实体类 src\main\java\com\chasing\pojo\Department.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.chasing.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class Department { private Integer id; private String departmentName; }
src\main\java\com\chasing\pojo\Employee.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.chasing.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.Date;@Data @NoArgsConstructor public class Employee { private Integer id; private String lastName; private String email; private Integer gender; private Department department; private Date brith; public Employee (Integer id, String lastName, String email, Integer gender, Department department) { this .id = id; this .lastName = lastName; this .email = email; this .gender = gender; this .department = department; this .brith = new Date (); } }
编写Dao src\main\java\com\chasing\dao\EmployeeDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.chasing.dao;import com.chasing.pojo.Department;import com.chasing.pojo.Employee;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.HashMap;import java.util.Map;@Repository public class EmployeeDao { @Autowired private DepartmentDao departmentDao; private static Map<Integer, Employee> employees = null ; static { employees = new HashMap <Integer, Employee>(); employees.put(1001 ,new Employee (1001 ,"小米" ,"4832747382@qq.com" ,1 ,new Department (104 ,"建设部" ))); employees.put(1002 ,new Employee (1002 ,"小黄" ,"6122212@qq.com" ,0 ,new Department (102 ,"体育部" ))); employees.put(1003 ,new Employee (1003 ,"小名" ,"1025047382@qq.com" ,0 ,new Department (101 ,"教学部" ))); employees.put(1004 ,new Employee (1004 ,"小分" ,"233747382@qq.com" ,1 ,new Department (105 ,"学习部" ))); employees.put(1005 ,new Employee (1005 ,"小五" ,"8789482@qq.com" ,1 ,new Department (103 ,"图书部" ))); } 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(); } public Employee getEmployeeeById (Integer id) { return employees.get(id); } public void delEmployeeeById (Integer id) { employees.remove(id); } }
src\main\java\com\chasing\dao\DepartmentDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.chasing.dao;import com.chasing.pojo.Department;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.Collections;import java.util.HashMap;import java.util.Map;@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(101 ,new Department (102 ,"体育部" )); departments.put(101 ,new Department (103 ,"学习部" )); departments.put(101 ,new Department (104 ,"建设部" )); departments.put(101 ,new Department (105 ,"图书部" )); } public Collection<Department> getDepartment () { return departments.values(); } public Department getDepartmentByid (Integer id) { return departments.get(id); } }
导入前台模板
如图copy到项目
4.2 登录功能和拦截器
在index.html
的表单加入name属性,并加入
编写LoginController.java
控制器
编写LoginHandlerInterceptor.java
拦截器
编写MyMvcConfig.java
配置mvc
src\main\resources\templates\index.html
1 2 3 4 5 6 7 8 9 <h1 class ="h3 mb-3 font-weight-normal" > Please sign in</h1 > <p style ="color: red" th:if ="${not #strings.isEmpty(msg)}" th:text ="${msg}" > </p > <label class ="sr-only" > Username</label > <input type ="text" name ="uname" class ="form-control" placeholder ="Username" required ="" autofocus ="" > <label class ="sr-only" > Password</label > <input type ="password" name ="pwd" class ="form-control" placeholder ="Password" required ="" >
src\main\java\com\chasing\controller\LoginController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.chasing.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpSession;import java.net.HttpCookie;@Controller @RequestMapping("/user") public class LoginController { @RequestMapping(value = "/login") public String login (@RequestParam("uname") String uname, @RequestParam("pwd") String pwd, Model model, HttpSession session) { if (!StringUtils.isEmpty(uname) && "121" .equals(pwd)){ session.setAttribute("loginUser" ,uname); return "redirect:/main" ; }else { model.addAttribute("msg" ,"用户名或者密码错误!" ); return "index" ; } } }
src\main\java\com\chasing\config\LoginHandlerInterceptor.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.chasing.config;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;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 ){ return true ; } request.setAttribute("msg" ,"没有权限,请先登录!" ); request.getRequestDispatcher("/index" ).forward(request,response); return false ; } }
src\main\java\com\chasing\config\MyMvcConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.chasing.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController("/" ).setViewName("index" ); registry.addViewController("/index" ).setViewName("index" ); registry.addViewController("/404" ).setViewName("404" ); registry.addViewController("/main" ).setViewName("dashboard" ); registry.addViewController("/list" ).setViewName("list" ); } @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor ()) .addPathPatterns("/**" ) .excludePathPatterns("/index" ,"/" ,"/user/login" ,"/css/*" ,"/js/**" ,"/img/**" ); } }