предисловие
Java Web относится к сумме технологий, используемых для решения связанных веб-полей в Java.Веб-приложение включает две части: веб-клиент и веб-сервер, то есть приложение, основанное на архитектуре B/S (браузер/сервер).
1. Оба конца
1.1 Веб-клиент
Веб-клиент обычно относится к браузеру на компьютере пользователя, например браузеру Microsoft IE или браузеру Firefox. Клиенту не нужно разрабатывать какой-либо пользовательский интерфейс, а браузер можно использовать единообразно.
1.2 Веб-сервер
Веб-сервер — это один или несколько компьютеров, на которых могут запускаться веб-приложения.Обычно адрес веб-сайта, который мы вводим в браузере, является адресом веб-сервера. Когда пользователь вводит адрес веб-сайта в адресную строку браузера и нажимает клавишу ввода, запрос отправляется на веб-сервер. После того, как сервер получит запрос, он вернет пользователю ответное сообщение с запрошенным ресурсом. Применение Java на стороне сервера очень богато, например, Servlet, JSP и сторонние фреймворки.
Две, две остановки
2.1 Статический веб-сайт
Ранние веб-приложения предназначались в основном для просмотра статических страниц, то есть статических веб-сайтов.
Эти веб-сайты написаны на HTML и размещены на веб-сервере.
Пользователь использует браузер для запроса веб-страницы на сервере по протоколу HTTP, а веб-сервер обрабатывает полученный запрос пользователя и отправляет его в клиентский браузер для отображения пользователю. Принцип работы следующий:
2.2 Динамический веб-сайт
Ресурсы, к которым обращаются пользователи, больше не ограничиваются статическими веб-страницами, сохраненными на сервере. Дополнительный контент должен динамически генерировать информацию о странице в соответствии с запросом пользователя, то есть динамический веб-сайт.
Эти веб-сайты обычно написаны на языке HTML и языке динамических сценариев (например, JSP, ASP или PHP и т. д.), а написанные программы развертываются на веб-сервере.
Динамический код скрипта обрабатывается веб-сервером и преобразуется в HTML-код, который может быть проанализирован браузером и, наконец, возвращается в клиентский браузер для отображения пользователю. Рабочий процесс выглядит следующим образом:
Три, две структуры
3.1 Структура C/S
Клиенту необходимо установить специальное клиентское программное обеспечение. как показано на рисунке:
3.2 Структура Б/С
В структуре B / S клиенту не нужно разрабатывать любой пользовательский интерфейс, но равномерно использует такие браузеры, как IE или Firefox. Запрос отправляется на веб-сервер через веб-браузер, а также процессы веб-сервера и передает результат обработки обратно на шаг клиента, как показано на рисунке.
встроенные объекты
1.Request对象
Request对象是javax.servlet.http.HttpServletRequest类的实例。代表请求对象,主要用于接受客户端通过HTTP协议连接传输到服务器端的数据。比如表单中的数据、网页地址后带的参数等。
2.Response对象
Response对象是javax.servlet.http.HttpServletResponse类的实例。代表响应对象,主要用于向客户端发送数据。
3.Out对象
Out对象是javax.servlet.jsp.JspWriter类的实例。主要用于向客户端浏览器输出数据。
4.session对象
Session 对象是javax.servlet.http.HttpSession类的实例。主要用来保持在服务器与一个客户端之间需要保留的数据,比如在会话期间保持用户的登录信息等,会话状态维持是Web应用开发者必须面对的问题。当客户端关闭网站的所有网页或关闭浏览器时,session对象中保存的数据会自动清除。由于Htp协议是一个无状态协议,不保留会话间的数据,因此通过session对象扩展了htp的功能。比如用户登录一个网站之后,登录信息会暂时保存在session对象中,打开不同的页面时,登录信息是可以共享的,一旦用户关闭浏览器或退出登录,就会清除session对象中保存的登录信息。
5.Application对象
Application对象是javax.servlet.ServletContext类的实例。主要用于保存用户信息,代码片段的运行环境;它是一个共享的内置对象,即一个容器中的多个用户共享一个application对象,故其保存的信息被所有用户所共享。
6.PageContext对象
PageContext对象是javax.servlet.jsp.PageContext类的实例。用来管理网页属性,为JSP页面包装页面的上下文,管理对属于JSP中特殊可见部分中已命名对象的访问,它的创建和初始化都是由JSP容器来完成的。
7.Config对象
Config对象是javax.servlet.ServletConfig类的实例。是代码片段配置对象,表示Servlet的配置。
8.Page(相当于this)对象
Page对象是javax.servlet.jsp.HttpJspPage类的实例。用来处理JSP网页,它指的是JSP页面对象本身,或者说代表编译后的servlet对象,只有在JSP页面范围之内才是合法的。
9.Exception对象
Exception对象是java.lang.Throwable类的实例。处理JSP文件执行时发生的错误和异常只有在JSP页面的page指令中指定isErrorPage=“true”后,才可以在本页面使用exception对象。
В-четвертых, JavaBean
4.1 Предыстория создания JavaBean
На начальном этапе разработки веб-страницы JSP не существует фреймворка и концепций логического разделения, и код Java должен быть встроен в веб-страницу для обработки некоторой бизнес-логики на странице JSP, такой как обработка строк и операции с базой данных. процесс показан на рисунке.
4.2 Роль JavaBeans
Если код HTML и Java разделены, код Java инкапсулируется в класс, который обрабатывает некоторую бизнес-логику. Затем вызов этого класса на странице JSP может уменьшить связь между HTML и кодом Java, упростить страницу JSP и улучшить возможность повторного использования и гибкость программного кода Java. Он отделен от кода HTML, а класс, инкапсулированный кодом Java, является компонентом JavaBean.
В веб-разработке на Java этот компонент можно использовать для завершения обработки бизнес-логики, а режим разработки с применением комбинации JavaBean и JSP показан на рисунке.
4.3 Применение JavaBeans
JavaBean написан на языке Java - это многоразовые компоненты, которые широко используются, многие слои могут применяться к системам, такие как PO, VO, DTO POJO и тому подобное.
Пять, сервлета
Пользователь получает доступ к сервлету, щелкнув ссылку или непосредственно введя URL-адрес в адресной строке браузера.После того как веб-сервер получает запрос, он не передает запрос непосредственно контейнеру сервлета. Контейнер сервлета создает экземпляр сервлета и вызывает определенный метод сервлета (service()) и выдать ответ. Этот ответ возвращается контейнером сервлета на веб-сервер, который упаковывает ответ и отправляет его в веб-браузер как ответ HTTP. Весь процесс показан на рисунке:
6. Как сообщить серверу, что вы здесь были?
6.1 Технология файлов cookie
Роль файлов cookie: с точки зрения непрофессионала, когда пользователь получает доступ к серверу через протокол HTTP, сервер возвращает некоторые пары ключ-значение в браузер клиента и добавляет некоторые ограничения к данным. сервер в следующий раз, данные полностью возвращаются на сервер.
Эта функция похожа на то, как когда вы идете за покупками в супермаркет, вы впервые получаете карту покупок.Эта карта покупок хранит часть вашей личной информации.В следующий раз, когда вы придете в этот сетевой супермаркет, супермаркет распознает вашу карту покупок и скачать Просто переходите к покупкам. Когда W3C разрабатывал Cookie, на самом деле предполагалось записывать поведение пользователей, обращающихся к веб-приложениям, в течение определенного периода времени. Поскольку протокол HTTP является протоколом без сохранения состояния, когда запрос пользователя на доступ заканчивается, внутренний сервер не может знать, является ли пользователь, который обращается в следующий раз, пользователем, который обращался в последний раз.При разработке приложения это легко дважды подумать.Доступ - это доступ для одного человека, а другой доступ для двух человек сильно различается по дизайну и производительности программы. Например, за короткий период времени, если к данным, связанным с пользователем, часто обращаются, данные могут быть кэшированы, что может значительно повысить производительность доступа к данным. Роль файлов cookie именно здесь.Поскольку это запрос, отправленный одним и тем же клиентом, каждый запрос будет нести информацию, установленную сервером во время первого посещения, так что сервер может разделить посещающих пользователей в соответствии со значением файла cookie.
@WebServlet("/CookieTest")
public class CookieTest extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Cookie[] cookies = request.getCookies();
PrintWriter out = response.getWriter();
if(cookies!=null){
out.println("上次访问的时间是:");
for (Cookie cookie : cookies) {
if("lastTime".equals(cookie.getName())){
long lastTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastTime);
out.println(date.toLocaleString());
}
}
}else{
out.println("你是第一来");
}
Cookie cookie = new Cookie("lastTime", String.valueOf(System.currentTimeMillis()));
//给cookie设置一些信息
//cookie.setMaxAge(500); //有效期
//cookie.setPath(uri);
//服务器端给客户端一个Cookie
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Декодирование и кодирование (не связанные с файлами cookie, просто способ устранения искаженных символов)
//传中文,避免乱码。可以进行编码
Cookie cookie = new Cookie("lastTime",URLEncoder.encode("尚", "utf-8"));
//取出Cookie值,需要解码
URLDecoder.decode(cookie.getValue(),"utf-8");
6.2 Сеансовая технология
Зачем вам Сессия?
Ранее было описано, что куки-файлы могут разрешить серверным программамотслеживатьКаждый визит клиента, но каждый визит клиента должен возвращать эти куки.Если куки много, то это незримо увеличит объем передачи данных между клиентом и сервером, и появление Session должно решить эту проблему.
Каждый раз, когда один и тот же клиент взаимодействует с сервером, ему не нужно каждый раз возвращать все значения cookie, а нужно только вернуть идентификатор, который генерируется, когда клиент обращается к серверу в первый раз, и каждый клиент уникальный. Таким образом, у каждого клиента есть唯一的ID
, клиент должен только вернуть этот идентификатор, который обычно является нанесением какJSESIONID
печенья.
Браузер заходит на сервер, чтобы снять дом, сервер записывает поведение и данные браузера, а затем дает браузеру ключ от комнаты Тогда каждый раз браузер может использовать свой ключ, чтобы открыть свою комнату и использовать все, что есть в комнате. (Конечно, вы не можете открыть чужую комнату, не говоря уже о том, чтобы открыть ее)
7. Контекст
7.1 Происхождение SeveletContext или ApplicationContext
Браузеры хотят заниматься спортом и чувствовать себя хорошо. Официант подумал, что я не могу добавить комплект спортивного инвентаря в каждую из ваших комнат, какое финансовое давление на меня. Сервер подумал об этом и решил построить общественное место, тренажерный зал, и все браузеры могут использовать эти共享资源
.
@WebServlet("/SessionTest1")
public class SessionTest extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("Session的ID为:");
// 获取 Session
HttpSession session = request.getSession();
out.write(session.getId());
session.setAttribute("name", "shang");
//设置当前会话多久结束,单位秒。如果设置的值为零或负数,则表示会话将永远不会超时。常用于设置当前会话时间。
// session.setMaxInactiveInterval(1);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/SessionTest2")
public class SessionTest2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
HttpSession session = request.getSession();
//移除session的数据
session.removeAttribute("name");
//手动注销当前会话
session.invalidate();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
7.2 контекст сервлета
Каждое веб-приложение, работающее на виртуальной машине Java, имеет связанный с ним контекст сервлета. Java Servlet API предоставляет интерфейс ServletContext для представления контекстов. Этот интерфейс определяет набор методов, которые сервлет может использовать для связи со своим контейнером сервлетов, например, для получения MIME-типа файла, пересылки запроса или записи сообщений журнала в файл журнала.
Объект ServletContext является корнем известного пути на веб-сервере. Например, контекст сервлета находится вhttp://localhost:8080/ch02
. от/ch02
Все запросы, начинающиеся с пути запроса (называемого путем контекста)отправляется вс этимServletContext
Связанное веб-приложение. В качестве другого примера мы обычно используемhttp://localhost:8080/
. от/
Все запросы, начинающиеся с пути запроса (называемого путем контекста)отправляется вВеб-приложение, связанное с этим ServletContext.
ServletContext: это концепция из спецификации сервлета, представляющая собой комбинацию интерфейсов, которые сервлеты используют для взаимодействия с контейнерами, то есть этот интерфейс определяет ряд методов.сервлет может легко взаимодействовать со своим собственным контейнером с помощью этих методов. В приложении (JVM) может быть несколько контейнеров сервлетов, и все контейнеры сервлетов совместно используют ServletContext.
8. Две эпохи
8.1 Эпоха Model1
Начальным режимом разработки JSP является режим Model 1: JSP+JavaBean.
8.2 Эпоха Model2
Медленно перешел в режим Model 2: JSP+Servlet+JavaBean.
Модель 2 соответствует архитектурному шаблону MVC, MVC — это Модель-Представление-Контроллер (Model-View-Controller).
- МодельДанные, представляющие приложение и бизнес-правила для доступа и изменения этих данных. Когда модель изменяется, она уведомляет представление и предоставляет ему возможность запрашивать соответствующее состояние модели. В то же время он также предоставляет контроллеру возможность доступа к функциям приложения, инкапсулированным внутри модели.
- ПосмотретьИспользуется для организации содержимого модели. Он берет данные из модели и указывает, как должны вести себя эти данные. При изменении модели представление отвечает за поддержание согласованности представления данных. Представление также уведомляет контроллер о запросе пользователя.
- контроллерОпределяет поведение приложения. Он отвечает за интерпретацию пользовательских запросов от представлений и преобразование этих запросов в соответствующее поведение, которое реализуется моделью. В автономном GUI-клиенте запросом пользователя может быть щелчок мышью или выбор меню. В веб-приложении они могут появиться в виде HTTP-запроса GET или POST от клиента. Поведение, реализованное моделью, включает обработку бизнеса и изменение состояния модели. На основе запроса пользователя и результата поведения модели контроллер выбирает представление в качестве ответа на запрос пользователя. как показано на рисунке:
Девять, загрузка и загрузка файлов
9.1 Загрузка файлов
- импортный пакет jar
commons-io.jar
иcommons-fileupload.jar
- Форма должна быть отмечена
enctype="multipart/form-data"
<%--
${pageContext.request.contextPath}:保证我发布在项目在服务器上也能被访问
--%>
<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
上传用户:<input type="text" name="username"><br/>
<input type="file" name="file1"><br/>
<input type="submit" value="提交"> | <input type="reset" value="重置">
</form>
- ServletFileUpload отвечает за обработку загруженных данных файла и инкапсулирует каждый элемент ввода в форме в объект FileItem.Объект DiskFileItemFactory требуется при использовании объекта ServletFileUpload для анализа запроса. Поэтому нам необходимо создать объект DiskFileItemFactory() перед синтаксическим анализом и установить атрибут fileItemFactory объекта ServletFileUpload через конструктор объекта ServletFileUpload или метод setFileItemFactory().
package com.shang.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;
public class FileServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判断上传的表单是普通表单还是带文件的表单
if(!ServletFileUpload.isMultipartContent(request)){
return;
}
//创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if(!uploadFile.exists()){
uploadFile.mkdir();
}
//缓存,临时文件
//临时路径,假如文件超出了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File tmpFile = new File(tmpPath);
if(!tmpFile.exists()){
tmpFile.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦。但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件:
//1. 创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
String msg = null;
try {
msg = uploadParseRequest(upload, request, response, uploadPath);
} catch (FileUploadException e) {
e.printStackTrace();
}
//servlet请求转发消息
request.setAttribute("msg", msg);
request.getRequestDispatcher("info.jsp").forward(request, response);
}
protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
public static DiskFileItemFactory getDiskFileItemFactory(File file){
//通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M
factory.setRepository(file);//临时目录的保存目录,需要一个File
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead:已经读取到的文件大小
//pContentLength:文件大小
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:"+pContentLength+"已上传:"+pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1024 = 1kb * 1024 =1M * 10 =10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,HttpServletResponse response,String uploadPath) throws FileUploadException, IOException {
String msg = "";
//把前端请求解析,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if(fileItem.isFormField()){ //判断上传文件是普通表单还是带文件的表单
//getFiledName指的是前端表单控件的name
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8"); //处理乱码
System.out.println(name+":"+value);
}else {//判断它是上传文件
//========处理文件======
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:"+uploadFileName);
if(uploadFileName.trim().equals("")||uploadFileName==null){
continue;
}
//获取上传的文件名 /images/boy/cool.jpg
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获取文件的后缀
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
* 如果文件后缀名 fileExtName 不是我们所需要的,
* 就直接return,不处理,告诉用户文件类型不对
* */
System.out.println("文件信息 [件名:"+fileName+"----文件类型"+fileExtName+"]");
//可以使用UUID(唯一识别的通用码),保证文件的唯一
//,UUID.randomUUID(),随机生成一个唯一识别的通用码
String uuidPath = UUID.randomUUID().toString();
//===========================处理文件完毕========
//存到哪? uploadPath
//文件真实存在的路径 realPath
String realPath = uploadPath +"/"+uuidPath;
//给每个文件创建一个对应的文件夹
File realPathFile = new File(realPath);
if(!realPathFile.exists()){
realPathFile.mkdir();
}
//存放地址完毕
//=======文件传输=====
//获取文件的上传流
InputStream inputStream = fileItem.getInputStream();
//创建文件输出流
//realPath 真实的文件夹
//差一个文件;加上输出的名字+"/"+uuidFileName
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
//判断是否读取完毕
int len = 0;
//创建一个缓冲区
byte[] buffer = new byte[1024*1024];
//如果不等于-1说明还存在数据
while((len = buffer.length)!= -1){
fos.write(buffer, 0, len);
}
//关闭流
fos.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete();// 上传成功,清除临时文件
}
}
return msg;
}
}
9.2 Загрузка файлов
public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取下载文件的路径
//String path = this.getServletContext().getRealPath("/1.jpg");
String path = "G:\\MyIDEProject\\JavaWeb\\UploadFile\\resources\\1.jpg";
System.out.println("要下载的文件路径"+path);
//2.下载的文件名
String filename = path.substring(path.lastIndexOf("\\") + 1);
//3.设置让浏览器支持我们要下载的东西
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//4.获取下载文件的输入流
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
//5.创建缓冲区
byte[] buffer = new byte[1024];
int len = 0;
//6.获取OutputStream对象
ServletOutputStream fos = response.getOutputStream();
//7.将FileOutputStream流写入到buffer缓冲区
while((len = buffer.length)!=-1){
//8.使用OutputStream将缓冲区中的数据输入到客户端
fos.write(buffer, 0, len);
}
//9. 关闭流
fos.close();
fis.close();
}
}