|
| 1 | +##Servlet总结 |
| 2 | + |
| 3 | +在Java Web程序中,**Servlet**主要负责接收用户请求`HttpServletRequest`,在`doGet()`,`doPost()`中做相应的处理,并将回应`HttpServletResponse`反馈给用户。**Servlet** 可以设置初始化参数,供Servlet内部使用。一个Servlet类只会有一个实例,在它初始化时调用`init()`方法,销毁时调用`destroy()`方法**。**Servlet需要在web.xml中配置(MyEclipse中创建Servlet会自动配置),**一个Servlet可以设置多个URL访问**。**Servlet不是线程安全**,因此要谨慎使用类变量。 |
| 4 | + |
| 5 | +##Servlet接口中有哪些方法及Servlet生命周期 |
| 6 | + |
| 7 | +Servlet接口定义了5个方法,其中**前三个方法与Servlet生命周期相关**: |
| 8 | + |
| 9 | +-`void init(ServletConfig config) throws ServletException` |
| 10 | +-`void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException` |
| 11 | +-`void destroy()` |
| 12 | +-`java.lang.String getServletInfo()` |
| 13 | +-`ServletConfig getServletConfig()` |
| 14 | + |
| 15 | +**生命周期:****Web容器加载Servlet并将其实例化后,Servlet生命周期开始**,容器运行其**init()方法**进行Servlet的初始化;请求到达时调用Servlet的**service()方法**,service()方法会根据需要调用与请求对应的**doGet或doPost**等方法;当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的**destroy()方法**。**init方法和destroy方法只会执行一次,service方法客户端每次请求Servlet都会执行**。Servlet中有时会用到一些需要初始化与销毁的资源,因此可以把初始化资源的代码放入init方法中,销毁资源的代码放入destroy方法中,这样就不需要每次处理客户端的请求都要初始化与销毁资源。 |
| 16 | + |
| 17 | +参考:《javaweb整合开发王者归来》P81 |
| 18 | + |
| 19 | +##get和post请求的区别 |
| 20 | + |
| 21 | +可以把 get 和 post 当作两个不同的行为,两者并没有什么本质区别,底层都是 TCP 连接。 get请求用来从服务器上获得资源,而post是用来向服务器提交数据。比如你要获取人员列表可以用 get 请求,你需要创建一个人员可以用 post 。这也是 Restful API 最基本的一个要求。 |
| 22 | + |
| 23 | +##转发(Forward)和重定向(Redirect)的区别 |
| 24 | + |
| 25 | +**转发是服务器行为,重定向是客户端行为。** |
| 26 | + |
| 27 | +**转发(Forward)** 通过RequestDispatcher对象的forward(HttpServletRequest request,HttpServletResponse response)方法实现的。RequestDispatcher可以通过HttpServletRequest 的getRequestDispatcher()方法获得。例如下面的代码就是跳转到login_success.jsp页面。 |
| 28 | + |
| 29 | +```java |
| 30 | + request.getRequestDispatcher("login_success.jsp").forward(request, response);Copy to clipboardErrorCopied |
| 31 | +``` |
| 32 | + |
| 33 | +**重定向(Redirect)** 是利用服务器返回的状态码来实现的。客户端浏览器请求服务器的时候,服务器会返回一个状态码。服务器通过`HttpServletResponse` 的`setStatus(int status)` 方法设置状态码。如果服务器返回301或者302,则浏览器会到新的网址重新请求该资源。 |
| 34 | + |
| 35 | +1.**从地址栏显示来说** |
| 36 | + |
| 37 | +forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址. redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL. |
| 38 | + |
| 39 | +1.**从数据共享来说** |
| 40 | + |
| 41 | +forward:转发页面和转发到的页面可以共享request里面的数据. redirect:不能共享数据. |
| 42 | + |
| 43 | +1.**从运用地方来说** |
| 44 | + |
| 45 | +forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等 |
| 46 | + |
| 47 | +1. 从效率来说 |
| 48 | + |
| 49 | +forward:高. redirect:低. |
| 50 | + |
| 51 | +##Servlet与线程安全 |
| 52 | + |
| 53 | +**Servlet不是线程安全的,多线程并发的读写会导致数据不同步的问题。** 解决的办法是尽量不要定义name属性,而是要把name变量分别定义在doGet()和doPost()方法内。虽然使用synchronized(name){}语句块可以解决问题,但是会造成线程的等待,不是很科学的办法。 注意:多线程的并发的读写Servlet类属性会导致数据不同步。但是如果只是并发地读取属性而不写入,则不存在数据不同步的问题。因此Servlet里的只读属性最好定义为final类型的。 |
| 54 | + |
| 55 | +参考:《javaweb整合开发王者归来》P92 |
| 56 | + |
| 57 | +##JSP有哪些内置对象、作用分别是什么 |
| 58 | + |
| 59 | +JSP有9个内置对象: |
| 60 | + |
| 61 | +- request:封装客户端的请求,其中包含来自GET或POST请求的参数; |
| 62 | +- response:封装服务器对客户端的响应; |
| 63 | +- pageContext:通过该对象可以获取其他对象; |
| 64 | +- session:封装用户会话的对象; |
| 65 | +- application:封装服务器运行环境的对象; |
| 66 | +- out:输出服务器响应的输出流对象; |
| 67 | +- config:Web应用的配置对象; |
| 68 | +- page:JSP页面本身(相当于Java程序中的this); |
| 69 | +- exception:封装页面抛出异常的对象。 |
| 70 | + |
| 71 | +##Request对象的主要方法有哪些 |
| 72 | + |
| 73 | +- setAttribute(String name,Object):设置名字为name的request 的参数值 |
| 74 | +- getAttribute(String name):返回由name指定的属性值 |
| 75 | +- getAttributeNames():返回request 对象所有属性的名字集合,结果是一个枚举的实例 |
| 76 | +- getCookies():返回客户端的所有 Cookie 对象,结果是一个Cookie 数组 |
| 77 | +- getCharacterEncoding() :返回请求中的字符编码方式 = getContentLength() :返回请求的 Body的长度 |
| 78 | +- getHeader(String name) :获得HTTP协议定义的文件头信息 |
| 79 | +- getHeaders(String name) :返回指定名字的request Header 的所有值,结果是一个枚举的实例 |
| 80 | +- getHeaderNames() :返回所以request Header 的名字,结果是一个枚举的实例 |
| 81 | +- getInputStream() :返回请求的输入流,用于获得请求中的数据 |
| 82 | +- getMethod() :获得客户端向服务器端传送数据的方法 |
| 83 | +- getParameter(String name) :获得客户端传送给服务器端的有 name指定的参数值 |
| 84 | +- getParameterNames() :获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例 |
| 85 | +- getParameterValues(String name):获得有name指定的参数的所有值 |
| 86 | +- getProtocol():获取客户端向服务器端传送数据所依据的协议名称 |
| 87 | +- getQueryString() :获得查询字符串 |
| 88 | +- getRequestURI() :获取发出请求字符串的客户端地址 |
| 89 | +- getRemoteAddr():获取客户端的 IP 地址 |
| 90 | +- getRemoteHost() :获取客户端的名字 |
| 91 | +- getSession([Boolean create]) :返回和请求相关 Session |
| 92 | +- getServerName() :获取服务器的名字 |
| 93 | +- getServletPath():获取客户端所请求的脚本文件的路径 |
| 94 | +- getServerPort():获取服务器的端口号 |
| 95 | +- removeAttribute(String name):删除请求中的一个属性 |
| 96 | + |
| 97 | +##request.getAttribute()和 request.getParameter()有何区别 |
| 98 | + |
| 99 | +**从获取方向来看:** |
| 100 | + |
| 101 | +`getParameter()`是获取 POST/GET 传递的参数值; |
| 102 | + |
| 103 | +`getAttribute()`是获取对象容器中的数据值; |
| 104 | + |
| 105 | +**从用途来看:** |
| 106 | + |
| 107 | +`getParameter()`用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。 |
| 108 | + |
| 109 | +`getAttribute()` 用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了 mapping.findForward。 getAttribute 只能收到程序用 setAttribute 传过来的值。 |
| 110 | + |
| 111 | +另外,可以用`setAttribute()`,`getAttribute()` 发送接收对象.而`getParameter()` 显然只能传字符串。`setAttribute()` 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样`getAttribute()`就能取得你所设下的值,当然这种方法可以传对象。session也一样,只是对象在内存中的生命周期不一样而已。`getParameter()`只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。 |
| 112 | + |
| 113 | +**总结:** |
| 114 | + |
| 115 | +`getParameter()`返回的是String,用于读取提交的表单中的值;(获取之后会根据实际需要转换为自己需要的相应类型,比如整型,日期类型啊等等) |
| 116 | + |
| 117 | +`getAttribute()`返回的是Object,需进行转换,可用`setAttribute()`设置成任意对象,使用很灵活,可随时用 |
| 118 | + |
| 119 | +##讲解JSP中的四种作用域 |
| 120 | + |
| 121 | +JSP中的四种作用域包括page、request、session和application,具体来说: |
| 122 | + |
| 123 | +-**page**代表与一个页面相关的对象和属性。 |
| 124 | +-**request**代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。 |
| 125 | +-**session**代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。 |
| 126 | +-**application**代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。 |
| 127 | + |
| 128 | +##实现会话跟踪的技术有哪些 |
| 129 | + |
| 130 | +1.**使用Cookie** |
| 131 | + |
| 132 | +向客户端发送Cookie |
| 133 | + |
| 134 | +```java |
| 135 | +Cookie c=newCookie("name","value");//创建Cookie |
| 136 | +c.setMaxAge(60*60*24);//设置最大时效,此处设置的最大时效为一天 |
| 137 | +response.addCookie(c);//把Cookie放入到HTTP响应中Copy to clipboardErrorCopied |
| 138 | +``` |
| 139 | + |
| 140 | +从客户端读取Cookie |
| 141 | + |
| 142 | +```java |
| 143 | +String name="name"; |
| 144 | +Cookie[]cookies=request.getCookies(); |
| 145 | +if(cookies!=null){ |
| 146 | +for(int i=0;i<cookies.length;i++){ |
| 147 | +Cookie cookie=cookies[i]; |
| 148 | +if(name.equals(cookis.getName())) |
| 149 | +//something is here. |
| 150 | +//you can get the value |
| 151 | + cookie.getValue(); |
| 152 | + |
| 153 | + } |
| 154 | + } |
| 155 | +Copy to clipboardErrorCopied |
| 156 | +``` |
| 157 | + |
| 158 | +**优点:** 数据可以持久保存,不需要服务器资源,简单,基于文本的Key-Value |
| 159 | + |
| 160 | +**缺点:** 大小受到限制,用户可以禁用Cookie功能,由于保存在本地,有一定的安全风险。 |
| 161 | + |
| 162 | +1. URL 重写 |
| 163 | + |
| 164 | +在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。 |
| 165 | + |
| 166 | +**优点:** 在Cookie被禁用的时候依然可以使用 |
| 167 | + |
| 168 | +**缺点:** 必须对网站的URL进行编码,所有页面必须动态生成,不能用预先记录下来的URL进行访问。 |
| 169 | + |
| 170 | +3.隐藏的表单域 |
| 171 | + |
| 172 | +```html |
| 173 | +<inputtype="hidden"name ="session"value="..."/>Copy to clipboardErrorCopied |
| 174 | +``` |
| 175 | + |
| 176 | +**优点:** Cookie被禁时可以使用 |
| 177 | + |
| 178 | +**缺点:** 所有页面必须是表单提交之后的结果。 |
| 179 | + |
| 180 | +1. HttpSession |
| 181 | + |
| 182 | +在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方 法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用 HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的 是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession 中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了 Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。 |
| 183 | + |
| 184 | +##Cookie和Session的的区别 |
| 185 | + |
| 186 | +Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。 |
| 187 | + |
| 188 | +**Cookie 一般用来保存用户信息** 比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。**Session 的主要作用就是通过服务端记录用户的状态。** 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。 |
| 189 | + |
| 190 | +Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。 |
| 191 | + |
| 192 | +Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。 |