【Web】javaEE课程复习笔记

本文是一篇详细的JavaEE复习笔记,涵盖了Web应用的基础,包括Servlet、Tomcat容器、HTTP缓存策略、JSP、Struts、Spring及Spring MVC等内容。深入探讨了WebSocket、Session接口、EL表达式以及数据访问技术。文中还讲解了Spring框架的注解、配置以及Controller的使用,以及视图解析和ModelAndView的概念。通过对各种核心技术的解析,帮助读者深入理解JavaEE开发的核心概念和技术要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaEE复习笔记

根据上课的笔记整理与补充。涵盖web应用开发基础,jsp,标签,注解,struts,spring, mvc, 数据访问等内容
(因为转于个人blog,csdn图片无法显示,可至下面链接查看https://sakuyui.github.io/2019/12/27/JavaEE%E5%A4%8D%E4%B9%A0%E7%AC%94%E8%AE%B0/)
contact: 405544641@qq.com

Spring的思想 控制翻转:让容器管理对象的创建与销毁,依赖注入:利用反射实现,动态地向一个对象提供其所需的其他对象

JavaEE三大组件: Servlet, Filter, Listener
组件必须有 init(conf) destroy()

web容器(servlet容器)

请求怎么来到servlet呢?答案是servlet容器,比如我们最常用的tomcat,同样,你可以随便谷歌一个servlet的hello world教程,里面肯定会让你把servlet部署到一个容器中,不然你的servlet压根不会起作用。
tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。

import javax.servlet servlet是个接口
HttpServlert实现Servlet
使用Servlet ServletRequest ServletRespond
1.首先要在web.xml中进行配置

<servlet>
	<servlet-name>A</servlet-name>   //servlet名
	<servlet-class>com.xxx.xx.xx.servlet类名</servlet-class>  //对应的类
	<init-param>   //初始化参数
		<param-name>p1</param-name><param-value>123</param-value>
	</init-param>
</servlet>
//! 到这为止已经定义好servlet,不会有任何错误。 当服务器启动后,也会创建好servlet. 但是无法访问因为没mapping
<servlet-mapping>
	<servlet-name>A</servlet-name> //要和上面对应
	<url-pattern>/login</url-pattern>     //注意 /代表的是web Content的位置
</servlet-mapping>


**url-pattern:  /是缺省匹配,若当前访问资源地址的所有 Servlet 都不匹配时,就由缺省的 Servlet 进行处理
               优先级:全路径匹配>部分路径匹配>拓展名匹配
               如果我们web应该中同时配置"/"和"/*",那么默认的Servelt永远都不会被匹配到,所有的路径最终都会匹配到"/*"上
               /不能匹配jsp,原因是jsp容器已经默认映射了一个*.jsp,优先级要高于/  /*可以
               精确路径匹配>最长路径匹配>扩展匹配     /a/*.xxx 这样方式会报错。不能混搭。
注:Filter不会像servlet只匹配一个。 顺序与定义顺序相同
/*和/** 后者会匹配更多的目录 (Ant path匹配。spring支持。还支持正则表达式,进行更复杂的匹配)

关于url-pattern的/, 同样在struts中,默认映射了*.action *.do , /无法覆盖他们
strut2的配置文件加载顺序为:

   Struts-default.xml---> struts-plugin.xml--> struts.xml-->   struts.properties--> web.xml

使用servlet

//AServlet.java
package a; //倒序 com.xxx,部门,项目:模块

先引入这3个包
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class AServlet extends HttpServlet{
	

   /*  默认已经实现
   private ServletConfig config;
   @Ovrride
   public void init(ServletConfig config) throws ServletException{
      super(config);
      init();
    }*/

	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws    IOException,ServletException{
    response.setContentType("text/html;charset=UTF-8");  //默认ISO8859-1
    response.setCharacterEncoding("UTF-8")//设置编码
    PrintWriter out=response.getWriter();
    out.println("<h1>this is servlet</h1>");
    //不要close()   谁创建的流谁负责关闭
	    }
	
	@Ovrride
	protected void doPost(HttpServletRequest request,HttpServletResponse){
	}

/*
	@Override
	public void destroy(){
        super.destroy();
    }

    @Override
    public void service(SevletRequest req,ServletResponse res) throws ServletException,IOException{



       res.setContextType("text/html");
       PrintWriter out=response.getWriter();
       out.println("this is servlet");

       //获取config
       //getServletConfig();
		//!!!!考ServletConfig   的函数

       HttpServletRquest hsr=(HttpServeltRequest) req;
       HttpServletResponse hsres=(HttpServletResponse) res;
       //GET / HTTP/1.1\r\n            获取资源
       //GET /HTTP/a HTTP/1.1\r\n
       String method=res.getMethod();
       if(method.compareTo("POST")==0){
           doPost(req,res);
       }else if("GET".equals(method)){
            doGet(req,res);
       }

}      
*/
   }

注意事项

  • doPost doGet serice 一般抛2个异常 ServletException 和IOException

  • serve的两个参数是ServletRequest和ServletResponse

  • Context-Type:

    • text/html : HTML格式
      text/plain :纯文本格式
      text/xml : XML格式
      image/gif :gif图片格式
      image/jpeg :jpg图片格式
      image/png:png图片格式
      application/xhtml+xml :XHTML格式
      application/xml : XML数据格式
      application/atom+xml :Atom XML聚合格式
      application/json : JSON数据格式
      application/pdf :pdf格式
      application/msword : Word文档格式
      application/octet-stream : 二进制流数据(如常见的文件下载)
  • this.getServletConfig().getInitParameter(String); 获取servlet的初始化参数

每个servlet有一个servletconfig,但是全局只有一个servletcontext (每个web应用仅有一个,servletcontext也可以叫applicationContext,是最大的web域对象)

使用**response.setContentType(String);**设置 如text/html;charset=UTF-8

  • 输出办法: 首先从response.getWriter();获取PrintWriter对象,之后利用其进行流操作输出 (println();)
  • HttpServlet 中已存在 service()方法.缺省的服务功能是调用与 HTTP 请求的方法相应的 do 功能。
    例如,如果 HTTP 请求方法为 GET,则缺省情况下就调用 doGet()。 super(req,res)

setContentType(String) 和 setCharacterEncoding()的区别:前者设置的是页面的静态文字编码(浏览器显示的编码),后者关系到动态参数的编码

HTTP缓存**(必考)**

  • http缓存有强缓存,协商缓存
    +步骤1. 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。 (返回200)
    2.如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。
    3.如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。

  • 强缓存: 利用http的返回头中的Expires或者Cache-Control两个字段来控制的。前者表示缓存过期时间(具体时间),后者表示相对时间。如Cache-Control:3600,代表着资源的有效期是3600秒。所以服务器与客户端时间偏差也不会导致问题。
    同时启用的时候Cache-Control优先级高

    • Cache-Control可包含的字段:
      1.max-age 单位s
      2.s-maxage 同1,只适用于共享缓存,私有缓存中被省略
      3.public 响应可以被任何对象缓存
      4.private 响应只能被单个用户,非共享。不能被代理服务器缓存
      5.**no-cache:**强制缓存了响应的用户,在使用数据前都要先发请求到服务器
      6.no-store:禁止缓存
  • 协商缓存:
    服务器根据http头信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存中加载资源。

Last-Modify/If-Modify-Since
ETag/If-None-Match
与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化*。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95XD8hDL-1577506046387)(./1576666287803.png)]

ServletRequest
>>getAttribute(String) //获取存在request的属性 是Object
>>getAttributeNames() //Enumeration 用hasMoreElements() nextElement()进行遍历
>>getParameter(String)//获取存在request的参数 只能是String (可以获得通过get post传进来的数据)
>>getParameterNames() //返回迭代器
>>getParameterValues() //返回String[]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89nEmyji-1577506046388)(./1576668415360.png)]

>>getProtocol()
>>getRealPath(String path) //寻找某个资源在服务器文件系统上的实际地址
>>getServletContext()

HttpServletResponse
>>addCookie(Cookie cookie)
>>getHeader(String name)
>>addHeader(String name, String value)
//继承来的
>> getWriter()
>>setContentType(String type)

  • ServletConfig getServletConfig(); //必考

ServletConfig

  • getInitParameter(String name)
  • getServletName()
  • getServletContext()

!!! 必考ServletContext
context可以直接在servlet里get,也可以从request.getSession().getServletContext() 也可以 request.getServletContext();

servletcontent.getRealPath("/")和servletcontent.getContextPath()的区别
前面是获取ServletContext 所在的文件系统上的实际位置。 后者是获取配置的servletContext路径

ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
凡是域对象都有如下3个方法:

**setAttribute(name,value);**name是String类型,value是Object类型;

往域对象里面添加数据,添加时以key-value形式添加

getAttribute(name);

根据指定的key读取域对象里面的数据

removeAttribute(name);

根据指定的key从域对象里面删除数据

同时因为都是web域对象。所以除servletcontext外,**其他三个域都能通过getServletContext()**获取到servletContext

可以获取web.xml中的全局参数

  <context-param>
         <param-name>param1</param-name>
         <param-value>value1</param-value>
  </context-param>
 用servletContext.getInitParameter(parameName);获取

>>getContextPath();
设置contextpath的方式
/META-INF/context.xml

!!可以获取servletContext()的方式

  • ServletConfig的getServletContext()
  • request.getSession().getServletContext()
  • 直接 getServletContext();

WEB应用结构

xxxxxxxxxxxx\first
-> WEB-INF
----> classes
----> lib
----> web.xml
-> META-INF
----> context.xml

!!!URL 三部分
1.schema 2.服务器位置 3.资源路径

<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>
header

http的两部分内容:header body ,header项用\r\n区分,区分 两次回车换行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c8EoNWPb-1577506046394)(./1576751175527.png)]

编码 base64:3个字节为一组 ucs:任何一个字符都是4字节

http状态码:
404 资源不存在
500 服务器遇到外部故障,一般是异常
2xx OK
3xx 重定向
4xx 客户端错误
–>401 客户端证书无效
–>403 请求结构正确。但是服务器不想处理.403暗示了所请求的资源确实存在。跟401一样,若服务器不想透露此信息,它可以谎报一个404
–>405 请求方法错误。比如用了不支持的协议,或者不支持get,结果用了get

5xx:服务器端错误
502 代理错误
500 异常
501 服务器不能识别一个方法。类似405,但是405是能够被服务器识别,但是资源不支持该方法.
101表示服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。

web.xml

<welcome-file-list>  //可以设置多个,可以访问到web-inf内的文件,会返回第一个找到的文件,找不到就404,首页的路径只能是一个实际存在的物理文件地址,不能将首页设置成Servlet或Controller的地址,再通过来Servlet或Controller返回一个页面
	 <welcome-file>a.jsp</welcome-file>
	 <welcome-file>b.html</welcome-file>
     <welcome-file>c.html</welcome-file>
</welcome-file-list>

xml区分大小写

部署web application在Tomcat

<Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">
		
	
	<!-- 部署 "三个" web application  -->
	<Context path="/a" docBase="/somefoler/first"/>  //虚拟路径1 context path=/a
	<Context path="/s" docBase="/otherfolder/second"/> //虚拟路径2 context path=/s
	<Context path="" docBase="/otherfolder/second"/>   //虚拟路径3

    <!-- SingleSignOn valve, share authentication between web applications
         Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->

    <!-- Access log processes all example.
         Documentation at: /docs/config/valve.html
         Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log" suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />

  </Host>

**!!如何自己设计ServletContext().getRealPath(); **
A: ServletContext().getContextPath();可以用,然后去tomact的 server.xml中寻找对应docBase…然后就可以get到了,如果docBase是相对路径的话,也可以根据tomcat所在路径加上这个相对位置确定

//使用真实路径读取文件
String filename = getServletContext().getRealPath("/WEB-INF/aFolder/a.txt");
FileInputStream fis = new FileInputStream(filename);

###web socket

现在前后端通讯的常用的方式有ajax,websocket,还有fetch

  //创建套接字
  Socket s = new Socket("www.baidu.com", 80);  //这是Java的Socket建立过程。直接访问底层的TCP协议。
  var socket = new WebSocket("ws://localhost:8080/websocket1/b");  //JavaScript代码。

websocket可以跨域访问。非常灵活。

Connection: Upgrade
Cookie: JSESSIONID=6FFBEA8EB6951EAD7D123A2D7ED70861
Host: localhost:8080
Origin: http://localhost:8080
Sec-WebSocket-Key: 6ZxylD/4f4qccKeapm3LEQ==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko

响应代码:101,不是200, 101表示服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。
在发送完这个响应最后的空行后,服务器将会切换到 在Upgrade消息头中定义的那些协议。: 只有在切换新的协议更有好处的时候才应该采取类似措施。
例如,切换到新的HTTP版本比旧版本更有优势,或者切换到一个实时且同步的协议以传送利用此类特性的资源。

	Connection: upgrade
	Date: Thu, 12 Sep 2019 00:54:07 GMT
	Sec-WebSocket-Accept: 5uiTO0X9qutU+74Ugp/7eMHoXQk=
	Upgrade: websocket

和以往的http请求不同,增加了Connection: Upgrade, Upgrade: websocket等请求头,大家理解,客户端请求建立websocket.
服务器可以不支持。当然,客户端程序来自同一个服务器,在某个使用websocket的应用中,显然支持。我们的JavaEE版本8支持websocket.
至于请求中的Sec-WebSocket-Key, 是base64编码,源数据是16个字节的随机数。服务器收到这个数据, 并不做Base64解码,而是直接拼上一个magic字符串,
“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”, 然后转换为utf-8编码的字节数组,最后做SHA1,(见MD5,CRC,SHA-1,SHA-256)。
对SHA1产生的20个字节(160个比特位)做BASE64,然后就是Sec-WebSocket-Accept: 5uiTO0X9qutU+74Ugp/7eMHoXQk=, 返回给客户端。
客户端当然做同样的算法,然后做比对,实际上就是完成websocket的握手过程。

握手完毕,http协议“转换”到websocket协议。
  • 1、客户端:申请协议升级
  • 2.服务端:响应协议升级 :状态代码101表示协议切换。到此完成协议升级,后续的数据交互都按照新的协议来。
  • 3、Sec-WebSocket-Accept的计算 :Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTQfhJJL-1577506046395)(./1576755405347.png)]

实例:
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// Connection opened
socket.addEventListener('open', function (event) {
    socket.send('Hello Server!');
});

// Listen for messages
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

//javaee
@ServerEndpoint("/chatroom/{roomId}/{nickName}")
public class ChatRoomServer{
		@OnOpen//连接打开时
		public void onOpen(Session session,@PathParam("roomId") long roomId,
        @PathParam("nickName") String unDecName){
        }  //可以注入参数
        @OnMessage  //消息抵达
	  
	    public void onMessage(Session session, String message, @PathParam("roomId") long roomId, 
		@PathParam("nickName") String unDecName)
	    {
	
	    }

		@OnClose
	    public void onClose(Session session, @PathParam("roomId") long roomId, 
    		@PathParam("nickName") String unDecName)
	    {}
	

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gbJcKWAU-1577506046397)(./1576755801639.png)]

package a;

//Socket客户端
import java.io.*;
import java.net.*;

import javax.websocket.*;

@ClientEndpoint
public class WebSocketClienet {

//就是例子代码,只有一个session
public static Session session = null;

@OnOpen
public void onOpen(Session session) {
	try {
		this.session = session;
		System.out.println("create a session.");
		session.getBasicRemote().sendText("hello");
		System.out.println("send hello to server.");
		
	} catch (IOException ex) {
		
	}
}

@OnMessage
public void processMessage(Session session, String message, boolean last) {
	System.out.println(message);
}

@OnClose
public void end() {
	System.out.println("bye server.");
}

@OnError
public void onError(Throwable t) throws Throwable {
	System.out.println("meet some exception in client.");
	t.printStackTrace();
}



public static void main(String[] args) throws Exception {
	WebSocketContainer container = ContainerProvider.getWebSocketContainer();
	container.connectToServer(WebSocketClienet.class, URI.create("ws://localhost:8080/websocket1/b"));
	
	for(int i = 0; i < 10; i++) {
		Thread.sleep(1000);
		session.getBasicRemote().sendText("" + new java.util.Date());
	}
	session.close();
}

}

####Server Sent Event(SSE):服务器向客户端发送消息 (应该是只做了解)

一般服务器向客户端发送消息常用的方式就是用setInterval去做轮询或者是websocket。只是前者setInterval**(//每60秒执行myFunction()一次 setInterval(“myFunction()”,60000); )**轮询这个中间的时间间隔需要考虑好,如果事件间隔较短,这对服务器的压力比较大,如果事件较长,则有些需要立即立即做出响应的方式是做不到的。后者的websocket相对来说技技术要求有点高,实现起来比较复杂。所以就有现在的这种方式就是Server-sent Events我们只需要需要在服务器端将事件流发送给前端,然后前端接收到后端所传给的事件流,然后触发事件,这是事件的捕获和监听其实和前端的事件捕获和触发是一样的

用法:

var evtSource = new EventSource('/sse'); //创建es对象,/sse是服务器端给的向前端发送事件的接口地址。通过get方式进行发送事件。
//var evtSource = new EventSource('http://www.baidu.com', { withCredentials: true }); (如果跨域)
//至此接收器创建好了
evtSource.onmessage = function (e) {
	  console.log(e.data)
}
//也就是当后端发送的内容之后就会进行触发,并且将data给打印出来,首先要提出的的是,Server-sent Events 所发送的内容都是字符串的流而且是通过utf-8的编码格式的,如果后端希望给前端发送一串json,也需要将json转化成相对应的字符串,然后在发送给前端,前端接收之后,再讲所发送的字符串转换成json,然后进行处理。

//然后就是监听后端发送给前端的事件内容,不如说,我们后端给前端sent一个testEvent事件,前端通过事件接收者,去触犯相对应的事件监听,因此就有了下面的工作流程
evtSource.addEventListener('testEvent', function (e) {
	  console.log(e)
})
...
后端应该如何才能给我们发送事件呢,
首先我们发送内容是需要给前端设置一个mime为text/event-stream,然后在进行发送事件的内容
'Content-Type': 'text/event-stream'
  • 注解@Endpoint("/b") // @ServerEndpoint("/b")指定服务器资源
  • sse使用 javax.socket.endpoint
javax.websocket.Endpoint类

使用方法。一个类继承Endpoint,之后重写onOpen,onClose,onError
对于Socket来说,每一端都是一个EndPoint
还可以具体一点,用ServerEndpoint或者ClientEndpoint

Session 接口 (websocket的)

>> getBasicRemote() :返回RemoteEndpoint object,getAsyncRemote是非阻塞式的,getBasicRemote是阻塞式的

大部分情况下,推荐使用getAsyncRemote()。由于getBasicRemote()的同步特性,并且它支持部分消息的发送即sendText(xxx,boolean isLast). isLast的值表示是否一次发送消息中的部分消息,对于如下情况:
session.getBasicRemote().sendText(message, false);
session.getBasicRemote().sendBinary(data);
session.getBasicRemote().sendText(message, true);
由于同步特性,第二行的消息必须等待第一行的发送完成才能进行,而第一行的剩余部分消息要等第二行发送完才能继续发送,所以在第二行会抛出IllegalStateException异常。如果要使用getBasicRemote()同步发送消息,则避免尽量一次发送全部消息,使用部分消息来发送。

>>WebSocketContainer getContainer()

####WebSocketContainer
connectToServer(class,URI) ,返回Session

所以… session <-> WebSocketContainer 可以相互获取。 session是从container连接服务器后来的.

至于Endpoint,客户端和服务器都是一个Endpoint

###HttpSession

import javax.servlet.http.*;

其是一个域对象。因此也具有
getAttribute(String),setAttribute(String,Object)等函数
同时有
getID()
,**getServletContext()**等函数
创建时间 getCreationTime()
getMaxInactiveInterval() //超时时间

设置超时时间
在web.xml中

<session-config>
	<session-timeout>2</session-timeout>  //2分钟,默认为30
</session-config>
#也可以session.setMaxInactiveInterval(30*60);
  • 扔到Attribute中的对象要序列化

Q:如何识别一个request是某个会话的
tomcat有个全局的map,产生的session对象的id一定放在**response中,返回给浏览器.**下次请求会带上它

一般来说Session是基于Cookie实现的,
会话追踪手段

  • 手段1:cookies.

  • 手段2: URL重写 如果浏览器不支持Cookie或用户阻止了所有Cookie,可以把会话ID附加在HTML页面中所有的URL上,这些页面作为响应发送给客户。这样,当用户单击URL时,会话ID被自动作为请求行的一部分而不是作为头行发送回服务器。这种方法称为URL重写(URL rewriting)。

  • 手段3:隐藏域

      使用隐藏域:<input type="hidden" name="…" value="…">
    

jsessionID ssessionID …

刷新是个问题
有时不用httpsession, 把会话信息放在分布式存储系统。只要ID在就行

####Cookies

response.addCookies(Cookies);
//Cookie(String name, String value)
压缩(要考)

gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRzVaPxo-1577506046399)(./1576837387364.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b23yqMS7-1577506046402)(./1576837550820.png)]

RequestDispatcher

可以用requestDispatcher来分发请求到多个组件去处理。

rd.forward() //转发,让其他组件去处理,自己不管了
rd.include(request,response) 包含.是让其他组件去处理,但是还会返回来,自己继续处理

!!Interface SingleThreadMode() //保证不会有多个线程执行service函数

解决并发访问的两种方法:

  • 1.加锁
  • 2.数据复制

事务的ACID

  • A:原子性
  • C:一致性
  • I:隔离性
  • D:持久性

**request.getContextPath(): ** 可以获取所配置的ServletContext路径

**例:**http://localhost:8080/dmsd-itoo-exam-log-web/course/index.jsp,在tomcat中配置了application context为 /dmsd-itoo-exam-log-web
request.getContextPath(),得到context路径:/dmsd-itoo-exam-log-web (取决于contextpath的配置);
request.getServletPath(),返回当前请求的资源相对于context的路径:/course/index.jsp;
request.getRequestURL(),返回请求资源的完整地址:http://localhost:8080/dmsd-itoo-exam-log-web/course/index.jsp;
request.getRequestURI() ,返回包含Context路径的资源路径:/dmsd-itoo-exam-log-web/course/index.jsp。

###Filter

doFilter(ServletRequest request, ServletResponse response, FilterChain chain)


  import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public mFliter implements Fliter{
   private FliterConfig config;
   public void destroy(){
   }
   public void doFliter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException,IoException{
       chain.doFilter(req,res);  //当前过滤器处理结束,往下一个过滤器
       //多个过滤器会形成一个过滤器链,如果不想拦截下该请求的话,应该让Filter往下传,后面没有filter后就到达资源
	//想拦截的话可以什么都不干,也可以直接跳到另一个地方(用redirect,forwer之类的
   }
}
//Filter通常要做的事情:
//Filter最最最早执行。
//在资源到达后端之前就执行了。  也就是拦截器
//数据写在session里
//常见作用:1.认证 不拦截/login.html 2.日志 3.数据转换 4.数据压缩 5.加密 6

访问计时: 应该加在filter
getServletContext().log(“xxxxxxxxxxxx”);

乱码解决 (Filter不仅可以用来拦截不合法的请求,还可以用来编码转换)

request.setCharcterEncoding("UTF-8"); //可以用filter实现
String wd=new String(wd.getBytes("ISO-8859-1"),"UTF-8");



public class EncodingFilter(){
     public void doFilter(...){
         request.setCharacterEncoding("UTF-8");
         chain.doiFliter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值