web框架的一些基础功能
0web工程更换主机需要的工作
1修改maven配置
F:/yang/software/Maven/apache-maven-3.8.3
F:\yang\software\Maven\apache-maven-3.8.3\conf\settings.xml
F:\yang\software\Maven\maven_repository
修改java版本
1请求数据
数据的传输格式一般为json格式
客户端发送请求(可以包含数据,或者不包含数据)服务端响应请求(可以包含数据,或者不包含数据)
服务端发送请求()
2请求转发 ,重定向 跳转页面
一、请求转发与重定向区别
重定向:
1.可以理解为是客户端行为,客户端发起一次请求,服务器端给出一次响应,但这个响应包含下一次客户端需要 访问的服务器端处理程序的地址,客户端再次发起请求,将会得到处理结果,也就意味着重定向客户端至少发起两次请求
[外链图片转存失败,源站可能有防盗
链机制,建议将图片保失败,源站可能有防盗链机制,建议将图片保存下来直接上传存上传(imPZyiduODLd-1648876653712)(springboot应用.assets/v-888898a708dca21247770152ca86c58_720w.jpg73)(springboot应用.assets/v2-9888178a708dca21247770352ca86c58_720w.jpg)]
请求转发:
1.可以理解是服务器端行为,客户端发起一次请求,这个请求在整个服务器端可以被多次传递,但都是由服务器端的处理程序传递给另一个处理程序,客户端不需要发起二次请求,无论这个请求经历过多少个处理程序,始终都是同一个请求,也就意味着,这个请求中的数据经历过的每一个处理程序都可以使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7vXyhjS6-1648876653712)(springboot应用.assets/v2-9be47256786691ba3fa13ee3ca817b14_720w.jpg)]
二、使用
当前后两个页面有数据传递时,例如查询了数据需要在页面显示时,用请求转发
当没有数据传递,例如做了更新操作跳转到其他页面,就用重定向。
3文件的上传下载
package com.xianjingshang.admin.controller;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/**
* 文件上传测试
*/
@Slf4j
@Controller
public class FormTestController {
@GetMapping("/form_layouts")
public String form_layouts(){
return "form/form_layouts";
}
/**
* MultipartFile 自动封装上传过来的文件
* @param email
* @param username
* @param headerImg
* @param photos
* @return
*/
@SneakyThrows
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,//从请求参数中获取email的值
@RequestParam("username") String username,
@RequestPart("headerImg") MultipartFile headerImg, //MultiparFile 文件格式
@RequestPart("photos") MultipartFile[] photos){
log.info("上传的信息:email={},username={},headerImg{},photos={}",
email,username,headerImg.getSize(),photos.length);
if(!headerImg.isEmpty()){
//保存到文件服务器,oss服务器
String originalFilename = headerImg.getOriginalFilename();//拿到原始文件名
//保存文件到这个地方
headerImg.transferTo(new File("F:\\yang\\study\\学习\\记忆宫殿3.0\\自然科学\\计算机\\Java\\Spring boot2\\resource\\"+originalFilename));
}
if(photos.length>0){
for (MultipartFile photo:photos){
if(!photo.isEmpty()){
//保存到文件服务器,oss服务器
String originalFilename = photo.getOriginalFilename();//拿到原始文件名
//保存文件到这个地方
photo.transferTo(new File("F:\\yang\\study\\学习\\记忆宫殿3.0\\自然科学\\计算机\\Java\\Spring boot2\\resource\\"+originalFilename));
}
}
}
return "main";
}
}
4往请求域中存取数据
方法一
public String dynamic_table(Model model){
//表格内容的遍历
List<User> users = Arrays.asList(new User("zhangsan", "123456"),
new User("Lisi", "aaaa"),
new User("haha", "aadd"));
model.addAttribute("user",users); //addAttribute把model数据放在请求域中session
return "table/dynamic_table";
}
方法二
(HttpServletRequest request){
HttpSession session = request.getSession();
//取数据
Object loginUser=session.getAttribute("loginUser");
//存数据
session.setAttribute("msg","请先登录");
}
spring boot应用
00
结构
第三方库AutoConfiguration
注解的运用
@Configuration与@Bean一起使用
@Configuration//放在类的上面作为配置类的标识
@Bean //放在方法上作为配置属性的修改
xml配置与配置类之间的转换
0创建一个简单的springboot后台管理系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rdMyf4Ne-1648876653715)(springboot应用.assets/Snipaste_2022-02-21_15-43-27.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t7GFx4yI-1648876653715)(springboot应用.assets/Snipaste_2022-02-21_15-43-19.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ch2GwEjP-1648876653716)(springboot应用.assets/Snipaste_2022-02-21_15-43-10.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4AhhGGeO-1648876653716)(springboot应用.assets/Snipaste_2022-02-21_15-44-09.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-we80Nc60-1648876653716)(springboot应用.assets/Snipaste_2022-02-21_15-44-15.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b1cMX3w6-1648876653717)(springboot应用.assets/Snipaste_2022-02-21_15-47-31.png)]
1浏览器接收和发送的数据类型
基于请求头(header)来判断数据类型
1、开启浏览器参数方式内容协商功能
为了方便内容协商,开启基于请求参数的内容协商功能。
在请求后带上一个format的参数,在参数后面跟上返回的数据类型,就能得到参数类型
yaml 配置类中写
spring:
mvc:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
发请求:
http://localhost:8080/test/person?format=json 返回json
http://localhost:8080/test/person?format=xml 返回xml
2、自定义 MessageConverter
实现多协议数据兼容。json、xml、x-guigu
0、@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
1、Processor 处理方法返回值。通过 MessageConverter 处理
2、所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
3、内容协商找到最终的 messageConverter;
SpringMVC的什么功能。一个入口给容器中添加一个 WebMvcConfigurer
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AMVVm9m9-1648876653717)(springboot应用.assets/Snipaste_2022-02-21_11-51-27.png)]
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ac8EwraX-1648876653718)(springboot应用.assets/1605260623995-8b1f7cec-9713-4f94-9cf1-8dbc496bd245-163937286206561.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4XH6Fbvm-1648876653718)(springboot应用.assets/1605261062877-0a27cc41-51cb-4018-a9af-4e0338a247cd-163937286206563.png)]
有可能我们添加的自定义的功能会覆盖默认很多功能,导致一些默认的功能失效。
大家考虑,上述功能除了我们完全自定义外?SpringBoot有没有为我们提供基于配置文件的快速修改媒体类型功能?怎么配置呢?【提示:参照SpringBoot官方文档web开发内容协商章节】
/**
* 自定义类的converter
*/
public class GuiguMessageConverter implements HttpMessageConverter<Person> {
@Override
/**
* 得到读取自己定义的数据
*/
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return false;
}
/**
*
*返回 类型 是person类就可以
* @return
*/
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return clazz.isAssignableFrom(Person.class);
}
/**
* 服务器要统计所有MessageConverter都能写出哪些内容类型
*
* application/x-guigu
* @return
*/
@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-guigu");
}
@Override
public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
//自定义协议数据的写出
String data=person.getUserName()+";"+person.getAge()+";"+person.getBirth()+";"+
person.getPet();
//写出去
OutputStream body = outputMessage.getBody();
body.write(data.getBytes());
}
}
3、基于参数的内容协商
在webconfig中的WebMvcConfigurer(){}进行配置
/**
* 设置内容协商策略 参数,请求头
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// Map<String, MediaType> mediaTypes
Map<String, MediaType> mediaTypes=new HashMap<>();
mediaTypes.put("json",MediaType.APPLICATION_JSON);
mediaTypes.put("xml",MediaType.APPLICATION_XML);
mediaTypes.put("gg",MediaType.parseMediaType("application/x-guigu"));
//指定支持解析哪些参数对应的哪些媒体类型
ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
//把format换成ff
parameterStrategy.setParameterName("ff");
//支持请求头的参数
HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
//把头和参数全放进去了
configurer.strategies(Arrays.asList(parameterStrategy,headerStrategy));
}
/**
* 拓展自定义的converter
* @param converters
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//添加自定义的converter
converters.add(new GuiguMessageConverter());
}
2图形解析器thymeleaf
1、引入Starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2、自动配置好了thymeleaf
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }
自动配好的策略
-
1、所有thymeleaf的配置值都在 ThymeleafProperties
-
2、配置好了 SpringTemplateEngine
-
3、配好了 ThymeleafViewResolver
-
4、我们只需要直接开发页面
public static final String DEFAULT_PREFIX = "classpath:/templates/";
//资源路径下的resources/templates放页面
public static final String DEFAULT_SUFFIX = ".html"; //xxx.html
<!DOCTYPE html>
<!--加入名称空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--替换文字-->
<h1 th:text="${msg}">哈哈</h1>
<h2>
<!-- 超链接 是<a>-->
<!-- 替换超链接,替换什么,在th后面加什么-->
<a href="www.atguigu.com" th:href="${link}">去百度</a> <br/>
<a href="www.atguigu.com" th:href="@{link}">去百度2</a>
</h2>
</body>
</html>
没有放到后端进行模板引擎的刷新
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HRLjqJek-1648876653719)(springboot应用.assets/Snipaste_2022-02-21_15-17-51-16454279122343.png)]
在后端进行了引擎的刷新
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKxzpEZ8-1648876653719)(springboot应用.assets/Snipaste_2022-02-21_15-16-15-16454279122344.png)]
3跳转页面
@Controller
public class IndexController {
/**
* 来登录页
* @return
*/
@GetMapping(value = {"/","/login"})
public String loginPage(){
return "login";
}
@PostMapping("/login")
public String main(String username,String password){
//登录成功重定向到main.html;重定向防止表单重复提交
return "redirect:/main.html";
}
/**
* 去main页面
* @return
*/
@GetMapping("/main.html")
public String mainPage(){
return "main";
}
}
4,bean的建立
@Data get,set方法
@AllArgsConstructor 有参构造器
@NoArgsConstructor 无参构造器
@SneakyThrows
Exception异常有两个分支,一个是运行时异常RuntimeException,一个是编译时异常,在Exception下的所有非RuntimeException异常,比如IOException、SQLException等;所有的运行时异常不捕获,编译时异常是一定要捕获,否则编译会报错。@SneakyThrows就是利用了这一机制,将当前方法抛出的异常,包装成RuntimeException,骗过编译器,使得调用点可以不用显示处理异常信息
5,拦截器
- 1,编写一个拦截器实现HandlerInterceptor接口
- 2,拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
- 3,指定拦截规则【如果是拦截所有,静态资源也会被拦截】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MK8WUwfN-1648876653720)(springboot应用.assets/Snipaste_2022-02-28_14-56-35.png)]
接口 | 功能 |
---|---|
preHandle | 在执行前处理 |
postHandle | 在执行后处理 |
afterCompletion | 在请求完成后处理 |
拦截类
向浏览器中发送一个session
@Controller
public class IndexController {
@PostMapping("/login")
public String main(User user, HttpSession session, Model model){ //RedirectAttributes
if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){
//把登陆成功的用户保存起来
session.setAttribute("loginUser",user);
//登录成功重定向到main.html; 重定向防止表单重复提交
return "redirect:/main.html";
}else {
model.addAttribute("msg","账号密码错误");
//回到登录页面
return "login";
}
}
}
package com.xianjingshang.admin.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 登录检查
* 1,配置好拦截器要拦截那些请求
* 2,把这些配置放置在容器中
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录检查逻辑
HttpSession session = request.getSession();
Object loginUser=session.getAttribute("loginUser");
if(loginUser !=null){
return true;
}else {
return false;
}
}
/**
* 目标方法执行完成以后
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 页面渲染
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 添加路径
.addPathPatterns("/**")
// 放行路径
.excludePathPatterns("/","/login");
}
拦截器的执行顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BFDr4Mco-1648876653720)(springboot应用.assets/Snipaste_2022-02-28_16-01-13.png)]
6,配置类
spring的容器的注册都在配置类中写
加上==@Configuration===
继承WebMvcConfigurer接口
就完成了配置类的基础搭建
package com.xianjingshang.admin.config;
import com.xianjingshang.admin.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 添加路径
.addPathPatterns("/**")
// 放行路径
.excludePathPatterns("/","/login");
}
}
7,日志
@Slf4j 引入注释,是lombok插件里的
使用
log.info("当前的日志内容");
log.info("拦截的请求路径是{}",requestURI);
//{}类似c语言中的pringtf("%d",a);中的%d
8,加载更新
实际上是重启,不是更新。更新的插件收费
ctrl+F9
9、异常处理
1、错误处理(自动配置)
- 默认情况下,Spring Boot提供
/error
处理所有错误的映射 - 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8RyEjcy-1648876653721)(springboot应用.assets/1606024421363-77083c34-0b0e-4698-bb72-42da351d3944-163937286206583.png)]
- 要对其进行自定义,添加
**View**
解析为**error**``** **
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahIW8Tfq-1648876653721)(springboot应用.assets/1606024616835-bc491bf0-c3b1-4ac3-b886-d4ff3c9874ce.png)]
- 要完全替换默认行为,可以实现
ErrorController
并注册该类型的Bean定义,或添加ErrorAttributes类型的组件
以使用现有机制但替换其内容。 - error/下的4xx,5xx页面会被自动解析;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bq2G5dyb-1648876653721)(springboot应用.assets/1606024592756-d4ab8a6b-ec37-426b-8b39-010463603d57-163937286206587.png)]
2,应用
1自定义错误页
error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKRQ6B3d-1648876653722)(springboot应用.assets/1606024592756-d4ab8a6b-ec37-426b-8b39-010463603d57-163937286206587.png)]
2处理全局异常
@ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
package com.xianjingshang.admin.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* 处理整个web controller
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({ArithmeticException.class,NullPointerException.class}) //处理异常
public String handleArithException(Exception e//抓住异常
){
log.error("异常是:{}",e);
return "login"; //视图地址
}
}
3处理自定义异常
@ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
package com.xianjingshang.admin.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "用户数量太多")
public class UserTooManyException extends RuntimeException{
public UserTooManyException(){
}
public UserTooManyException(String message){
super(message); //把信息传到异常里
}
}
//引出异常
@GetMapping("/dynamic_table")
public String dynamic_table(Model model){
//表格内容的遍历
List<User> users = Arrays.asList(new User("zhangsan", "123456"),
new User("Lisi", "aaaa"),
new User("haha", "aadd"));
model.addAttribute("user",users); //addAttribute把model数据放在请求域中session
if(users.size()>3){
throw new UserTooManyException();
}
return "table/dynamic_table";
}
4,Spring底层的异常
Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
5,可以作为默认的全局异常处理规则
自定义实现 HandlerExceptionResolver 处理异常;可以作为默认的全局异常处理规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tz69fN20-1648876653722)(springboot应用.assets/Snipaste_2022-03-01_16-49-29.png)]
6 ,tomcat处理
ErrorViewResolver 实现自定义处理异常;
-
response.sendError 。error请求就会转给controller
-
你的异常没有任何人能处理。tomcat底层
-
response.sendError。error请求就会转给controller
-
basicErrorController 要去的页面地址是 ErrorViewResolver ;
10原生组件注入
1注释类型
1在spring配置文件中添加注释
@ServletComponentScan(basePackages = "com.xianjingshang.admin") //默认是配置类下的所有包及其子包,也就是当前目录
@SpringBootApplication
public class Boot05WebAdminApplication {
public static void main(String[] args) {
SpringApplication.run(Boot05WebAdminApplication.class, args);
}
}
2创建Servlet,Filter,ServlerContextList的方法中添加注释
1监听器
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MyServletContextListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MyServletContextListener监听到项目销毁");
}
}
2方法
//必须在配置类中添加一个包扫描器
//直接响应没有经过spring拦截器的拦截
@WebServlet(urlPatterns = "/my")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("6666");
}
}
3拦截器
//web自带的拦截器
//*是servlet的写法,**是spring的写法
@WebFilter(urlPatterns = {"/css/*","/images/*"})//没有拦截my
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化完成");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("MyFilter工作");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
3,@Configuration+@Bean 的MyRegistConfig实现组件的注册
1MyRegistConfig类
@Configuration
public class MyRegistConfig {
// 当没有在Servlet中写@WebServlet(urlPatterns = "/my")时可以用这个注册
@Bean//用来注册的标记注释
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
// 当没有写@WebFilter(urlPatterns = {"/css/*","/images/*"})时可以用这个注册
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter=new MyFilter();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));//配置拦截路径
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
MyServletContextListener myServletContextListener = new MyServletContextListener();
return new ServletListenerRegistrationBean(myServletContextListener);
}
}
2,Servlet类
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("6666");
}
}
3,Filter类
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化完成");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("MyFilter工作");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
4,ServletContextListener类
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MyServletContextListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MyServletContextListener监听到项目销毁");
}
}
11、嵌入式Servlet容器
1、切换嵌入式Servlet容器
- 默认支持的webServer
-
Tomcat
,Jetty
, orUndertow
ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并引导创建服务器
- 切换服务器
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkXedyca-1648876653722)(springboot应用.assets/1606280937533-504d0889-b893-4a01-af68-2fc31ffce9fc-1639372862067109.png)]
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
12.定制化常见方式
1,全面接管springMvc
/**
* 1,编写一个拦截器实现HandlerInterceptor接口
* 2,拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
* 3,指定拦截规则【如果是拦截所有,静态资源也会被拦截】
* @EnableWebMvc:全面接管
* 1,静态资源?视图解析器?欢迎页。。。全部失效
*/
//@EnableWebMvc//一定要慎用
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
/**
* 定义静态资源行为
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 访问/aa/** 所有请求都去classpath:/static/ 下面进行匹配
*/
registry.addResourceHandler("/aa/**")
.addResourceLocations("classpath:/static/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 添加路径
.addPathPatterns("/**")//所有请求都被拦截,包括静态请求
// 放行路径
.excludePathPatterns("/","/login","/css/**","/fonts/**","/js/**","/images/**","/aa/**");
}
/**
* 可以修改底层的内容
* @return
*/
// @Bean
// public WebMvcRegistrations webMvcRegistrations(){
// return new WebMvcRegistrations() {
// @Override
// public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
// return null;
// }
// };
// }
}
2,==Web应用 编写一个配置类实现 WebMvcConfigurer 即可定制化web功能;+ @Bean给容器中再扩展一些组件==常用
@Configuration
public class AdminWebConfig implements WebMvcConfigurer
3、原理分析套路重点
场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties – 绑定配置文件项
13.引入数据库
1配置数据库
1,基本配置
1、导入JDBC场景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jCY3GZ8-1648876653723)(springboot应用.assets/1606366100317-5e0199fa-6709-4d32-bce3-bb262e2e5e6a.png)]
2.导入数据库驱动
数据库版本和驱动版本对应
默认版本:<mysql.version>8.0.22</mysql.version>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <version>5.1.49</version>-->
</dependency>
想要修改版本
1、直接依赖引入具体版本(maven的就近依赖原则)
2、重新声明版本(maven的属性的就近优先原则)
<properties>
<java.version>1.8</java.version>
<mysql.version>5.1.49</mysql.version>
</properties>
navicat如何查看当前mysql的版本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0n2VbW9g-1648876653723)(springboot应用.assets/Snipaste_2022-03-04_08-44-13.png)]
3、修改配置项
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_account
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
2配置druid数据库连接池(过时了)
maven
<!-- 引入阿里德鲁伊数据库-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency>
@Configuration
public class MyDataSourceConfig {
/**
* 默认的自动配置是判断容器中没有才会配@ConditionalOnMissingBean(DataSource.class)
*/
//把public DataSource dataSource中
// DataSource里边的属性跟配置文件进行绑定 绑定之后不能再用配置类配置了
@ConfigurationProperties("spring.datasource")
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
// druidDataSource.setUrl();
// druidDataSource.setUsername();
// druidDataSource.setPassword();
// //加入监控功能
// druidDataSource.setFilters("stat");
return new DruidDataSource();
}
/**
* 配置druid的监控页功能
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
StatViewServlet statViewServlet = new StatViewServlet();
ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*" );
return registrationBean;
}
}
spring:
datasource:
url: jdbc:mysql://localhost:3306/occupy
username: root
password: 123456
# 加入监控功能
filters: stat
driver-class-name: com.mysql.jdbc.Driver
# type: com.zaxxer.hikari.HikariDataSource
# 查询超时默认是s
jdbc:
template:
query-timeout: 3
1,开启sql监控
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VS9IqmKJ-1648876653723)(springboot应用.assets/Snipaste_2022-03-04_13-05-53.png)]
spring:
datasource:
url: jdbc:mysql://localhost:3306/occupy
username: root
password: 123456
# 加入监控功能
filters: stat
2,开启web监控
MyDataSourceConfig类中
/**
* webStatFilter 用于采集web—jdbc关联监听的数据。
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter(){
WebStatFilter webStatFilter=new WebStatFilter();
FilterRegistrationBean<WebStatFilter> filterFilterRegistrationBean=
new FilterRegistrationBean<WebStatFilter>(webStatFilter);
filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
filterFilterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterFilterRegistrationBean;
}
3配置druid数据库连接池(官方配置)
3、使用官方starter方式
1、引入druid-starter
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
2,写sql语句
@SpringBootTest
class Boot05WebAdminApplicationTests {
@Autowired//自动注入 这个类的参数和方法
//类似静态变量,已经放到容器中了,随着请求而改变
JdbcTemplate jdbcTemplate;
@Autowired
DataSource dataSource;//sql类中的
@Test
void contextLoads() {
// 查询单条记录
// jdbcTemplate.queryForObject("select * from seats ");
jdbcTemplate.queryForList("select * from seats");
Long aLong = jdbcTemplate.queryForObject("select count(*) from seats", long.class);
for(int i=0;i<10;i++) {
log.info("msg 记录总数:{}", aLong);
log.info("msg 数据源类型:{}",dataSource.getClass());
}
}
}