no5-第四章第一次课:内置容器-springmvc支持
分类: springboot 专栏: springboot学习 标签: 内置容器-springmvc支持
2023-03-17 19:16:09 1256浏览
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>
好博客就要一起分享哦!分享海报
您可能感兴趣的博客

新业务
springboot学习
ssm框架课
vue学习
【带小白】java基础速成