no5-第四章第一次课:内置容器-springmvc支持
分类: springboot 专栏: springboot学习 标签: 内置容器-springmvc支持
2023-03-17 19:16:09 912浏览
1.内置容器
1.1内置容器配置
SpringBoot内置了Tomcat、Jetty、 Undertow 三种web容器,默认使用Tomcat。
1.2切换容器
pom中剔除Tomcat内置容器并新增jetty内置容器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--排除默认的Tomcat容器--> <exclusions> <exclusion> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </exclusion> </exclusions> </dependency> <!--增加jetty starter依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
2.springMVC支持
2.1静态资源
- springboot默认的静态资源设置类ResourceProperties
优先级分别是:
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
- 静态资源加前缀,防止跟controller层重叠
spring.mvc.static-path-pattern=/aaa/**
- 固定static下为静态资源存放位置
spring.resources.static-locations=classpath:/static/
- 配置类的方式给访问静态资源加前缀
@Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/bbb/**") .addResourceLocations("classpath:/static/"); } }
- 自定义静态资源存放目录
spring.resources.static-locations=classpath:/c55/
2.2设置首页
直接在默认的静态资源存放的位置写一个index.html即可。当然自定义的静态资源存放路径下也可以。
2.3网站logo设置
favicon.ico放到静态资源路径下即可
如果遇到访问不到此文件的话,要看是不是配置了拦截器给拦截掉了。
关于网站ico小图标的问题可以看我之前总结的笔记:
此处为语雀内容卡片,点击链接查看:https://www.yuque.com/feiyiyangdebiancheng/ekgbw2/tefp73
3.拦截器
依赖于web框架,本质是aop面向切面编程,只拦截control层。常见的应用场景:
- 权限检查:例如用户登录
- 日志记录:记录请求的重要信息,仪表与信息监控、信息统计
- 性能监控:可以记录某个请求通过拦截器进入处理器的开始时间和结束时间,从而得到该请求的耗时
- 通用行为:拦截器还可以读取cookie,获取用户信息,并将用户信息存放在请求中
public class MyIntercept implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyIntercept preHandle exec ..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyIntercept postHandle exec ..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyIntercept afterCompletion exec ..."); } }
@Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyIntercept()).addPathPatterns("/**") .excludePathPatterns("/dologin","/reg"); }
4.三大web组件
4.1servlet
@WebServlet(urlPatterns = "/myServlet",name = "myServlet") public class MyServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); out.write("<h1>my servlet</h1>"); out.flush(); out.close(); } }
使其生效
@SpringBootApplication @ServletComponentScan("com.bdqn.c55.web") public class AppCh4Web {
4.1过滤器
通过过滤器对web的资源静态html文件,静态图片 jsp servlet等进行拦截,比如:设置url的访问权限、过滤敏感词汇、压缩响应信息等,过滤器还适用于对用户请求和响应对象进行检查和修改。
filter的生命周期大致分为三个阶段:实例化,初始化,销毁。
@WebFilter(filterName = "MyFilter",urlPatterns = "/test") public class MyFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("MyFilter doFilter exec ... "); chain.doFilter(req, resp);//放行 } public void init(FilterConfig config) throws ServletException { } }
使其生效
@SpringBootApplication @ServletComponentScan("com.bdqn.c55.web") public class AppCh4Web {
4.3监听器
监听web中的一些特定事件,主要的应用场景:监听session会话获取当前系统在线人数,监听客户端请求的ServletRequest来获取用户的一些访问信息
1.监听servletContext对象
主要用于初始化一些不经常改变的数据,比如网站首页的一些菜单信息,用户账号相关信息等,将这些数据存进application作用域中,在一定程度上会起到缓存的作用,页面上使用数据的时候直接从application作用域获取,而不是每次获取数据都要从数据库中获取
1.自定义ServletContext的监听器
@Component public class ServletContextListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { //获取application上下文信息 ApplicationContext applicationContext=contextRefreshedEvent.getApplicationContext(); //获取userservice对象 UserService userService = applicationContext.getBean(UserService.class); UserInfo userinfo = userService.getUser(); ServletContext servletContext =applicationContext.getBean(ServletContext.class); servletContext.setAttribute("user",userinfo); } }
- controller层从application作用域中获取初始化的user信息
@RestController public class UserController { @GetMapping("/user") public UserInfo getuser(HttpServletRequest request){ ServletContext servletContext=request.getServletContext(); UserInfo user = (UserInfo) servletContext.getAttribute("user"); return user; } }
2.监听HTTP会话session对象
监听session对象,以统计当前web应用在线用户总数量。
- 自定义session会话监听器
@Component public class SessionListener implements HttpSessionListener { //用于记录在线用户数量 public static Integer count = 0; @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("新用户上线"); count++; se.getSession().getServletContext().setAttribute("count",count); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("用户下线"); count--; se.getSession().getServletContext().setAttribute("count",count); } }
- controller测试该监听器
@GetMapping("/countOnlineUser") public String getOnlineUserCount(HttpServletRequest request, HttpServletResponse response){ Cookie cookie; try { //将sessionId记录到浏览器中,防止在服务器找不到原有的用户信息,重新创建session cookie = new Cookie("JSSIONID", URLEncoder.encode(request.getSession().getId(), "utf-8")); cookie.setPath("/"); //设置cookie有效期为1天 cookie.setMaxAge(24*60*60); response.addCookie(cookie); }catch (Exception e){ e.printStackTrace(); } Integer count = (Integer)request.getSession().getServletContext().getAttribute("count"); return "total user online:"+count; }
3.监听servletRequest对象
监听客户端请求,主要是为了获取用户的一些请求信息。
- 监听request的类
@Component public class RequestListener implements ServletRequestListener { @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("此次请求开始"); HttpServletRequest request = (HttpServletRequest)sre.getServletRequest(); System.out.println("sessionId:"+request.getRequestedSessionId()+"; url:"+request.getRequestURL()); String username = (String)request.getAttribute("username"); if (username == null){ request.setAttribute("username","tudoudou"); } } @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("此次请求结束"); HttpServletRequest request = (HttpServletRequest) sre.getServletRequest(); String username = (String)request.getAttribute("username"); System.out.println("requestScope中username为:"+username); } }
补充:可以监控客户的ip
@Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("创建request对象"); HttpServletRequest request = (HttpServletRequest) sre.getServletRequest(); //请求的地址 System.out.println("getRequestURL:" + request.getRequestURL()); System.out.println("getRequestURI:" + request.getRequestURI()); System.out.println("getLocalAddr:" + request.getLocalAddr());//获取访客ip }
- 测试类control
@GetMapping("/testRequest") public String testRequest(HttpServletRequest request){ String username = (String)request.getAttribute("username"); System.out.println("init requestScope username:"+username); return "success"; }
4.自定义监听器
实现自定义监听器需要三步:
1自定义事件,即监听器用来监听的事件,该事件需要继承applicationEvent对象,
/** * 自定义监听事件 */ public class MyEvent extends ApplicationEvent { private UserInfo user; public MyEvent(Object source, UserInfo user) { super(source); this.user = user; } public UserInfo getUser() { return user; } public void setUser(UserInfo user) { this.user = user; } }
2自定义一个监听器加监听自定义的时间,需要实现applicationListener接口
public class MyListener implements ApplicationListener<MyEvent> { @Override public void onApplicationEvent(MyEvent myEvent) { UserInfo user = myEvent.getUser(); System.out.println("username:"+user.getUsername()); } }
3手动发布事件,发布后监听器才能监听到。
@Override public UserInfo publishMyEvent() { UserInfo userInfo = new UserInfo(1,"afan","123456"); applicationContext.publishEvent(new MyEvent(this,userInfo)); return userInfo; }
测试类
@GetMapping("/publish") public UserInfo publishMyEvent(HttpServletRequest request){ return userService.publishMyEvent(); }
4.4过滤器和拦截器的区别
- 过滤器是基于函数回调的,拦截器是基于servlet容器的
- 过滤器几乎可以过滤所有的请求,但是拦截器只能拦截controller的接口请求
- 拦截器可以访问action上下文,值栈里的对象,而过滤器不能访问
- 在controller的生命周期中,过滤器只能在容器初始化时被调用一次,拦截器可以多次被调用。
- 拦截器可以获取IOC容器中的各种bean,根据需求进行业务处理,但是过滤器不支持这一点。
4.5采用配置类的方式注入组件
场景:假设我们要用的servlet等组件是第三方的,我们没办法在jar包里添加注解。这个时候就需要采用配置类的方式
//装配servlet @Bean ServletRegistrationBean servletRegistrationBean(){ ServletRegistrationBean servletRegistrationBean= new ServletRegistrationBean(new MyServlet(),"/myservlet"); return servletRegistrationBean; } //装配filter @Bean FilterRegistrationBean filterRegistrationBean(){ FilterRegistrationBean filterRegistrationBean= new FilterRegistrationBean(new MyFilter()); filterRegistrationBean.setUrlPatterns(Arrays.asList("/test")); return filterRegistrationBean; } //装配监听器 @Bean ServletListenerRegistrationBean servletListenerRegistrationBean(){ ServletListenerRegistrationBean registrationBean= new ServletListenerRegistrationBean(new MyListener()); return registrationBean; }
4.6实用小例子——图形验证码
<!--用于生成图形验证码--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> <!--以jar包的方式引入jQuery--> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.4.1</version> </dependency>
@Bean ServletRegistrationBean kaptchaServletBean(){ ServletRegistrationBean servletRegistrationBean= new ServletRegistrationBean(new KaptchaServlet(),"/code"); return servletRegistrationBean; }
前端页面
<body> <form action="/dologin" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="pass"><br> 验证码:<input type="text" name="code"> <img src="code" alt="获取验证码"> <br> <input type="submit" value="登录"> </form> <script src="webjars/jquery/3.4.1/jquery.js"></script> <script> $(function () { $("#codeImg").click(function () { $("#codeImg").attr("src","/code") }) }) </script> </body>
好博客就要一起分享哦!分享海报
您可能感兴趣的博客