配置文档地址: https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties.
云雀笔记地址:https://www.yuque.com/atguigu/springboot
1、视图解析原理流程
1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址
2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer
3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。
4、processDispatchResult 处理派发结果(页面改如何响应)
• 1、render(mv, request, response); 进行页面渲染逻辑
• 1、根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】
• 1、所有的视图解析器尝试是否能根据当前返回值得到View对象
• 2、得到了 redirect:/main.html --> Thymeleaf new RedirectView()
• 3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。
• 4、view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作
• RedirectView 如何渲染【重定向到一个页面】
• 1、获取目标url地址
• 2、response.sendRedirect(encodedURL);
视图解析:
• 返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 转发request.getRequestDispatcher(path).forward(request, response);
• 返回值以 redirect: 开始: new RedirectView() --》 render就是重定向
• 返回值是普通字符串: new ThymeleafView()--->
内容协商:
引入依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
自定义messageconverter:
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
Map<String, MediaType> mediaTypes = new HashMap<>();
mediaTypes.put("json",MediaType.APPLICATION_JSON);
mediaTypes.put("xml",MediaType.APPLICATION_XML);
//mediaTypes.put("",MediaType.)自定义
ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
//strategy.setParameterName("");//设置名字,默认format
HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(parameterStrategy,headerStrategy));
}
}
模板引擎:
官方文档:using spring boot - starters—freemarker 页面渲染
Thymeleaf
链接: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<html xmlns:th="http://www.thymeleaf.org">
抽取公共界面:
<footer th:=fragment = "copy">
$;sadjkasjd
</footer>
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
<div>
<footer>
$;sadjkasjd
</footer>
</div>
<footer>
$;sadjkasjd
</footer>
<div>
$;sadjkasjd
</div>
<--如果是id选择器,那么
<footer id = "copy">
$;sadjkasjd
</footer><div>th:replace="footer :: #copy"</div>-->
拦截器
public class LoginInterceptor implements HandlerInterceptor {
@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;//放行
}
//未登录状态,跳转至登录页
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;//拦截
}
}
注册:
public class AdminWebConfig implements WebMvcConfigurer {
@Override//注册拦截器,拦截哪些,放行哪些
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/","login","/css/**","/fonts/**","/js/**","/images/**");
}
}
定制错误处理逻辑
- 自定义错误页
• error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页 - @ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({ArithmeticException.class,NullPointerException.class})
public String handleArithException(Exception e){
log.error("异常是:",e);
return "login";
}
}
- @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
@ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "用户数太多")
public class UserTooManyException extends RuntimeException{
public UserTooManyException() {
}
public UserTooManyException(String message) {
super(message);
}
}
- Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
• response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage()); - 自定义实现 HandlerExceptionResolver 处理异常;可以作为默认的全局异常处理规则
• - ErrorViewResolver 实现自定义处理异常;
• response.sendError 。error请求就会转给controller
• 你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller
• basicErrorController 要去的页面地址是 ErrorViewResolver ;
Web原生组件注入(Servlet、Filter、Listener)
1.@ServletComponentScan(basePackages = “com.atguigu.admin”) :指定原生Servlet组件都放在那里
@WebServlet(urlPatterns = “/my”):效果:直接响应,没有经过Spring的拦截器?
@WebFilter(urlPatterns={"/css/","/images/"})
@WebListener
2、使用RegistrationBean
ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean
@Configuration
public class MyRegistConfig {
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter = new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
return new ServletListenerRegistrationBean(mySwervletContextListener);
}
}
整合mybatis
引入mybatis-starter
配置application.yaml中,指定mapper-location位置即可
编写Mapper接口并标注@Mapper注解
简单方法直接注解方式
复杂方法编写mapper.xml进行绑定映射
@MapperScan(“com.atguigu.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解
分页插件:
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
//这是分页拦截器
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
}