SpringBoot
基础入门
默认扫描主启动器SpringBoot01Application同目录下的包。
SpringBoot所有的自动装配功能都在 spring-boot-autoconfigure包里
自动装配原理总结:
-
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
-
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值
@EnableConfigurationProperties(xxxProperties.class):
○ xxxProperties和配置文件进行了绑定
○ 将类注册进容器
-
生效的配置类就会给容器中装配很多组件
-
只要容器中有这些组件,相当于这些功能就有了
-
定制化配置
○ 用户直接自己@Bean替换底层的组件
○ 用户去看这个组件是获取的配置文件什么值就去修改。
总结:
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
最佳实践
-
引入场景依赖
-
查看自动配置了哪些(选做) 自己分析,引入场景对应的自动配置一般都生效了 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
-
是否需要修改
-
参照文档修改配置项
-
自己分析。xxxxProperties绑定了配置文件的哪些。 自定义加入或者替换组件
(1)@Bean、@Component。。。
(2)自定义器 XXXXXCustomizer;
SpringBoot 核心技术
yaml 使用
配置提示
<!--yaml配置提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 配置提示,开发用,告诉springboot打包时不用打包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
基本语法
(1) key: value #中间一定要用一个空格
(2) 大小写敏感
(3) 使用缩进表示层级关系
(4) 用空格缩进
(5) 字符串不用加引号,也可以用引号
当使用'\n' ==> 表示\n
当使用"\n" ==> 表示换行
(6)数组、集合可以用
[a,b,c...]
或者:- value
- value
(7)Map<key,Pet>可以用
- pet:
name: 哆啦A梦
weight: 3
- pet:
name: 哆啦B梦
weight: 4
或者
[{name: firstPet,weight: 10},{name: secondPet,weight: 20}]
举例
//加入容器并与application.yml绑定
@ConfigurationProperties(prefix="person")
@Component
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
//加入容器并与application.yml绑定
@ConfigurationProperties(prefix="pet")
@Component
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Pet {
private String name;
private Double weight;
}
application.yml
# yaml表示以上对象
person:
userName: zhangsan
boss: false
birth: 2019/12/12 20:12:33
age: 18
pet:
name: tomcat
weight: 23.4
interests: [篮球,游泳]
animal:
- jerry
- mario
score:
english:
first: 30
second: 40
third: 50
math: [131,140,148]
chinese: {first: 128,second: 136}
salarys: [3999,4999.98,5999.99]
allPets:
sick:
- {name: tom}
- {name: jerry,weight: 47}
health: [{name: mario,weight: 47}]
Web开发
静态资源
-
只要静态资源放在:/static、/public、/resources、/META-INF/resources
-
原理: 静态映射/。**
请求进来,先去找Controller看能不能处理。
不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面
自定义静态资源 访问前缀(默认无)、存放位置(一般不自定义存放位置)
spring:
mvc: #自定义访问前缀,会导致welcome page功能和小图标失效
static-path-pattern: /res/**
#了解,一般使用static作为静态资源路径
web:
resources: #可以存放res01和static目录下
static-locations: [classpath:/res01/,classpath:/static/]
SpirngMvc 原理
请求映射原理
doDisPatch 得到 HandlerMappings,遍历找到对应的 XxxHandlerMapping
RequestMappingHandlerMapping:保存了所有@RequestMapping 和 handler的映射规则,所有的请求映射都在HandlerMapping中。
自定义HandlerMapping(以后学)
常见参数注解
- @PathVariable :获取路径变量,RestFul风格 /user/{name}
- @RequestParam :获取请求参数,/user?name=zhangsan&...
- @RequestHeader :获取请求头
- @RequestBody :获取请求体(必须Post方式)
- @RequestAttribute :获取request域属性
- @ModelAttribute :获取Model设置参数值
- @MatrixVariable :获取矩阵变量
- @CookieValue :获取cookie值
- @MatrixVariable(pathVar="路径变量名",value="属性名")
@RestController
public class HelloController {
@GetMapping("/car/{id}/owner/{username}")
public Map<String,Object> getCar(@PathVariable("id") String id, // /car/{id}
@PathVariable("username") String name ,// /car/{username}
//获取所有的路径变量,存放进map<String,String>,map的key、value都得是String
@PathVariable Map<String,String> pvMap,
@RequestParam("age") Integer age, // /car?age=18
@RequestParam("hobbies") List<String> inters,// /car?hobbies=zq,lq
//获取所有的请求参数,存放进map<String,String>,map的key、value都得是String
@RequestParam Map<String,String> params,
@RequestAttribute("str") String str, //request.setAttribute("str","str1111");
@RequestHeader("User-Agent") String userAgent,
@RequestHeader() Map<String,String> headMap,
@CookieValue("_ga") String _ga,
@CookieValue("_ga") Cookie cookie,
HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
// request.setAttribute("str","str1111");
// map.put("id",id);
// map.put("name",name);
// map.put("pvMap",pvMap);
// map.put("userAgent",userAgent);
// map.put("headMap",headMap);
// map.put("hobbies",inters);
return map;
}
}
矩阵变量:绑定在路径变量中
@MatrixVariable使用之前要在springboot中开启 1.要有一个配置类 2.手动开启
@Configuration(proxyBeanMethods = false)
public class WebConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//不移除;后面内容,这样矩阵变量才能生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
}
- 示例
@RestController
public class HelloController {
//http://localhost:8080/car/1;name=lisi;age=18/10;name=2000;age=20
@GetMapping("/car/{boss1}/{boss2}")
public Map<String,Object> getCar(@MatrixVariable(pathVar="boss1",value="name") String boss1name,
@MatrixVariable(pathVar="boss1",value="age") Integer boss1age,
@PathVariable("boss1") String boos1,
@MatrixVariable(pathVar="boss2",value="name") String boss2name,
@MatrixVariable(pathVar="boss1",value="age") Integer boss2age,
@PathVariable("boss2") String boos2
){
Map<String,Object> map = new HashMap<>();
map.put("boss1name",boss1name);
map.put("boss1age",boss1age);
map.put("boos1",boos1);
map.put("boss2name",boss2name);
map.put("boss2age",boss2age);
map.put("boos2",boos2);
return map;
}
}
面试题:cookies被禁用,请问session里的内容怎么获取
用矩阵变量
url重写:/abc;jsesssionid=xxxx 把cookie的值使用矩阵变量的方式进行传递
-
Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
-
@ResponseBody 加在方法上,代表返回jason
内容协商
根据客户端接收能力不同,返回不同媒体类型的数据。
<!-- 内容协商,引入xml依赖-->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
3、开启浏览器参数方式内容协商功能 为了方便内容协商,开启基于请求参数的内容协商功能。
spring:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
发请求: format=json代表返回json类型
http://localhost:8080/test/person?format=json
http://localhost:8080/test/person?format=xml
登录检查用拦截器
拦截器
/**
* 登录检查
* 1.配置好拦截器要拦截哪些请求
* 2.把这些配置放在容器中
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
*目标方法执行前
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录逻辑检查
HttpSession session = request.getSession();
//获取LoginUser,因为在Controller中user是存放在session中,所以要用session获取
User user = (User) session.getAttribute("loginUser");
if(user!=null){
//放行
return true;
}
//拦截,提示信息并重定向回登录页面
request.setAttribute("msg","请 先 登 录 !");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
}
在WebMvcConfigurer总,添加拦截器
@Controller
public class AdminWebConfig implements WebMvcConfigurer {
/**
* 编写一个拦截器实现 HandlerInterceptor接口
* 拦截器注册进容器中(实现WebMvcConfiguer的addInterceptors)
* 指定拦截器规则,/**拦截所有
* */
@Override
public void addInterceptors(InterceptorRegistry registry) {
WebMvcConfigurer.super.addInterceptors(registry);
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都被拦截,包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行登录请求和静态资源
}
}
文件上传
html
<!--文件上传固定写法-->
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleInputEmail1"> 邮 箱 </label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1"> 名 字 </label>
<input type="text" name="username" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile"> 头 像 </label>
<input type="file" name="headerImg" id="exampleInputFile">
</div>
<div class="form-group">
<label for="exampleInputFile"> 生 活 照 </label>
<input type="file" name="photos" multiple>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-primary"> 提 交 </button>
</form>
Controller
/**
* MultipartFile 自动封装上传过来的文件
* */
@PostMapping("/upload") //点击表单提交请求到这
public String upload(@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestPart("headerImg") MultipartFile headerImg,
@RequestPart("photos") MultipartFile[] photos) throws IOException {
//把照片写入磁盘
if(!headerImg.isEmpty()){
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("D://"+originalFilename));
}
if(photos.length > 0){
for (MultipartFile photo : photos) {
if(!photo.isEmpty()){
final String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("D://"+originalFilename));
}
}
}
return "index"; //返回首页面
}
配置上传大小
#设置文件上传大小限制
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
错误处理
- 默认404白页
在templates引擎模板下面建立error,会被自动解析错误处理页面
自定义错误处理
- @ControllerAdvice + @ExceptionHandler处理全局异常
/**
* 处理整个web controller 的异常
* 异常解析器:
* ExceptionHandlerExceptionResolver(推荐):处理 @ExceptionHandler注解 、
* ResponseStatusExceptionResolver:处理 @ResponseStatus注解、
* DefaultHandlerExceptionResolver(默认异常解析器:出里框架自带异常)
*
*/
@ControllerAdvice
public class GlobalExceptionHandler {
//匹配 数学运算异常和空指针异常
//@ExceptionHandler 注解 能被 ExceptionHandlerExceptionResolver 异常解析器处理
@ExceptionHandler({ArithmeticException.class,NullPointerException.class}) //处理异常
public String handleArithException(){
return "login"; //视图地址
}
}
Web组件
1、Web原生组件(Servlet、Filter、Listener)可以使用
- 如果没有标注@WebServlet、@WebFilter、@WebListener就不是组件了,@ServletComponentScan(basePackages = "com.gwq.admin") 扫描不到
主启动器,配置扫描原生Servlet三大组件
//主启动器,扫描原生Servlet三大组件
@ServletComponentScan(basePackages = "com.gwq.admin")
@SpringBootApplication
public class Boot05WebAdminApplication {
public static void main(String[] args) {
SpringApplication.run(Boot05WebAdminApplication.class, args);
}
}
Servlet类
@WebServlet(urlPatterns = "/my")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("666");
}
}
Filter类
@Slf4j
@WebFilter(urlPatterns = {"/css/*"})//拦截/css下所有,单*是Servlet写法,双**是Spring写法
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("嘿嘿,抓到你啦");
filterChain.doFilter(servletRequest,servletResponse);//放行
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Listener类
@Slf4j
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("监听到MyServletContextListener ==> 初始化完成");
}
}
2、使用RegistrationBean (非常方便)
(0)写未标注@WebXXX的 MyServlet、 MyFilter 和 MyListener
- MyServlet
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("666");
}
}
- MyFilter
@Slf4j
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("嘿嘿,抓到你啦");
filterChain.doFilter(servletRequest,servletResponse);//放行
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
- MyServletContextListener
@Slf4j
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("监听到MyServletContextListener ==> 初始化完成");
}
}
(1)写配置类
@Configuration(proxyBeanMethods = true) //细节1 :始终保证依赖的组件是单实例的
public class MyRegistConfig {
@Bean
public ServletRegistrationBean myServlet(){
//创建一个自定义MyServlet
MyServlet servlet = new MyServlet();
return new ServletRegistrationBean(servlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean myFilter(){
//创建一个自定义MyFilter
MyFilter filter = new MyFilter();
//方式一 return new FilterRegistrationBean(filter,myServlet());
//方式二
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
//设置过滤路径
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
//创建一个自定义Listener
MyServletContextListener listener = new MyServletContextListener();
return new ServletListenerRegistrationBean(listener);
}
}
更改web服务器(Tomcat够用了)
数据访问
导入jdbc场景,如果引入mabatis场景,就把这删了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
使用Druid数据源
自定义方式
引入druid-starter
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
自动配置
● 扩展配置项 spring.datasource.druid
● DruidSpringAopConfiguration.class,
监控SpringBean的;配置项:spring.datasource.druid.aop-patterns
● DruidStatViewServletConfiguration.class,
监控页的配置:spring.datasource.druid.stat-view-servlet;默认开启
● DruidWebStatFilterConfiguration.class,
web监控配置;spring.datasource.druid.web-stat-filter;默认开启
● DruidFilterConfiguration.class}) 所有Druid自己filter的配置
yml配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_account
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
druid:
aop-patterns: com.atguigu.admin.* #监控SpringBean
filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)
stat-view-servlet: # 配置监控页功能
enabled: true
login-username: admin
login-password: admin
resetEnable: false
web-stat-filter: # 监控web
enabled: true
urlPattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
filter:
stat: # 对上面filters里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall:
enabled: true
config:
drop-table-allow: false #不允许删表跑路
springboot整合Mybatis
GitHub地址,选择最新版 https://github.com/mybatis/spring-boot-starter
选择mybatis-spring-boot-starter,然后选pom文件格式
<!--引入最新版mybatis-spring-boot-starter-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
提示信息用Model存,
用戶用HttpSession存