本博客java云同桌学习系列,旨在记录本人学习java的过程,并与大家分享,对于想学习java的同学,我希望这个系列能够鼓励大家一同与我学习java,成为“云同桌”。
每月预计保持更新数量三章起,每章都会从整体框架入手,介绍章节所涉及的重要知识点及相关练习题,并会设置推荐学习时间,每篇博客涉及到的点都会在开篇目录进行总览。(博客中所有高亮部分表示是面试题进阶考点)
学习时间:三周
学习建议:本章涉及到的内容较多,结合之前所学的JavaSE、前端、数据库的知识,就可以做出一个不错的web系统,学习本节内容时,建议大家经常回看之前每节的内容
1. 环境搭建
1.1 Tomcat
首先,我们需要回顾一个之前网络编程所讲的HTTP请求相关的内容:
java云同桌学习系列(十)——网络编程
那么首先,我们需要搭建一个服务器,我们选择Tomcat服务器
Tomcat:开源小型web服务器 ,完全免费,主要用于中小型web项目,只支持Servlet和JSP 等少量javaEE规范
下载地址:Tomcat8.5版本官方下载地址
使用方式:
1.将下载好的Tomcat解压到没有特殊符号的目录中
2.进入到解压的目录下找到bin\startup.bat双击启动即可,打开窗口即表示服务器开启,关闭窗口服务器关闭
3.建议:将Tomcat路径放到JAVA_HOME环境变量
检验是否配置成功:
输入域名:localhost:8080
访问某个项目文件:
url:http://服务器的ip地址:端口号/项目名/被访问的页面
需要知晓的一些小tips:
(1) 启动tomcat后,tomcat会加载部署在服务器端的所有项目
(2) 浏览器访问的页面是服务器端的页面,基本上服务器的项目和工作空间的项目要保持一致
1.2 Tomcat目录结构
-
bin目录:存放二进制可执行文件
-
conf目录:存放配置文件
- server.xml:配置整个服务器信息
- tomcat-users.xml:存储tomcat用户的文件
- web.xml:部署描述符文件
- context.xml:对所有应用的统一配置
-
lib目录:Tomcat的类库,所有目录均可共享其中的jar包
-
logs目录:存放日志文件,记录了Tomcat启动和关闭的信息
-
temp目录:存放Tomcat的临时文件
-
webapps目录:存放web项目的目录,其中每个文件夹都是一个项目
-
work目录:存放运行时生成的文件
1.3 IDEA配置Tomcat和建立Web项目
推荐这位博主的文章,很详细,并且所执行的步骤都是最新的(2020.11.20)
对于IDEA2020版本,有一个默认设置发生了变化,必须要小心,将其改成下图所示:
1.4 Tomcat管理项目
之前上面我们说过,Tomcat在启动后,会加载部署服务器端的所用项目,即webapps下的所有项目
但是,提供了相应的方法来管理这些项目,我们需要给tomcat增加管理员信息,配置conf/tomcat-users.xml,将下面的代码添加到<tomcat-users></tomcat-users>之间
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>
重启Tomcat服务器,然后打开Tomcat的初始页面,进入管理页面,输入在配置文件中的登陆名与密码
进入管理页面,输入在配置文件中的登陆名与密码,接下来就进入到了管理项目页面,可以通过每个项目的按钮进行管理
2. Java Servlet
Java Servlet
:指运行在 Web 服务器上的程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
Servlet 在 Web 应用程序中的位置
Servlet所负责的工作:
① 读取浏览器发送的显式或隐式的数据
② 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
③ 发送显示或隐式的数据到客户端
Servlet的原理:
1.Servlet接口就是定义了Servlet与Servlet容器的契约,在一个应用程序中,每种Servlet类型只能有一个实例。
2.Servlet的方法中,封装了一些对象,程序员可以直接使用这些对象。
Service()方法:ServletRequest对象和ServletResponse对象
doGet/doPost()方法:HttpServletRequest req, HttpServletResponse resp
2.1 创建Servlet的方式及生命周期
在建立之前,先将Tomcat的lib库导入,才能使用javax包中的内容IntelliJ IDEA 缺少javax包支持解决办法
方式一:实现Servlet接口及生命周期介绍
生命周期的步骤:
1.客户端首次发送第一次请求,由容器(web服务器(tomcat))去解析请求, 根据请求找到对应的servlet
2.判断该类的对象是否存在,不存在则创建servlet实例,调取init()方法进行初始化操作
3.初始化完成后调取service()方法,由service()判断客户端的请求方式,如果是get,则执行doGet(),如果是post则执行doPost().
4.处理方法完成后,作出相应结果给客户端.单次请求处理完毕。
5.当用户发送第二次以后的请求时,会判断对象是否存在,但是不再执行init()而直接执行service方法,调取doGet()/doPost()方法。
6.当服务器关闭时调取destroy()方法进行销毁。
public class Demo implements Servlet {
//一个Servlet只会有一个对象,服务所有的请求
//生命周期方法:当Servlet第一次被创建对象时执行该方法,该方法在整个生命周期中只执行一次
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//生命周期方法:对客户端响应的方法,该方法会被执行多次,每次请求该servlet都会执行该方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
//生命周期方法:当Servlet被销毁时执行该方法
@Override
public void destroy() {
}
}
方式二:继承 GenericServlet类
class Demo2 extends GenericServlet{
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
}
方式三:继承 HttpServlet类(常用)
class Demo3 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.2 Servlet部署
方式一:web.xml文件部署
容器(Tomcat)在得到客户端的请求后,但不知道去交给哪一个servlet去处理,所以需要进行部署,定义请求与对应serlet的映射关系
需要在/webapps/ROOT/WEB-INF/ 的 web.xml 文件中进行部署
<servlet>
<servlet-name>自定义名称</servlet-name>
<servlet-class>处理请求的类的完整路径</servlet-class>
</servlet>
<servlet-mapping><!-- mapping 表示映射 -->
<servlet-name>自定义名称</servlet-name>
<url-pattern>请求名</url-pattern>
</servlet-mapping>
方式二:@WebServlet注解部署(Servlet3.0后支持,推荐)
亦或是使用更为方便的注解来进行部署@WebServlet
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定Servlet 的 name 属性,默认为类的全限定名 |
value或者urlPatterns | String | 指定一个或一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签。 |
asyncSupported | boolean | 指定Servlet是否支持异步操作模式 |
displayName | String | 指定servlet的显示名 |
initParams | webInitParam[] | 配置初始化参数 |
loadOnStartup | int | 指定servlet的加载顺序 |
使用方式如下:
@WebServlet(
name = "DispatcherServlet",
//接收所用.do结尾的请求
urlPatterns = {"*.do"},
//加载顺序为0,项目服务器一启动就加载
loadOnStartup = 0,
//初始化配置参数:映射池配置文件
initParams =@WebInitParam(name="contentConfigLocation",value = "application.properties")
)
2.3 Servlet接收请求
- 前端向服务器发送请求
请求方式 | 请求类型 | 举例 |
---|---|---|
通过form表单 | get/post提交 | <form action=“请求”></form> |
通过a标签发送数据 | get提交 | <a href = “请求”></a> |
通过地址栏直接拼接 | get请求 | |
js提交数据 | get请求 | location.href=“目标请求?key=value&key=value” |
- get\post请求的异同
get请求 | post请求 |
---|---|
请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。 | POST请求会把请求的数据放置在HTTP请求包的包体中 |
特定的浏览器和服务器对URL的长度有限制,在使用GET请求时,传输数据会受到URL长度的限制。 | 对于POST,由于不是URL传值,理论上是不会受限制的 |
安全性低 | 安全性相对较高 |
- 处理请求乱码的问题
post请求 | get请求 |
---|---|
httpservlet.setCharacterEncoding(“UTF-8”); | tomacat 8.0默认设置字符集为utf-8 |
- Servlet处理前端请求
HttpServlet类是GenericServlet类的子类,是Servlet接口的实现类
所以接下来我们谈论的请求还是响应,都是HttpServlet的对象所拥有的方法。
HttpServletRequest类常用方法:
修饰 | 方法名 | 描述 |
---|---|---|
String | getParameter(String name) | 根据表单组件名称获取提交数据,返回值是String(服务器在接收数据时使用字符串统一接收) |
String[] | getParameterValues(String name) | 获取表单组件对应多个值时的请求数据 |
void | setCharacterEncoding(String charset) | 指定每个请求的编码(针对post请求才起作用) |
RequestDispatcher | getRequestDispatcher(String path) | 转发,返回一个RequestDispatcher对象,该对象的forward( )方法用于转发请求 |
Session | getSession() | 取得当前会话的Session对象 |
void | setAttribute(“key”,value) | 存值 |
void | getAttribute(“key”) | 取值,需要向下转型 |
2.4 Servlet响应请求
HttpServletResponse类常用方法:
修饰 | 方法名 | 描述 |
---|---|---|
void | addCookie(Cookie var1) | 给这个响应添加一个cookie |
void | sendRedirect(String var1) | 重定向,发送一条响应码,将浏览器跳转到指定的位置 |
PrintWriter | getWriter() | 获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端,可以返回一段js代码 |
void | setContentType() | 设置响应内容的类型 |
- 重定向与转发的区别
转发:httpServletRequest.getRequestDispatcher("目标地址").forward(传递参数)
重定向:httpServletResponse.sendRedirect("目标地址")
转发 | 重定向 |
---|---|
转发时地址栏显示的是请求页面的地址,request数据可以保存 | 重定向时地址栏显示的是目的页面的地址,request中存储的数据会丢失 |
转发属于一次请求一次响应 | 重定向属于两次请求(地址栏修改了两次)两次响应 |
2.5 Session
会话:从打开浏览器到关闭浏览器,期间访问服务器就称为一次会话
session会话的数据可以在多个页面中共享,即使重定向页面,数据不会丢失
取得Session对象:httpServletRequest.getSession()
Session常用方法:
修饰 | 方法名 | 描述 |
---|---|---|
void | setAttribute(String key,Object value) | 以key/value的形式保存对象值,将数据存储在服务器端 |
Object | getAttribute(String key) | 通过key获取对象值 |
void | invalidate() | 设置session对象失效 |
String | getId() | 获取sessionid,当第一次登录成功后,session会产生一个唯一的id,浏览器之后访时如果发现id值还是之前id,那么说明 当前访问的属于同一个会话 |
void | setMaxInactiveInterval(int interval) | 设定session的有效时间,单位为s秒,默认的有效时间:30分钟 |
int | getMaxInactiveInterval() | 获取session的有效时间(以秒为单位) |
void | removeAttribute(String key) | 从session中删除指定名称(key)所对应的对象 |
2.6 Cookie
首先,分清楚一点:
Cookie通过在客户端记录信息确定用户身份
Session通过在服务器端记录信息确定用户身份。
Cookie
:客户端(一般指浏览器)请求服务器后,服务器发给客户端的一个辨认标识,服务器可以通过这个标识来识别客户端的身份或状态等。
同样,Cookie也可以保存一些数据信息
Cookie cookie = new Cookie("jieguo","true");
response.addCookie(cookie);
Cookie有效时间可以自行设置(有效时间默认为一次浏览器打开到关闭的时间)
//setMaxAge用来设置Cookie的最大有效时间,需要int型的参数,代表有效的秒数
cookie.setMaxAge(秒数);
//当参数大于0时,会设置为指定的秒数
cookie.setMaxAge(30);
//当参数等于0时,浏览器不会保存Cookie,Cookie立即失效
cookie.setMaxAge(0);
//当参数小于0时,和不设置是一样,当前会话有效
cookie.setMaxAge(-100);
//设置一个永久有效的Cookie,并非永久,只是使Cookie的生命很长而已
cookie.setMaxAge(60*60*24*365*10);
并且如果想要更改或删除Cookie,只需要发送一个同名Cookie来替换原Cookie,想要删除的话,发送一个有效时间为0的Cookie即可
//1.创建一个name为username的Cookie
Cookie cookie = new Cookie("username", "aaa");
//2.设置Cookie的有效时间为0
cookie.setMaxAge(0);//删除cookie的关键
//3.将cookie发送给浏览器,来替换同名Cookie
response.addCookie(cookie);
3.JSP
JSP(Java Server Pages)
:跨平台的一种动态网页技术标准,在传统的网页HTML文件中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件
-
嵌套代码
声明标签: <%!变量或者方法声明%> 表达式标签: <%= 表达式%> 在页面上显示的效果 程序代码标签: <%java代码%> 页面上动态展示内容 <!-- html注释内容,查看源码时能看到 --> <%-- jsp注释,查看页面源码时看不到 --%>
-
JSP底层原理
jsp本质上也是Servlet
1.jsp文件被翻译成java文件并编译成class文件 2.HTML代码以流的方式被响应会浏览器显示
-
状态码
状态码 消息 描述 200 OK 请求被确认 202 Accepted 请求被接受,但未处理完 400 Bad Request 服务器无法识别请求 03 Forbidden 禁止访问所请求的页面 04 Not Found 服务器无法找到所请求的页面 05 Method Not Allowed 请求中所指定的方法不被允许 04 Gateway Timeout 网关超时
-
3.1 JSP内置对象
JSP中像Servlet一样,预先封装好了一些常用的Java对象,记得导入jsp-api的jar包,通常Tomcat文件夹lib下都会有
内置对象 | 描述 | 生命周期 |
---|---|---|
request | 代表了客户端的请求信息,可以传递一些临时数据 | 单次请求 |
response | 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端 | 只在JSP页面有效 |
session | 服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。内部使用键和值的方式存储 | 浏览器访问期间 |
application | 对象可将信息保存在服务器中,直到服务器关闭,application对象中保存的信息会在整个应用中都有效 | 服务器启动期间,所存的数据可以跨浏览器 |
out | 用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。可以以流的方式给前端输出一些js代码 | |
pageContext | 可以获取 JSP页面的out、request、reponse、session、application 等对象。也可以进行存取值 | 当前页面 |
config | 、取得服务器的配置信息。通过 pageConext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。 | |
page | 对象代表JSP本身,只有在JSP页面内才是合法的,类似于Java编程中的 this 指针。 | |
exception | 显示异常信息,exception 对象几乎定义了所有异常情况,页面中出现没有捕获到的异常,就会生成exception 对象,并把 exception 对象传送到在page指令中设定的错误页面中,然后在错误页面中处理相应的 exception 对象。 |
1.在可能发生异常的页面设置errorPage,填写异常处理页面error.jsp
errorPage="error.jsp"
2.在error.jsp页面中设置isErrorPage="true" 的属性
isErrorPage="true"
3.2 JSP指令
指令名称 | 描述 |
---|---|
page | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
include | 包含其他文件 |
taglib | 引入标签库的定义 |
-
page指令
Page指令的语法格式:
<%@ page attribute="value" %>
常用属性 属性值 属性描述 language java 解释该JSP文件时采用的语言,一般为java语言,默认为java import 引入该JSP中用到的类、包等 import是唯一可以声明多次的page指令属性,中间用英文逗号隔开<%@page import=包名.类名,包名.类名%> session true、false 该JSP内是否内置Session对象,如果为true,则内置Session对象,可直接使用,否则反之,默认为true isThreadSafe true,false 是否线程安全,如果为true,则运行多个线程同时运行该jsp程序,否则只运行一个线程,其余线程等待,默认为false isErrorPage true,false 指定该页面是否为错误显示页面,如果为true,则该JSP内置有一个Exception对象 exception,可直接使用,否则没有,默认为false errorPage 某个JSP页面的相对路径 指明一个错误页面,如果该JSP程序抛出一个未捕捉的异常,则转到 errorPage指定的页面,errorPage指定的页面通常isErrorPage属性为true,且内置的exception对象为未捕捉的异常 -
include指令
通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。
Include指令的语法格式如下:
<%@ include file="文件相对 url 地址" %>
-
Taglib指令
JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。
Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
uri属性确定标签库的位置,prefix属性指定标签库的前缀(可自定义)。
<%@ taglib uri="uri" prefix="" %>
3.3 EL表达式和JSTL
EL表达式
:简化对象和变量访问的一种语法
EL表达式使用前提:该工程web.xml文件版本至少为2.5
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
EL表达式语法
语法格式:${需要取出数据的键值}
-
可以直接取出键对应的值
${键名}
当表达式没有指定变量或者对象的范围时,那么容器会依次从
pageContext—>request—>session—>application
中查找该变量或对象 -
指定作用域取出键对应的值
${作用域.键名}
pageScope对象,用于获取当前页面的属性值 requestScope对象,用于获取请求范围的属性值 sessionScope对象,用于获取会话范围的属性值 applicationScope对象,用于获取程序范围的属性值 例如: ${requestScope.key}
-
直接取出对象的属性值
如果将对象存入,可以通过
${该对象的键.属性名}
取出
切记,EL表达式不可以直接取出变量,只能通过将变量放入作用域的方式
JSTL
:JSP标签集合,它封装了JSP应用的通用核心功能
下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jar 和 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下。
语法格式:
1.引入标签库<%@ taglib prefix=”页面使用的名称” uri=”功能范围的路径”%>
功能范围 | Uri | 前缀 |
---|---|---|
core | http://java.sun.com/jsp/jstl/core | c |
i18n | http://java.sun.com/jsp/jstl/fmt | fmt |
sql | http://java.sun.com/jsp/jstl/sql | sql |
xml | http://java.sun.com/jsp/jstl/xml | x |
functions | http://java.sun.com/jsp/jstl/function | fn |
2.通过标签库前缀和标记及属性进行操作<前缀:标记 属性=“值”,属性=“值”>
常用的标记及属性有:
-
<c:set> :主要用来将变量存储至JSP范围中 或是JavaBean的属性或Map对象中
名称 说明 是否必须写 默认值 Value 要被存储的值 否 无 var 存入的变量名称 否 无 scope var变量的JSP范围 否 Page target JavaBean或Map对象 否 无 property 指定target对象的属性 否 无 -
<c:if> 主要用于进行if判断,如果为true,则输出标签体中的内容
名称 说明 是否必须写 默认值 Test 表达式的结果为true,则执行体内容,false则相反 是 无 var 如果 用来存储test运算的结果(true或false) 否 无 scope Var变量的JSP范围 否 page -
<c:forEach> 循环控制,它可以将数组,集合(Collection)中的成员循序浏览一遍。
名称 说明 必须 默认值 var 用来存放现在指定的成员 是 无 items 被迭代的集合对象(需要使用EL表达式) 否 无 varStatus 用来代指被迭代的集合对象 否 无 begin 开始的位置 否 0 end 结束的位置 否 最后一个成员 step 每次迭代的间隔数 否 1 -
< fmt:formatDate> 作用:将日期类型格式化为指定模式的字符串
名称 说明 默认值 value 将要被格式化的数据 pattern 格式化的模式,与SimpleDateFormat的参数设置一样,如yyyy-MM-dd var 格式化后的字符串所要存放的变量,若不指定var,则会将格式化的结果直接显示在页面 scope 变量存放的域属性空间 page type 其取值为date、time、both,表示给出的value是日期、时间、还是两者都包含 date
EL表达式与JSTL结合练习实例:
背景:取得后端传过来的对象数据集data,然后输出对象的属性
<% ArrayList data = new ProductDaoImpl().getAll();
request.setAttribute("data",data);
%>
<c:forEach items="${data}" var="product" >
产品名称:${product.name},产品最新版本:${product.version}<br>
</c:forEach>
4. Fiter过滤器
Fiter过滤器
:负责通拦截request进行处理,也可以对返回的response进行拦截处理,类似海关
4.1 创建Filter的方式
创建一个类实现Fiter接口(javax.servlet.Filter):
public class FilterString implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//初始化过滤器
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//具体的执行逻辑
//执行完过滤跳转到原请求目的地
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
//关闭过滤器
}
}
4.2 部署Filter过滤器
-
在web.xml文件中部署
<filter> <filter-name>过滤器名称</filter-name> <filter-class>过滤器所在的路径</filter-class> </filter> <filter-mapping> <filter-name>过滤器名称</filter-name> <url-pattern>需要过滤的资源</url-pattern> </filter-mapping>
-
通过@WebFilter注解部署
属性名 类型 描述 filterName String 指定过滤器的 name 属性,等价于 value String[] 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 urlPatterns String[] 指定一组过滤器的 URL 匹配模式。等价于 标签。 servletNames String[] 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 的取值。
4.2 Fiter使用场景
Filter的应用是比较广泛的,接下来针对非法文字筛选和下载资源的限制进行举例
1.防止用户未登录就执行后续操作
String name=(String)session.getAttribute("key");
if(name==null){
//跳转到登录页面
}
2.设置编码方式--统一设置编码
3.加密解密(密码的加密和解密)
4.非法文字筛选
5.下载资源的限制
5.Listenenr监听器
listener监听器
: 监听某个域对象的的状态变化的组件
事件源:被监听的对象(三个域对象request、session、servletContext)
监听器:监听事件源对象事件源对象的状态的变化都会触发监听器
注册监听器:将监听器与事件源进行绑定
响应行为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)
根据不同的监听域,实现不同的接口来创建Listener监听器:
- 创建方式:
class Listener implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
//session被创建时执行
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
//session被销毁时执行
}
}
-
部署监听器
在web.xml文件中
<listener> <listener-class>监听器所在的路径</listener-class> </listener>
或者直接在其类的上面增加注解@WebListener
6. MVC表现模式
-
MVC
为了便于管理繁杂的代码,以及降低代码的耦合性,于是衍生出了MVC模式,可以使开发者思路更加清晰,且代码更加利于维护
M(Model) 模型
: 应用程序的核心功能,管理这个模块中用的数据和值,包含Dao层和Bean层V(View )视图
: 视图提供模型的展示,管理模型如何显示给用户,它是应用程序的外观,一般指JSP或HTML前端页面C(Controller)控制器
: 对用户的输入做出反应,管理用户和视图的交互,是连接模型和视图的枢纽。包含Servlet层和Service层以下是一个规范的目录结构图:
1.Web包下负责与前端进行数据交互 2.Service包负责具体的处理逻辑 3.Dao包负责与数据库进行数据交互 4.Bean包负责以对象形式保存从Dao包取出的数据(通常:表名=类名,列名=属性名) 5.Util包负责一些常用工具类,比如德鲁伊连接池工具类
-
三层架构
与MVC模式不同的是,通常还会说一种三层架构, 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。
-
表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。 前端页面
-
业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。Web包和Service包
-
数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等。Dao包
表现层实现的代表作品是Struts,springmvc框架, 业务层实现的代表作品是Spring, 持久层实现的代表作品是Hibernate,mybatis。
-
-
三层架构与MVC的区别与联系
MVC是表现模式(Presentation Pattern)
三层架构是典型的架构模式(Architecture Pattern)
三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC作为表现模式是不存在上下关系的,而是相互协作关系。即使将MVC当作架构模式,也不是分层模式。MVC和三层架构基本没有可比性,是应用于不同领域的技
术。
7. AJAX
AJAX(Asynchronous JavaScript and XML)
:异步的 JavaScript 和 XML,并非一种新的技术,而是几种原有技术的结合体,可以实现只更新部分页面,不需要重新加载整个页面。
学习时候不要搞混了,AJAX可以归类为前端技术,是在js代码标签中进行实现的
7.1 AJAX工作原理
Ajax相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化。
- 并不是所有的用户请求都提交给服务器。像—些数据验证和数据处理等都交给Ajax引擎自己来做
- 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
有了AJAX层,用户页面可以不必等待服务器返回响应才可以进行下一个请求,而是以异步的方式,不同的AJAX请求互相不需要等待,极大的提高了效率
7.2 AJAX的核心——XMLHttpRequest对象
AJAX技术通过XMLHTTPRequest对象来进行实现,不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。注意AJAX属于前端技术,是在js标签中实现的
IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 JavaScript 内建对象
-
创建 XMLHttpRequest对象
因为浏览器不同需要创建的对象不同,所以通常都会写一个if语句来创建
var xmlHttp; if (window.XMLHttpRequest) { //非IE xmlHttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { //IE xmlHttp = new ActiveXObject("Microsoft.XMLHTTP") }
顺便我们需要了解一下XMLHttpRequest对象属性和方法:
-
设置请求方式
//第二步:设置和服务器端交互的相应参数,准备发送数据 var username=document.getElementById("username").value; var url = "/testuname?uname="+username; xmlHttp.open("get", url, true);
open()方法第一个参数为:请求方式,get/post 第二个参数为:请求发送的目的地,如果是get请求,则需要进行URL拼接 第三个参数为:是否设置为异步,通常都是true
-
指定回调函数
需要给XmlHttpRequest对象的onreadystatechange属性设置响应的处理函数
回调函数要实现的功能就是接收后台处理后反馈给前台的数据,然后将这个数据显示到指定的div上。因为从后台返回的数据可能是错误的,所以在回调函数中首先要判断后台返回的信息是否正确,如果正确才可以继续执行。
//第三步:注册回调函数 xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var obj = document.getElementById(id); obj.innerHTML = xmlHttp.responseText; } else { alert("AJAX服务器返回错误!"); } } }
-
发送请求
get请求:
因为在设置请求方式的步骤时,get请求已经指定了目标URL并拼接了数据,所以对get请求,发送请求只需要: xmlHttp.send(null);
post请求:
1.先设置请求头 xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); 2.将要传递的数据放入Send()方法中 xmlHttp.send("uname="+username)
7.3 JQuery简化AJAX操作
只需要使用封装好的AJAX()方法即可
$.ajax({
url:请求地址
type:"get | post | put | delete " 默认是get,
data:请求参数 {"id":"123","pwd":"123456"},
dataType:请求数据类型"html | text | json | xml | script | jsonp ",
success:function(data,dataTextStatus,jqxhr){ },//请求成功时
error:function(jqxhr,textStatus,error)//请求失败时
})
同样,也封装好了简易的Get/Post请求
$.get(url,data,function(result) {
//省略将服务器返回的数据显示到页面的代码
});
$.post(url,data,function(result) {
//省略将服务器返回的数据显示到页面的代码
});
url:请求的路径
data:发送的数据
result:自动接收从servlet打印流打印的字符串,默认是String,不能接收JSON格式
返回的数据都被封装到了一个叫result的变量里,get/post()中返回时text类型,ajax()中可以指定返回的数据类型
根据传回的数据格式选择不同的方法,如果是简单的字符串,建议使用get/post(),如果传回的是复杂数据,以JSON格式传回,只能使用ajax()
AJAX练习:
$(function () {
//接收旧点赞数并显示在html元素上
$("#likenum").text(${Old_likenum})
$("#likenum_button").click(function () {
//发送post方式AJAX请求,并更改元素text属性
$.post("/likenum++",function (result) {
$("#likenum").text(result)
})
})
})
解释:
Old_likenum是Servlet层放到作用域中的数据,通过EL表达式传给指定的HTML元素
然后对一个按钮设置点击触发方法,发送AJAX的post请求,
请求名为“/likenum++”,请求返回的数据封装在了result中,赋给了指定的HTML元素
8.文件上传
文件上传实质上就是客户端发起请求,将一个大数据IO流传个服务器
我们可以借助jar包来减少底层的编码量
-
添加jar包:smartupload.jar
-
创建smartupload对象并初始化
//创建对象 SmartUpload smartUpload = new SmartUpload(); //获得jsp的pageContent对象并初始化 PageContext pageContext = JspFactory.getDefaultFactory().getPageContext(this, req, resp, null, false, 1024, true); smartUpload.initialize(pageContext); //编码 smartUpload.setCharset("utf-8");
这里需要获得pageContext对象才可以初始化,所以需要先调用一个JSP工厂来获得其内置对象
-
文件上传
截止目前,文件就被上传到了服务器,但服务器并没有保存
//文件上传 try { smartUpload.upload(); } catch (SmartUploadException e) { e.printStackTrace(); }
-
保存文件到指定位置
/*保存文件*/ //得到smartUpload对象中文件数组的第1个文件 File file = smartUpload.getFiles().getFile(0); //得到该文件的信息 String fileName = file.getFileName(); //指定存储路径 String path = "UploadFile"+fileName; //存储 try { file.saveAs(path,SmartUpload.SAVE_VIRTUAL); } catch (SmartUploadException e) { e.printStackTrace(); }
至此,数据文件已经被存放到了某个指定路径下,接下来就可以自己决定如何在前端显示,可以将文件名发过去,指定文件路径,对之前的上传页面进行AJAX异步刷新
9.Git
现在,随着开发项目发展的越来越大,在公司中基本已经很难独立承担一个项目的开发,这就需要协同开发,这时候为了便于大家将不同的程序整合在一起,就需要进行版本控制。
Git
:是一个开源的分布式版本控制系统,用以有效、高速的特点承担从很小到非常大的项目版本管理.
下载地址:Downloading Git
9.1 Git常用操作
Git的工作区域分为下图三片区域:
只有提交到版本库才算是将代码进行了持久化保存,暂存区只是临时的中转站
-
设置签名用于区分不同的开发人员
设置用户名: git config --global user.name ‘用户名’ 设置用户名邮箱: git config --global user.email ‘邮箱’
-
提交文件:
1.工作区提交到暂存区:git add 文件名 2.查看暂存区内容:git status 3.暂存区内全部提交到仓库中:git commit -m 此次提交描述 4.若需要提交到远程仓库:git push
-
建立仓库:在当前路径下
git init
,就会看到出现一个.git文件 -
撤销未提交的修改:
* 对于修改中出现错误不想保存的情况,可以在尚未执行add命令之前, 使用git checkout filename 重置文件的修改 * 对于已经将错误文件add的情况,使用git reset --hard 重置到上一次提交
-
删除文件
1. 发起删除命令:git rm 文件名 如果想要删除文件夹,则添加参数 -r 2. 提交删除命令:git commit -m 此次提交描述
-
查看提交记录:
git log
-
克隆/下载代码:找到要下载的项目远程链接,
git clone 仓库地址
9.2 Git分支管理
推荐阅读:git分支的理解
在项目开发流程中,可能需要更新添加一些新的功能模块,但在此期间又不想影响主线功能正常运行,这时候就需要将新的功能放到主线的一个分支上进行开发,直到开发完毕合并到主线。
同时对于协同开发,每一位开发者使用一条分支,即使后来出现bug,根据分支合并的log文件,也可以快速定位问题。
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
-
查看分支:
git branch
$ git branch * dev master
有星号*标志的表示当前操作的分支
-
创建分支:
git branch 分支名
-
切换分支:
git checkout 分支名
,创建并切换分支:git checkout -b 分支名
-
合并分支:
git merge 分支名
-
删除分支:
git branch -d 分支名
-
查看分支合并信息:
git log --graph
恭喜每一位耐心学到这里的小伙伴,至此,经过将近3个月的学习,我们走到了JavaWeb,根据我们云同桌系列所讲的理论,认真学到这里的小伙伴已经可以自己独立完成一个大学校园级别的简易Web系统了,例如:学生管理系统、图书管理系统等等…相关的简易选题非常多,用到的技术基本我们都已经讲到了
这一节我给大家的建议学习时间是3周,实际上本节的理论只需要1周即可,剩余的时间我希望大家能够自己去独立完成一个简易的Web项目,毕竟,脱离敲代码的学习java永远都是纸上谈兵,而博主接下来也会暂停更新半个月左右,我也有一个小项目要去做,并且要去找实习了…暂别半个月~,希望下一篇文章能看到各位小伙伴的留言汇报自己的学习总结