요청을 처리하고 응답을 제공하는 모든 요소의 집합을 서버라고 하며 하드웨어와 소프트웨어를 모두 포함합니다.
서버가 요청을 처리하고 응답할 때 따르는 원칙입니다.
서버 측에서 실행되는 Java 애플리케이션인 Server Applet은 Java 언어로 작성되었으며 Servlet 사양의 핵심인 Java 사양을 준수합니다.
서블릿은 전체 웹 서버에서 컨트롤러 역할을 하며 요청을 해당 비즈니스 로직 처리로 전달합니다.
Tomcat은 Servlet 사양과 JSP 사양을 구현하는 컨테이너입니다. Apache에서 제공하는 무료 오픈 소스 경량 수준의 애플리케이션 서버입니다. 중간 규모 시스템과 동시 접속 사용자가 많지 않습니다.
다목적 인터넷 메일 확장 프로토콜인 Multi Purpose Internet Mail Extensions는 파일을 받은 후 브라우저가 해당 구성 요소를 호출하여 열 수 있도록 파일 유형별 사양을 개발합니다.
두 가지 중요한 클래스레벨 효과.
ServletContext의 범위에서 볼 수 있습니다.
servletContext.setAttribute(name, object);//向servletContext作用域中添加属性,该属性为所有用户共享servletContext.getAttribute(name);//获取servletContext作用域中指定属性的属性值servletContext.removeAttribute(name);//从servletContext作用域中删除指定属性servletContext.getRealPath(path);//根据相对于项目的路径获取资源的绝对路径URLservletContext.getResourceAsStream(path);//获取路径文件的输入流servletContext.getInitParameter(name);//获取初始化参数的值
얻는 방법입니다.
this.getServletContext();//HttpServlet提供了获取ServletContext实例对象的方法,在doGet或者doPost方法内部request.getServletContext();//通过request对象获取HttpSession session = request.getSession(); session.getServletContext();//通过session对象获取2.ServletConfig
public void init(ServletConfig config) throws ServletException { String initParameter = config.getInitParameter("initParamName"); }
Web容器启动时会创建两个与Servlet相关的Map集合,两个集合的key值均为urlPattern,即请求uri,第一个Map的value是Servlet的引用变量,第二个Map的value是Servlet的全限定性类名。请求到达Web容器后,系统先搜索第一个Map集合,如果存在与uri对应的引用变量,则获取该引用变量,如果不存在,继续搜索第二个Map集合,获取对应的全限定类型,创建对象,并把引用变量存到第一个Map集合中。
Servlet ServletConfig Serializable
| | |
--------------------------------------------------
|
|
Servlet接口是Servlet规范中定义的,服务器自动调用其中service方法处理请求,该接口有多个抽象方法,很多在实际开发中很少使用,实现该接口需要实现其中的全部抽象方法,因此不采用直接实现Servlet接口的方法创建Servlet。
GenericServlet实现Servlet接口中大多数抽象方法,保留了一个抽象方法service,继承该抽象类创建servlet,必须实现该抽象方法。HTTP中多个请求方法在处理请求前必须做一些固定的前置工作,如果实现该serivce方法就需要在每一个Servlet的service方法中都编写前置工作代码,造成代码冗余。为了解决此问题,tomcat提供了一个GenericServlet的子类HttpServlet,HttpServlet采用固定行为结构的模板方法模式将前置工作固定在一个方法,用户在创建Serlvet时继承HttpServlet,然后重写与请求方式对应的方法即可。(具体参考源码)
protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException { String method = req.getMethod();if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logic doGet(req, resp); } else {long ifModifiedSince;try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) {// Invalid date header - proceed as if none was setifModifiedSince = -1; }if (ifModifiedSince < (lastModified / 1000 * 1000)) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
从中可以看出Get请求在实际执行前做了很多准备工作。
Servlet默认在调用时创建并初始化,这也是工作原理中第一个Map集合引用变量为空情况出现的原因。对一些必定会被访问并且访问频繁的Servlet可以设定为在容器启动时创建并初始化,提高访问速度。
<load-on-startup>int类型数字</load-on-startup>
小于0:默认值,调用时创建初始化。
等于大于0:在Web服务器启动时创建初始化,值越小,优先级越高。出现相同值时,不会出现异常,容器自定义顺序执行。
this.getInitParameter("");//获取初始化参数this.getServletName();//获取配置文件<servlet-name>标签的内容this.getServletContext();
6.由于继承HttpServlet创建的Servlet属于自定义类,系统不知晓,必须在配置文件中配置:
<servlet> <servlet-name>bothRegisterServlet</servlet-name> <servlet-class>com.servlet.register.BothRegisterServlet</servlet-class> <init-param> <param-name>xxx</param-name> <param-value>xxxx</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported></servlet><servlet-mapping> <servlet-name>bothRegisterServlet</servlet-name> <url-pattern>/bothRegisterServlet01</url-pattern></servlet-mapping>
웹 컨테이너에서 서블릿 객체에 접근할 때는 어떤 방법을 사용하더라도 간접적으로만 접근할 수 있기 때문입니다. 일반적으로 서블릿에 접근하기 위해서는 url을 사용하므로 일대일 관계를 구축해야 합니다. 접근할 때 사용하는 URL과 최종 리소스 서블릿 간의 매핑 관계가 바로 servletMapping이 존재하는 이유입니다.
서블릿 개체에 대해 여러 URL 형식을 구성할 수 있습니다.
네 가지 요청2. 요청에는 어떤 정보가 포함되며, 요청을 통해 어떤 정보를 얻을 수 있나요?
3. 일반적인 방법:
getAttribute: 범위 내에서 속성을 가져옵니다. 반환 유형은 속성이 없으면 null이 반환됩니다.
⑵ request.getSession()과 request.getSession(boolean create)
getSession(false): 쿠키를 기반으로 세션 개체를 가져옵니다. 쿠키가 없으면 null을 반환합니다.
⑶request.setCharacterEncoding(): 요청 본문의 인코딩 방법, 즉 브라우저에서 제출한 데이터를 구문 분석할 때 서버에서 사용하는 인코딩 방법을 설정합니다.
⑷request.getContentLength(): POST에만 의미가 있는 요청 본문의 바이트 길이를 가져옵니다.
⑸request.getQueryString(): URL 뒤의 요청 문자열을 가져옵니다. 이는 GET 요청에만 의미가 있습니다.
⑹request.getRequestDispatcher().forward(request,response)request.getRequestDispatcher().include(request,response)의 차이점:
앞으로 요청은 계속해서 앞으로 이동하며 응답 권한은 후속 리소스로 이전됩니다. 즉, out.write
include include는 다음 리소스를 자신의 일부로 처리하여 다음 리소스가 응답할 수 있을 뿐만 아니라 자체적으로 응답할 수도 있습니다. 이는 자체 코드의 일부를 다음 리소스로 나누는 것과 같습니다.
4. 같은 요청은 무엇인가요?
동일한 요청은 범위 내 요청 매개변수, 속성 등의 정보를 공유합니다.
Servlet规范定义的一个向浏览器发出响应的对象,由Servlet容器自动创建。
由于存在多种响应数据类型,因此服务器在响应前必须指明数据类型,以便浏览器根据指定类型处理接收的数据。
response.setContentType("text/html;charset=UTF-8");//以HTML方式处理
response.setHeader(name,value);
response.addCookie(Cookie cookie);
response.sendRedirect(url);
PrintWriter out=reponse.getWriter();
ServletOutputStream sos=response.getOutputStream();
代码继续执行,对响应结果或者request作用域没有影响,因为响应已经结束,请求已转发给其他资源,自身就失去了处理请求的能力,但对session\applicatiion作用域可以产生影响。通常不在响应或者跳转之后对整个处理过程施加影响。
由服务器生成,保存在浏览器端的存储会话信息的对象。
Servlet规范提供了Cookie类,用于创建Cookie对象:
Cookie cookie=new Cookie(name,value);
由服务器创建,保存在客户端,浏览必须允许保存Cookie将cookie:
response.addCookie(cookie);
Cookie在访问服务器时自动提交,这种提交不是无选择地对任何访问路径都提交,而是只对设定的路径提交。在未单独设定Cookie的绑定路径时,Cookie与生成Cookie的访问路径绑定,访问该路径下任何一个资源时,浏览器自动提交Cookie。
可以设定Cookie的绑定路径,使Cookie不受生成路径的限制:
cookie.setPath(String uri);
默认情况下,Cookie保存在浏览器缓存中,浏览器关闭,Cookie销毁。如果希望Cookie中保存的信息长期存在,可以将Cookie保存到本地硬盘中,前提是当前浏览器支持。
cookie.setMaxAge(int expiry);//以秒为单位
取值大于0:将Cookie保存到硬盘中,无论浏览器是否关闭,指定时长过去后,Cookie被销毁。
等于0:立即销毁Cookie。
小于0:默认情况,将Cookie保存在浏览器缓存中,浏览器关闭,Cookie销毁。
String name = cookie.getName();//获取Cookie的名称String value = cookie.getValue();//获取Cookie的值cookie.setValue(newValue);//修改Cookie的值
Cookie主要用于保存浏览器关闭以后需要保留的会话信息,如登陆信息,实现免登陆功能。
在HTTP协议中,浏览器向服务器发送请求,服务器响应完毕后,连接结束,服务器端没有保存本次请求的任何信息,这就是HTTP协议的无状态特性。如果需要保存会话信息,就必须提供一种解决方案,而Session就是这个解决方案。
Session是用来在服务器端保存会话信息的对象,比如保存用户在网站上的足迹等。
在浏览器开启Cookie的情况下,从浏览器第一个访问网站到浏览器关闭的时间内浏览器与服务器所有的互动都是在同一个会话中。如果浏览器关闭了Cookie,那么浏览器每向服务器发送一次请求,都开启一个新的会话,即服务器端都会新建一个Session对象。
第一次访问时,服务器会自动创建一个Session对象,并为Session对象分配一个唯一的32位的id,同时生成一个Cookie对象,name为JSESSIONID,value为Session的id。在Cookie的有效期内,再次访问服务器时,根据value值获取对应的Session对象,这样就保证了在同一次会话中存在的始终是同一个Session对象。
Session对象在浏览器第一次访问服务器时创建,如果浏览器长时间不向服务器发送请求,在指定的时长之后,服务器会销毁Session对象。
这里所说的时长不是从Session创建到销毁的时间长度,而是浏览器长时间发送请求,服务器保存Session对象的最大时间长度,通过以下方法设置,以秒为单位:
session.setMaxInactiveInterval(int interval);
通过以下方法,浏览器可以主动销毁Session对象:
session.invalidate();
Session主要用于在同一会话中共享数据,所以对Session的主要操作是操作作用域中的属性:
session.setAttribute(name,value);//向作用域中添加属性session.getAttribute(name);//获取作用域中的属性session.removeAttribute(name);//从作用域中删除属性
服务器接收到请求以后,首先对请求进行预处理,然后将请求转发给其他的资源继续处理,这种转发叫做请求转发。
服务器调用特定的方法向浏览器发送一个资源路径,浏览器访问该路径,这一过程叫做重定向。
请求转发是服务器调用不同的资源处理同一请求,始终是同一请求。
重定向使得浏览器再次向服务器发送请求,前后是两个不同的请求。
为耗时的任务分配一个线程,主线程继续执行后面的代码,执行完毕,将主线程归还线程池,以便执行其他的请求。
Servlet是单例多线程的,允许并发访问的线程数目有限,为此Servlet建立了一个线程池,请求必须从线程池中获取了线程才能访问Servlet。若一个请求长时间占有线程,可能导致后面的请求长时间等待,降低了程序的吞吐能力。如果一个线程从Servlet线程池中获取了线程以后,另外开启一个线程处理耗时的任务,及时将主线程归还线程池,就解决这个问题。
异步机制的作用主要不是为了提高单次执行速度,而是提高吞吐量,即同一时间段内允许更多的请求访问Servlet。为了提高访问的线程数目,降低每次访问占有Servlet线程的时间,将耗时的任何交个另外一个线程处理,将主线程及时归还线程池。
Servlet接收到请求以后,对请求进行初步处理,然后开启一个异步线程处理具体的业务,Servlet线程继续执行后面的代码,执行完毕后,将Servlet线程归还线程池,以便其他请求使用。等待异步线程执行完毕后一起响应,异步线程执行完毕主要有两个标志:
在异步线程内部调用complete方法。
超时时间结束。
超时时间不并代表异步线程的生命时长,而是最大生命时长。如果在超时时长内,异步线程调用了complete方法,异步线程提前结束。
异步线程默认的超时时长是10s(Servlet不同版本不同),当主线程执行完毕,同时超时时长结束或者异步线程提前结束,服务器开始向浏览器发送响应,销毁request、response对象,关闭输出流,如果异步线程未执行完毕,那么异步线程中已执行的响应会响应到浏览器,未执行的响应不会响应到浏览器。
分配给异步线程的时间不是无限的,因此存在一个响应时机的问题。
在主线程执行完毕并且异步线程超时时长用完或者提前结束时响应。
AsyncContext ac=request.startAsync(); ac.setTimeout(int mills); ac.start(Runnable run);//将异步线程管理对象ac作为参数传入异步线程中,通过该参数可以获取request\response
由于异步机制的设计目的是为了使请求尽快归还Servlet线程,提高程序的吞吐量,并未显著提高响应速度。异步机制通常不直接用作向浏览器输出响应内容,如在异步线程内部使用out.write直接向浏览器输出,而是用来处理耗时的任务,将处理结果存放到session/application等作用域中。
8.还可以使用AsyncContext对象为异步线程添加监听器,监听异步线程的执行过程。
1.配置Servlet、Filter、Listener、contextParams等构成应用程序的重要信息。
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>default.html</welcome-file></welcome-file-list>
注:在配置文件中书写路径时,只有欢迎列表中的路径不需要在前面加“/”,其他地方的路径都需要在前面加“/”,因为欢迎页面只能放在WebContent根路径下,不能放在WebContent根路径下的文件夹内,其路径相对固定,因此可以简写。
<error-page> <error-code>404</error-code> <location>/xxxx</location>//可以放在WebContent目录下任意位置</error-page>
<error-page> <exception-type>java.lang.NullException</exception>//异常类必须写完整的类名 <location>/xxxx</location></error-page>
<context-param><param-name>paramName</param-name><param-value>paramValue</param-value></context-param>
Servlet3.0新增注解式开发,注解式开发就是将在编写在配置文件web.xml中的信息转移到类文件上。
注解方式:
在类名上添加注解:
@WebServlet(urlPatterns={"",""},loadOnStartup=1,initParams={@WebInitParam(name="",value="")},asyncSupported=true)
两种注册方式同时存在,如果映射路径不相同,相当于存在一个集中了所用路径的Servlet,如果存在相同路径,服务器无法启动。
1.Servlet3.0提供一个Part类型,该类封装了上传文件信息。
2.文件名存储在一个名为Content-Disposition的请求头中。
Part part=request.getPart(文件字段名);//获取文件封装对象String fileName=part.getHeader("Content-Dispostion");//获取文件名part.write("parentPath/"+fileName);//将文件保存到指定路径,只能使用绝路径
1.Servlet提供了ServletOutputStream用作文件下载的输出流。
2.文件下载时必须设置浏览器以附件的形式处理从服务器获取的数据:
response.setHeader("Content-disposition","attachment;filename=xxxx");
如果请求头中设置的文件名含有中文必须转化为ISO-8859-1的编码方式。
3.从服务器获取输入流,利用ServletOutputStream输出流将文件写到用户指定路径:
InputStream is = getServletContext().getResourceAsStream("/Files/upload.txt"); ServletOutputStream os = response.getOutputStream();
입력 스트림과 출력 스트림을 사용하여 후속 작업은 입력 스트림의 내용을 출력 스트림에 쓰는 것인데, 이는 일반적인 IO 작업입니다.
서블릿은 싱글톤 형태로 멀티스레드 환경에서 실행되며, 인스턴스 변수는 힙의 객체에 저장됩니다. , 그리고 힙은 여러 스레드에 의해 공유되므로 인스턴스 변수에는 스레드 안전성 문제가 있는 반면 정적 변수는 여러 스레드에 의해 공유되는 메서드 영역에 저장되며 로컬 에도 문제가 있습니다. 얼굴 변경 저장소 스택에서는 스택의 데이터가 내부적으로 공유되지만 스택 간에는 공유되지 않습니다. 즉, 하나의 스레드에는 하나의 스택이 있으므로 로컬 변수는 스레드로부터 안전합니다.
전역 변수를 지역 변수로 변환합니다.
동기화된 메소드 또는 동기화된 블록에 전역 변수를 수정하는 코드를 추가합니다.
전역 변수를 ThrealLocal에 저장하고 변수의 복사본을 각 스레드에 할당하며 각 스레드는 서로 독립적으로 작동합니다.
오픈 리소스: 예 사용된 리소스는 공개되어 허가 없이 접근할 수 있습니다.
권한자원: 이용자의 개인정보를 저장하는 자원으로, 본인 확인을 거쳐야 접근할 수 있습니다.
해당 웹사이트에 로그인하신 후, 다음번 웹사이트 방문 시 동일한 브라우저를 사용하실 때 다시 로그인하실 필요가 없습니다.
로그인 정보(사용자 이름, 비밀번호)를 쿠키에 저장하고, 쿠키를 로컬에 저장한 후, 웹사이트 방문 시 자동으로 쿠키를 제출하고, 필터를 통해 전달합니다. 또는 인터셉터 인증을 통과하시면 로그인 없이 바로 접속하실 수 있습니다.
동일한 브라우저: 로컬에서 쿠키 개체 확인 정보를 얻기 위해 로그인이 필요하지 않습니다.
Servlet3.0 구성 요소를 확인할 수 있습니다. 즉, Servlet, Filter 및 Listener를 프로젝트에 선반 패키지로 삽입할 수 있습니다.
프로젝트 생성 웹 조각 프로젝트.
패키지 jar 파일.
lib 디렉터리에 넣어서 랙 패키지로 사용하세요.
일반적으로 사용되는 일부 서블릿 구성 요소를 랙 패키지에 캡슐화하고 이를 lib 디렉토리에 직접 넣어서 사용할 수 있습니다(예: POST 요청에서 중국어 왜곡 문자를 해결하기 위한 필터).
웹이 실행될 때 서블릿, 필터, 리스너를 등록합니다.
보안상의 이유로 웹 서버가 시작될 때만, 즉 ServletContextListener 리스너를 통해서만 등록할 수 있습니다.
위 내용은 서블릿의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!