【面试】JavaEE基础
参考:https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/J2EE基础知识.md
1、Servlet
参考:https://www.cnblogs.com/Rain1203/p/10919557.html
2、get和post请求的区别?
1)get请求用来从服务器上获取资源,post是用来向服务器提交数据的;
2)get将表单中数据按照name=value的形式,添加到action所指向的URL后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向的URL;
3)get传输的数据要受到URL长度的限制(最大2048个字符),而post可以传输大量的数据,上传文件通常使用post方式;
4)使用get请求参数会显示在地址栏上,非敏感数据可以使用get方式,敏感数据应该使用post;
5)get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是“%20”。
补充:get方式表单的典型应用是搜索引擎,get方式就是被设计为查询用的。
3、转发(Forward)和重定向(Redirect)的区别?
转发是服务器的行为,重定向是客户端的行为。
转发(Forward)通过RequestDispatcher对象的forward(HttpServletRequest request,HttpServletResponse response)方法实现的。
RequestDispatcher可以通过HttpServletRequest的getRequestDispatcher()方法获得。
request.getRequestDispatcher("login_success.jsp").forward(request,response);
重定向(Redirect)是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过HttpServletResponse 的 setStatus(int status)方法设置状态码,如果服务器返回301或者302,则浏览器会跳转到新的网址重新获取资源。
1)从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标URL把资源读取过来,返回给浏览器,浏览器并不知道服务器发送的资源从何而来,所以地址栏是不变的;
redirect是服务器根据逻辑,发送一个状态码,告诉浏览器去请求那个地址,所以地址栏显示的是新的URL;
2)从数据共享来说
forward转发页面和转发到的页面可以共享request里面的数据;
redirect不能共享数据;
3)从运用地方来说
forward一般用于用户登录的时候,根据角色转发到相应模块;
redirect一般用于用户注销登录时返回主页或跳转到其他网站等;
4)从效率来说
forward高;redirect低。
4、Servlet与线程安全?
Servlet不是线程安全的,多线程并发的读写会导致数据不同步的问题。解决的办法是尽量不要定义name属性,而是要把name变量分别定义在doGet()和doPost()方法内。虽然是以synchronized(name){} 语句块可以解决问题,但是会造成线程的等待,不是很科学的办法。注意,多线程的并发读写Servlet类属性会导致数据不同步。但是如果只是并发的读取属性而不写入,则不存在数据不同步的问题。因此,Servlet里的只读属性最好定义为final。
5、JSP中的四种作用域?
1)page代表与一个页面相关的对象和属性;
2)request代表与web客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个web组件;需要在页面显示的临时数据可以置于此作用域;
3)session代表某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中;
4)application代表与整个web应用程序相关的对象和属性,它实质上是跨越整个web应用程序,包括多个页面,请求和会话的一个全局作用域。
6、如何实现JSP或Servlet的单线程模式?
对于JSP页面,可以通过page指令进行设置。<%@page isThreadSafe="false'%>;
对于Servlet,可以让自定义的Servlet实现SingleThreadModel 标识接口;
说明:如果将JSP或Servlet设置成单线程工作模式,会导致每个请求创建一个Servlet实例,这种将导致严重的性能问题(服务器的内存压力很大,还会导致频繁的垃圾回收),所以通常情况下我们不会这么做。
7、实时会话跟踪的技术有哪些?
1)使用Cookie
向客户端发送Cookie
Cookie c =new Cookie("name","value"); //创建Cookie
c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天
response.addCookie(c); //把Cookie放入到HTTP响应中
从客户端读取Cookie
String name ="name";
Cookie[]cookies =request.getCookies();
if(cookies !=null){
for(int i= 0;i<cookies.length;i++){
Cookie cookie =cookies[i];
if(name.equals(cookis.getName()))
//something is here.
//you can get the value
cookie.getValue();
}
}
优点:数据可以持久保存,不需要服务器资源,简单,基于文本的key-Value;
缺点:大小受到限制,用户可以禁用Cookie功能,有一定的安全风险。
2)URL重写
在URL中添加用户会话的信息作为请求参数,或者将唯一的会话ID添加到URL结尾以标识成一个会话;
优点:在Cookie被禁用时仍然可以使用;
缺点:必须对网站的URL进行编码,所有页面必须动态生成,不能用预先记录下来的URL进行访问;
3)隐藏的表单域
<input type="hidden" name ="session" value="..."/>
优点:Cookie被禁用时可以使用;
缺点:所有页面必须是表单提交之后的结果。
4)HttpSession
在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问它自己的HttpSession。可以通过HttpServletRequest对象的getSession()方法获取HttpSession,通过HttpSession的setAttribute方法可以将一个值放到HttpSession中,通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。
与上面三种方式不同的是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession中的对象移到其他存储设备中,但这势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时容易出现异常。
8、Cookie和Session的区别?
Cookie和Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie一般用来保护用户信息,比如(1)我们在Cookie保存已经登录过的用户信息,下次访问网站的时候可以帮你把登录的信息给填了;
(2)一般的网站都会有保持登录,也就是说你下次再访问网站就不需要重新登录了,这是因为用户登录的时候我们存放了一个Token在Cookie中,下次登录的时候只需要根据Token值来查找用户即可(为了安全考虑,重新登录一般要将Token重写);
(3)登录一次网站后访问网站其他页面不需要重新登录。
Session的主要作用就是通过服务端记录用户状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为HTTP协议是无状态的。服务端给特定的用户创建特定的Session之后,就可以标识这个用户并且跟踪这个用户了。
Cookie数据保存在客户端(浏览器),Session保存在服务器端;
Session安全性更高,如果使用Cookie的一些敏感信息不要直接写入到Cookie中,最好能将Cookie信息加密,然后使用到的时候再去服务器端解密。