Servlet 介绍
Servlet是sun公司提供的一门用于开发动态web资源的技术。 Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤: 1、编写一个Java类,实现servlet接口。 2、把开发好的Java类部署到web服务器中。 按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet
Servlet 和 SpringMVC的关系
SpringMVC是基于Servlet封装的MVC框架
Servlet线程是否安全?如何证明 答:在Servlet 的无参构造函数上面输出内容,并且在该Servlet类上设置变量,在请求的方法上输出并修改变量。 结果: Servlet线程是不安全的,所以是需要注意线程安全问题。解决方法: doGet方法上加锁、变量上加上原子类。
使用注解代替之前的web.xml配置
原理的xml方式
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.kaico.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
使用注解方式,使用 @WebServlet() 注解,注解参数为请求路径。
@WebServlet("/")
public class MyServlet extends HttpServlet {
private Integer count = 0;
public MyServlet() {
System.out.println("<<<MyServlet被实例化...>>>");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
count++;
try {
Thread.sleep(50);
} catch (Exception e) {
}
resp.getWriter().print(" this is mayikt count:" + count);
}
}
ServletContainerInitializer 接口
在web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer实现此功能。 每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类。
1、Servlet容器启动会扫描,当前应用里面每一个jar包的 ServletContainerInitializer 的实现 2、提供ServletContainerInitializer 的实现类;必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer 文件的内容就是ServletContainerInitializer 实现类的全类名;
@HandlesTypes(value = MyHandlesType.class)
public class MyServletContainerInitializer implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
for (Class<?> c : set) {
System.out.println(c);
}
ServletRegistration.Dynamic payServlet = servletContext.addServlet("payServlet", new PayServlet());
payServlet.addMapping("/pay");
}
}
想使用这个接口的实现类的话,必须增加这个配置文件,这是定义的规范。
注解启动 SpringMVC
1、启动 SpringMVC容器类注入到Spring中 2、注入我们的springMVC的配置文件 3、将我们的DispatcherServlet注入到servlet容器中。 4、填写url路径的映射
项目启动时使用 tomcat 启动。
项目结构如图所示:webapp中的配置文件应该全部删除,使用 java 类来配置。 Java配置类,作用:增加mvc开关、配置扫包范围 继承了 WebApplicationInitializer 接口的类,这里配置 servlet并且绑定 url 路径 springmvc没有web.xml配置文件时如何启动的? 首先查看源码(如下图)得知:继承了WebApplicationInitializer接口的类会传递到SpringServletContainerInitializer类中方法onStartUp 中。 原理:Sevlet容器在初始化的时候会加载到这个SpringServletContainerlnitializer,然后找HandlesTypes子类 传回调传递servletContext。
配置视图层
配置类SpringMvcConfig 中增加这个方法,注入bean InternalResourceViewResolver ### 拦截器和过滤器 相同点:拦截器和过滤器都是基于AOP技术实现,对方法实现增强,都可以拦截请求方法。 不同点: 1.过滤器属于Servlet自己研发的,而拦截器技术属于SpringMVC自己研发的。 2.过滤器属于拦截Web请求,而拦截器不仅可以拦截请求还可以拦截普通方法。 3.过滤器会比拦截器先执行,拦截器封装的方法比过滤器拦截使用起来更加简单。
实际开发中绝大多数情况下,都会使用拦截器 拦截器:权限控制、日志打印、参数验证、会话。 过滤器应用场景:编码转换、跨域解决、xss攻击。
拦截器的代码写法:实现接口 注入到Spring中,配置类实现 WebMvcCondfigurer接口,将拦截器bean添加,在配置类SpringMvcConfig 中增加下面代码添加拦截器 注意:使用拦截器一定要关闭EnableWebMvc 否则拦截器不会生效。
SpringMVC多线程异步处理
为什么使用多线程?提高我们的响应的速度、异步执行。
在我们的Web 中为什么要使用异步呢? 目的:快速响应给客户端,防止客户端请求等待的。.单独开启一个线程处理。 使用异步也有缺点:线程安全问题、不能及时拿到结果、消耗CPU。
注解使用异步
在方法上使用注解:@Async controller层调用 service 层这个方法的时候,使用异步线程执行。
Callable 接口实现异步
使用 Callable 实现异步需要设置asyncSupported 为true开启异步 使用方式如下: 这里会等待 callable 里面的方法执行完成之后,才会返回给客户端。service 层的方法去掉注解 @Async 。
|