平时直接用springmvc较多,都没怎么接触底层的Servlet,致使对一些基本的知识点了解都不够,因此今天专门的抽出时间来学习一下html
带着问题出发,看下能够怎么玩java
Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的做用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中一般须要:web
通常来说,建立一个自定义的Servlet有两个步骤,在web.xml中配置serverlt的声明;实现Servlet接口,实现自定义的Servlet逻辑spring
一个简单的case以下apache
web.xml中,添加配置跨域
<servlet> <servlet-name>doc-servlet</servlet-name> <servlet-class>com.yihui.study.DocServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>doc-servlet</servlet-name> <url-pattern>/study/*</url-pattern> </servlet-mapping>
实现自定义Servlet缓存
public class DocServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); writer.append("这是一个自定义servlet") .append("emoj😄==").flush(); System.out.println("hereher!!!!"); } }
上面这个Servlet,实现了拦截 /study 下的全部请求, 而后返回一段文本,上面做为演示,具体的展开下面说明服务器
上面是直接继承了HttpServlet,可能无法彻底的暴露一个Servlet的具体接口有哪些,以及它的生命周期是怎样的,接下来则直接针对源头进行说明cookie
public interface Servlet { // 初始化 public void init(ServletConfig config) throws ServletException; // 获取配置信息 public ServletConfig getServletConfig(); // 处理请求 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; // Returns information about the servlet, such as author, version, and copyright public String getServletInfo(); // 销毁 public void destroy(); }
五个方法,从命名也能够看出对应的生命周期mvc
说明
在Servlet被建立后,服务器会立刻调用Servlet的void init(ServletConfig)方法。请记住, Servlet出生后立刻就会调用init()方法,咱们能够把一些对Servlet的初始化工做放到init方法中,从此全部分配到这个Servlet的请求,都是公用这个Servlet的
init()方法的参数
ServletConfig对象对应web.xml文件中的元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可使用servletConfig.getServletName()方法获取
String getServletName():获取Servlet在web.xml文件中的配置名称,即指定的名称; ServletContext getServletContext():用来获取ServletContext对象,ServletContext会在后面讲解; String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,经过参数名来获取参数值; Enumeration getInitParameterNames():用来获取在web.xml中配置的全部初始化参数名称;
请求对象,能够从其中获取请求数据,请求头等
内部提供的方法挺多,一般咱们最关心的有:
javax.servlet.ServletRequest#getParameter
javax.servlet.http.HttpServletRequest#getHeader
javax.servlet.http.HttpServletRequest#getCookies
javax.servlet.http.HttpServletRequest#getRequestURI
还有一个比较重要的就是指定字符编码,如咱们一般要求提交的参数知足utf8编码,这时就能够以下设置
// javax.servlet.ServletRequest#setCharacterEncoding request.setCharacterEncoding("utf-8");
如咱们最经常使用的一个spring的fitler,关键代码以下
// org.springframework.web.filter.CharacterEncodingFilter#doFilterInternal // @Override protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) { request.setCharacterEncoding(this.encoding); if (this.forceEncoding) { response.setCharacterEncoding(this.encoding); } } filterChain.doFilter(request, response); }
返回对象,返回响应给调用方的结构,设置返回头
返回数据给调用方,主要就是利用这个东西了,内部提供的方法也很多,咱们主要关心的其实也并不太多
javax.servlet.http.HttpServletResponse#setHeader
javax.servlet.http.HttpServletResponse#addCookie
javax.servlet.http.HttpServletResponse#sendRedirect
javax.servlet.http.HttpServletResponse#sendError
javax.servlet.ServletResponse#setContentType
javax.servlet.ServletResponse#getOutputStream
, javax.servlet.ServletResponse#getWriter
javax.servlet.ServletResponse#setCharacterEncoding
这个配置,主要针对 Servlet 的顺序指定,URL匹配这两个问题,因此有必要研究下这个配置中的说明
一般web.xml的配置,下面两个是必须的
<!-- servlet的配置 --> <servlet> <!-- servlet的内部名称,自定义。尽可能有意义 --> <servlet-name>ServletDemo</servlet-name> <!-- servlet的类全名: 包名+简单类名 --> <servlet-class>com.xxx.ServletDemo</servlet-class> </servlet> <!-- servlet的映射配置 --> <servlet-mapping> <!-- servlet的内部名称,必定要和上面的内部名称保持一致!! --> <servlet-name>ServletDemo</servlet-name> <!-- servlet的映射路径(访问servlet的名称) --> <url-pattern>/servlet</url-pattern> </servlet-mapping>
其中 servlet-mapping 指定映射的路径,知足条件的会匹配对应的Servlet,匹配规则有如下几个定义
既然这个url匹配支持模糊匹配,那么问题来了,若是两个servlet都匹配了这个path路径,那么究竟是哪一个处理呢?
注意到前面有个配置参数:load-on-startup
注意 这个参数是加载顺序,而不是最终的匹配顺序
那么匹配顺序的优先级是:
参数获取,则主要区分get请求参数,post提交表单,上传的文件了
这种获取参数的方式,只能获取url上面的参数,没法获取到post的表单内容
String str = req.getQueryString();
// 返回全部的请求参数 javax.servlet.ServletRequest#getParameterMap
这种使用姿式,和咱们在SpringMVC中常见的基本一致
获取请求流,通常的使用姿式以下
InputStream stream = req.getInputStream(); byte[] bytes = new byte[stream.available()]; stream.read(bytes); String str = new String(bytes);
而后就须要本身对上面的请求参数进行处理了;两厢对比,常规的获取方法,直接使用 getParameter方式更加优雅
注意
经过getInputStream方式获取了请求数据以后,再经过 getParameter获取不到参数的,也好理解,请求的流,被你读取以后,其余的地方就没法获取流中的数据了
从请求参数中获取上传的文件,网上随意搜索了一下,发现大部分都使用apache的fileupload包, 其实处理的依然是inputstream这个请求流,只是逻辑比较复杂,粗略的翻看了一下源码,发现这一块还挺有意思的,准备单独的深刻看一下
返回数据,前面介绍HttpServletResponse的时候,就给出了两个方法
public PrintWriter getWriter() throws IOException;
public ServletOutputStream getOutputStream() throws IOException;
下面简单说一下上面的区别
PrintWriter | ServletOutputStream |
---|---|
字符流返回 | 字节流返回 |
须要字符编码 | 字节流直接返回(返回文件就很占优点了) |
说明
常见的请求头和返回头设置,对于servlet而言也是比较常见的,通常常见的几个设置
而实际的使用也比较简单了,以下便可
# javax.servlet.http.HttpServletResponse#addHeader response.addHeader("Content-Type", "text/html; charset=UTF-8");
建立一个自定义的嗯Servlet,而后拦截全部 /study 下面的请求
public class DocServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); writer.append("这是一个自定义servlet") .append("emoj😄==").flush(); System.out.println("hereher!!!!"); } protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException { Map map = req.getParameterMap(); System.out.println("arg: " + map); res.getWriter().append("success").flush(); } }
对应的xml配置以下
<servlet> <servlet-name>doc-servlet</servlet-name> <servlet-class>com.yihui.study.DocServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>doc-servlet</servlet-name> <url-pattern>/study/*</url-pattern> </servlet-mapping>
实测演示:
尽信书则不如,已上内容,纯属一家之言,因本人能力通常,看法不全,若有问题,欢迎批评指正