- 前言:
在遨游了一番 Java Web 的世界以后,发现了本身的一些缺失,因此就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大部份内容参照自这一篇文章,有一些本身补充的,也算是从新学习一下 Java 吧。javascript
前序文章连接:html
Java 面试知识点解析(六)——数据库篇spring
不涉及任何框架,对 J2EE 相关知识点的解析sql
在 Web 容器中,Servlet 主要经历 4 个阶段,以下图:数据库
1. 加载 Servlet:当 Tomcat 第一次访问 Servlet 的时候,Tomcat 会负责建立 Servlet 的实例。
2. 初始化 Servlet:当 Servlet 被实例化以后,Tomcat 会调用 init() 方法来初始化这个对象。
3. 处理服务:当浏览器访问 Servlet 的时候,Servlet 会调用 service() 方法处理请求。
4. 销毁:当 Tomcat 关闭或者检测到 Servlet 要从 Tomcat 删除的时候,会自动调用 destroy() 方法,让该实例所占用的资源释放掉。一个 Servlet 若是长时间不被使用的话,也会被 Tomcat 自动销毁。
浏览器发出请求: http://localhost:80/xxx1/xxx2
(80端口能够默认不写,由于这是http协议默认的端口,平时咱们访问https://www.baidu.com/
时其实访问的是https://www.baidu.com:80/
)
服务器解析请求信息:
解析 Tomcat 服务器根目录下的 /config/server.xml 文件:
<Context docBase="D:\javaPros\test\webapp" path="xxx1" />
判断哪个<Context />
元素的 path属性 属性为 xxx1
<Context />
元素,获得docBase
属性,获取当前访问 Web 项目的跟的绝对路径:D:\javaPros\test\webapp
从D:\javaPros\test\webapp
下的 WEB-INF 下找到 web.xml 文件
判断 web.xml 文件中是否有 <url-pattern>
的文本内容为 /xxx2
判断 Servlet 实例缓存池 中是否有 xxx.xxx 的对象
Map<String,Servlet> cache = ......(Tomcat提供的);
key:存Servlet类的全限定名称
value:该Servlet类的对象.
Servlet obj = cache.get("xxx.xxx"); if(obj==null){ //Servlet实例缓存中没有该类的对象,第一次. GOTO 6: }else{ //有对象,非第一次. GOTO 8: } }
使用反射调用构造器,建立对应的对象
obj = Class.forName("xxx.xxx").newInstance();
把当前建立的 Servlet 对象,存放在缓存之中,供给下一次的使用.
cache.put("xxx.xxx",obj);
建立 ServletConfig 对象,并调用 init() 方法
obj.init(config);
建立 ServletRequest 对象和 ServletResponse 对象,并调用 service()方法
obj.service(req,resp);
在 service() 方法中对浏览器做出响应操做。
Servlet 是单例的,浏览器屡次对Servlet的请求,通常状况下,服务器只建立一个Servlet对象,也就是说,Servlet对象一旦建立了,就会驻留在内存中,为后续的请求作服务,直到服务器关闭。
要知道,GET 和 POST 都是请求方式
浏览器器地址栏:http://localhost/test.html?name=wmyskxz&sex=male
这里提交了两个参数,一个是name
属性值为wmyskxz
,另外一个是sex
属性值为male
,这是一种直接的请求方式,在请求资源后面跟上 ? 符号与参数链接,其余的参数使用 & 符号链接。
浏览器地址栏:http://localhost/test.html#
在 Tomcat 服务器中,接受请求的时候,默认的编码方式为 ISO-8859-1,而该编码方式只占一个字节,不支持中文(两个字节),因此当咱们作请求的时候,会出现乱码的问题
解决方案:
1.对乱码使用 ISO-8859-1 解码,转换成byte数组,恢复为二进制
byte[] data = name.getBytes("ISO-8859-1");
2.对byte数组从新进行 UTF-8 编码:
name = new String(data,"UTF-8");
可是这样会出现一个问题,那就是当表单数据太多的时候,这样反复解码-编码,会很繁琐。
终极解决方案:
1.对于 POST 请求:
设置请求的编码方式:request.setCharacterEncoding("UTF-8");
注意:必须在获取第一个参数以前设置,而且该方式只对 POST 方式有效。
2.对于 GET 请求:
从新设置 Tomcat 的编码方式,修改 Tomcat 的配置文件:
Tomcat根目录/conf/server.xml(修改端口的那一行)
又叫作直接转发方式,客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每一个信息资源是共享的。
好比:从 AServlet 请求转发到 BServlet
request.getRequestDispatcher(path).forward(request, response);
参数: path
,要跳转到的资源路径:上下文路径 / 资源路径
特色:
1.地址栏中的地址【不会】改变,一般看做是服务端的跳转
2.只有一个请求
3.资源是共享的
也就是说在两个 Servlet 中能够共享请求的资源,能够经过request.setAttribute(String var1,Object var2)
设置要共享的数据资源,并经过request.getAttribute(String var1);
来获取传递的资源
4.【能够】访问 WEB-INF 中的资源
WEB-INF 文件夹是 Java Web 应用的默认安全目录,即客户端没法直接访问,只有服务端能够访问的目录。若是想在页面中直接访问其中的文件,必须经过web.xml文件对要访问的文件进行相应映射才能访问。
注意:在实际的开发中,能够把不但愿用户直接访问到(经过浏览器输入地址栏)的网页放在文件夹中经过此方式访问。
5.请求转发【不能】跨域访问
所谓的同域,是指域名,协议,端口均相同
又叫作间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另一个URL发出请求,从而达到转发的目的。
好比:从AServlet重定向到BServlet
response.sendRedirect(String location);
参数:location
,转发到的资源路径
特色:
1.地址栏中的地址【会】发生改变,一般看做是客户端跳转
2.有两个请求
3.在两个 Servlet 中不能够共享请求中的数据
4.最终的响应由 BServlet 来决定,和 AServlet 没有关系
5.【不能够】访问 WEB-INF 中的资源
6.请求转发【能】跨域访问
就像是在网页中点开了新的连接同样
当访问一个 JSP 页面时,该页面请求将会讲给服务器中的 JSP 引擎去处理,它负责解释和执行 JSP 页面,每一个 JSP 页面在第一次被访问时,JSP 引擎就会将它翻译成一个继承自 org.apache.jasper.runtime.HttpJspBase
类的 Servlet 源程序,接着再编译成 class 类文件,再由 Web 容器像调用普通 Servlet 程序同样的方式来装载和解释执行这个由 JSP 页面翻译成的 Servlet 程序。
request.getParameter() 一般用来接收接收表单的get或者post提交过来的参数;而request.getAttribute()通常和setAttribute()搭配使用,只有先set以后才能经过get方法获取到Object类型的数据
getAttribute 返回的是对象,而getParameter 返回的是字符串
getAttribute 和 setAttribute 只是在 web 容器内流转,仅仅是请求处理阶段;而 getParameter 取到的数据是经过容器来获取的。
<%@include file="被包含的页面的路径"%>
包含的时机:在 JSP 文件被翻译的时候合并在一块儿,最终翻译获得一个 class文件
<jsp:include page="被包含页面的路径"></jsp:include>
包含的时机:在运行阶段合并代码,最终获得两个 class 文件
JSP 共有如下 9 个内置的对象:
JSTL(JSP StandardTagLibrary,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,由四个定制标记库(core、format、xml和sql)和一对通用标记库验证器(ScriptFreeTLV和PermittedTaglibsTLV)组成。优势有:
在应用程序服务器之间提供了一致的接口,最大程序地提升了WEB应用在各应用服务器之间的移植。
简化了JSP和WEB应用程序的开发。
以一种统一的方式减小了JSP中的scriptlet代码数量,能够达到没有任何scriptlet代码的程序。在咱们公司的项目中是不容许有任何的scriptlet代码出如今JSP中。
容许JSP设计工具与WEB应用程序开发的进一步集成。相信不久就会有支持JSTL的IDE开发工具出现。
Cookie 是一种会话技术,用于将用户的信息保存在客户端上。Cookie 英文直接翻译过来就是小甜品,Cookie 的做用呢,通俗的说就是当一个用户经过 HTTP 访问一个服务器时,这个服务器会将一些 Key/Value 键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问这个服务器时,数据又被完整地带回给服务器。
这个做用就像是你去超市购物时,第一次给你办了一张购物卡,在这个购物卡里存放了一些你的我的信息,下次你再来这个超市的时候,你就只须要带上你的购物卡,直接购物就行了。
Session:会话,从浏览器打开开始,直到浏览器关闭结束,不管在这个网站中访问了多少页面,点击了多少连接,都属于同一个会话。Session 也能够称为会话 Cookie
总结: 将登陆信息等重要信息存放为 Session;其余信息若是须要保留,能够存放在 Cookie 中。
过滤器就是 Servlet 的高级特性之一,就是一个具备拦截/过滤功能的一个东西,在生活中过滤器能够是香烟滤嘴,滤纸,净水器,空气净化器等,在 Web 中仅仅是一个实现了 Filter 接口的 Java 类而已。
举一个实际的例子:(处理 POST 请求中文编码的问题)
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller):
在JSP/Servlet开发的软件系统中,这三个部分的描述以下所示:
1.Web浏览器发送HTTP请求到服务端,被Controller(Servlet)获取并进行处理(例如参数解析、请求转发)
2.Controller(Servlet)调用核心业务逻辑——Model部分,得到结果
3.Controller(Servlet)将逻辑处理结果交给View(JSP),动态输出HTML内容
4.动态生成的HTML内容返回到浏览器显示
MVC模式在Web开发中的好处是很是明显,它规避了JSP与Servlet各自的短板,Servlet只负责业务逻辑而不会经过out.append()动态生成HTML代码;JSP中也不会充斥着大量的业务代码。这大大提升了代码的可读性和可维护性。
因为我没有接触和学习过 Hibernate 和 Struts 这两个框架,因此细节方面的东西请读者自行收集...
框架是指完成必定功能的半成品。
框架可以帮助咱们完成的是:项目的总体框架、一些基础功能、规定了类和对象如何建立,如何协做等,当咱们开发一个项目时,框架帮助咱们完成了一部分功能,咱们本身再完成一部分,那这个项目就完成了。
Spring 是一个轻量级的 DI / IoC 和 AOP 容器的开源框架,来源于 Rod Johnson 在其著做《Expert one on one J2EE design and development》中阐述的部分理念和原型衍生而来。
Spring 提倡以 “最少侵入” 的方式来管理应用中的代码,这意味着咱们能够随时安装或者卸载 Spring
从框架的角度能够理解为:无需继承框架提供的任何类
这样咱们在更换框架时,以前写过的代码几乎能够继续使用。
IoC:Inverse of Control(控制反转),读做 “反转控制”,更好理解,不是什么技术,而是一种设计思想,就是将本来在程序中手动建立对象的控制权,交由Spring框架来管理。
为了便于理解咱们这里举一个鲜明的例子:
在现实生活中,人们要用到同样东西的时候,第一反应就是去找到这件东西,好比想喝新鲜橙汁,在没有饮品店的日子里,最直观的作法就是:买果汁机、买橙子,而后准备开水。值得注意的是:这些都是你本身“主动”创造的过程,也就是说一杯橙汁须要你本身创造。
然而到了今时今日,因为饮品店的盛行,当咱们想喝橙汁时,第一想法就转换成了找到饮品店的联系方式,经过电话等渠道描述你的须要、地址、联系方式等,下订单等待,过一下子就会有人送来橙汁了。
请注意你并无“主动”去创造橙汁,橙汁是由饮品店创造的,而不是你,然而也彻底达到了你的要求,甚至比你创造的要好上那么一些。
指 Spring 建立对象的过程当中,将对象依赖属性(简单值,集合,对象)经过配置设值给该对象
IoC 和 DI 实际上是同一个概念的不一样角度描述,DI 相对 IoC 而言,明确描述了 “被注入对象依赖 IoC 容器配置依赖对象”。
你也能够简单的理解为:IoC 是目的,是一种思想,而 DI 是手段,是一种设计模式。
1.BeanFactory:
是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,建立和管理bean。在应用中,通常不使用 BeanFactory,而推荐使ApplicationContext(应用上下文),缘由以下。
2.ApplicationContext:
⑴. 继承了 BeanFactory,拥有了基本的 IoC 功能;
⑵. 除此以外,ApplicationContext 还提供了如下功能:
① 支持国际化;② 支持消息机制;③ 支持统一的资源加载;④ 支持AOP功能;
最后咱们简单说说IoC是如何实现的。想象一下若是咱们本身来实现这个依赖注入的功能,咱们怎么来作? 无外乎:
咱们发现其实本身来实现也不是很难,Spring实际也就是这么作的。这么看的话其实IoC就是一个工厂模式的升级版!固然要作一个成熟的IoC框架,仍是很是多细致的工做要作,Spring不只提供了一个已经成为业界标准的Java IoC框架,还提供了更多强大的功能,因此你们就别去造轮子啦!但愿了解IoC更多实现细节不妨经过学习Spring的源码来加深理解!
引用地址:这里
在 Spring 中提供了 3 种方法进行配置:
在现实的工做中,这 3 种方式都会被用到,而且在学习和工做之中经常混合使用,因此这里给出一些关于这 3 种优先级的建议:
1.最优先:经过隐式 Bean 的发现机制和自动装配的原则。
基于约定因为配置的原则,这种方式应该是最优先的
2.其次:Java 接口和类中配置实现配置
在没有办法使用自动装配原则的状况下应该优先考虑此类方法
3.最后:XML 方式配置
在上述方法都没法使用的状况下,那么也只能选择 XML 配置的方式。
AOP 即 Aspect Oriented Program 面向切面编程
首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。
周边功能在 Spring 的面向切面编程AOP思想里,即被定义为切面
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发,而后把切面功能和核心业务功能 "编织" 在一块儿,这就叫 AOP
仍是来举一个鲜明的例子:
在上面的例子中,包租婆的核心业务就是签合同,收房租,那么这就够了,灰色框起来的部分都是重复且边缘的事,交给中介商就行了,这就是 AOP 的一个思想:让关注点代码与业务代码分离!
在默认的状况下,Spring IoC 容器只会对一个 Bean 建立一个实例,但有时候,咱们但愿可以经过 Spring IoC 容器获取多个实例,咱们能够经过 @Scope
注解或者 <bean>
元素中的 scope
属性来设置,例如:
// XML 中设置做用域 <bean id="" class="" scope="prototype" /> // 使用注解设置做用域 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Spring 提供了 5 种做用域,它会根据状况来决定是否生成新的对象:
做用域类别 | 描述 |
---|---|
singleton(单例) | 在Spring IoC容器中仅存在一个Bean实例 (默认的scope) |
prototype(多例) | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,至关于执行new XxxBean():不会在容器启动时建立对象 |
request(请求) | 用于web开发,将Bean放入request范围 ,request.setAttribute("xxx") , 在同一个request 得到同一个Bean |
session(会话) | 用于web开发,将Bean 放入Session范围,在同一个Session 得到同一个Bean |
globalSession(全局会话) | 通常用于 Porlet 应用环境 , 分布式系统存在全局 session 概念(单点登陆),若是不是 porlet 环境,globalSession 等同于 Session |
在开发中主要使用 scope="singleton"
、scope="prototype"
,对于MVC中的Action使用prototype类型,其余使用singleton,Spring容器会管理 Action 对象的建立,此时把 Action 的做用域设置为 prototype.
扩展阅读:@Profile 注解 、 条件化装配 Bean
更多戳这里:Spring面试问答Top 25
每当用户在 Web 浏览器中点击连接或者提交表单的时候,请求就开始工做了,像是邮递员同样,从离开浏览器开始到获取响应返回,它会经历不少站点,在每个站点都会留下一些信息同时也会带上其余信息,下图为 Spring MVC 的请求流程:
从请求离开浏览器之后,第一站到达的就是 DispatcherServlet,看名字这是一个 Servlet,经过 J2EE 的学习,咱们知道 Servlet 能够拦截并处理 HTTP 请求,DispatcherServlet 会拦截全部的请求,而且将这些请求发送给 Spring MVC 控制器。
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <!-- 拦截全部的请求 --> <url-pattern>/</url-pattern> </servlet-mapping>
因此 DispatcherServlet 会查询一个或多个处理器映射来肯定请求的下一站在哪里,处理器映射会根据请求所携带的 URL 信息来进行决策,例如上面的例子中,咱们经过配置 simpleUrlHandlerMapping 来将 /hello 地址交给 helloController 处理:
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <!-- /hello 路径的请求交给 id 为 helloController 的控制器处理--> <prop key="/hello">helloController</prop> </props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean>
一旦选择了合适的控制器, DispatcherServlet 会将请求发送给选中的控制器,到了控制器,请求会卸下其负载(用户提交的请求)等待控制器处理完这些信息:
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { // 处理逻辑 .... }
当控制器在完成逻辑处理后,一般会产生一些信息,这些信息就是须要返回给用户并在浏览器上显示的信息,它们被称为模型(Model)。仅仅返回原始的信息时不够的——这些信息须要以用户友好的方式进行格式化,通常会是 HTML,因此,信息须要发送给一个视图(view),一般会是 JSP。
控制器所作的最后一件事就是将模型数据打包,而且表示出用于渲染输出的视图名(逻辑视图名)。它接下来会将请求连同模型和视图名发送回 DispatcherServlet。
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { // 处理逻辑 .... // 返回给 DispatcherServlet return mav; }
这样以来,控制器就不会和特定的视图相耦合,传递给 DispatcherServlet 的视图名并不直接表示某个特定的 JSP。(实际上,它甚至不能肯定视图就是 JSP)相反,它传递的仅仅是一个逻辑名称,这个名称将会用来查找产生结果的真正视图。
DispatcherServlet 将会使用视图解析器(view resolver)来将逻辑视图名匹配为一个特定的视图实现,它多是也可能不是 JSP
上面的例子是直接绑定到了 index.jsp 视图
既然 DispatcherServlet 已经知道由哪一个视图渲染结果了,那请求的任务基本上也就完成了。
它的最后一站是视图的实现,在这里它交付模型数据,请求的任务也就完成了。视图使用模型数据渲染出结果,这个输出结果会经过响应对象传递给客户端。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> <h1>${message}</h1>
更多 Spring-MVC 内容:Spring MVC【入门】就这一篇
对象关系映射(Object-Relational Mapping,简称ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;
简单的说,ORM是经过使用描述对象和数据库之间映射的元数据(在Java中能够用XML或者是注解),将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另一种形式。
在咱们传统的 JDBC 中,咱们除了须要本身提供 SQL 外,还必须操做 Connection、Statment、ResultSet,不只如此,为了访问不一样的表,不一样字段的数据,咱们须要些不少雷同模板化的代码,闲的繁琐又枯燥。
而咱们在使用了 MyBatis 以后,只须要提供 SQL 语句就行了,其他的诸如:创建链接、操做 Statment、ResultSet,处理 JDBC 相关异常等等均可以交给 MyBatis 去处理,咱们的关注点因而能够就此集中在 SQL 语句上,关注在增删改查这些操做层面上。
而且 MyBatis 支持使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
#
和 $
的区别区别以下:
#
符号将传入的数据都当作一个字符串,会对自动传入的数据加一个双引号$
符号将传入的数据直接显示生成SQL中。#
符号存在预编译的过程,,对问号赋值,防止SQL注入。$
符号是直译的方式,通常用在orderby {列名} 语句中。#
号就不要用$
符号在 Web 系统中,最重要的操做就是查询数据库中的数据。可是有些时候查询数据的频率很是高,这是很耗费数据库资源的,每每会致使数据库查询效率极低,影响客户的操做体验。因而咱们能够将一些变更不大且访问频率高的数据,放置在一个缓存容器中,用户下一次查询时就从缓存容器中获取结果。
更多深刻MyBatis的内容戳这里:MyBatis(2)——MyBatis 深刻学习
在早期 Java Web 的开发中,统一把显示层、控制层、数据层的操做所有交给 JSP 或者 JavaBean 来进行处理,咱们称之为 Model1:
正由于上面的种种弊端,因此很快这种方式就被 Servlet + JSP + Java Bean 所替代了,早期的 MVC 模型(Model2)就像下图这样:
首先用户的请求会到达 Servlet,而后根据请求调用相应的 Java Bean,并把全部的显示结果交给 JSP 去完成,这样的模式咱们就称为 MVC 模式。
扩展阅读:Web开发模式
为解决持久层中一直未处理好的数据库事务的编程,又为了迎合 NoSQL 的强势崛起,Spring MVC 给出了方案:
传统的模型层被拆分为了业务层(Service)和数据访问层(DAO,Data Access Object)。在 Service 下能够经过 Spring 的声明式事务操做数据访问层,而在业务层上还容许咱们访问 NoSQL ,这样就可以知足异军突起的 NoSQL 的使用了,它能够大大提升互联网系统的性能。
回顾咱们以前的 SSM 项目,搭建过程仍是比较繁琐的,须要:
而使用 Spring Boot 来开发项目则只须要很是少的几个配置就能够搭建起来一个 Web 项目,而且利用 IDEA 能够自动生成生成,这简直是太爽了...
Spring Boot 因为笔者尚未深刻学习..因此细节部分请读者自行收集...
欢迎转载,转载请注明出处!转载自@我没有三颗心脏