欢迎来到 盛码笔记,这篇是我在 CSDN 的第一篇博文,标志着这段记录与分享的技术旅程的开始。欢迎留言交流,技术路上共同前行!
(一)web项目配置
web项目结构
创建一个web项目
-
创建一个普通的maven项目
-
在该项目的pom.xml文件中,修改打包方式(记得刷新一下)
<packaging>war</packaging>
-
选择”文件——项目结构——Facet“,点”+“添加WebApp文件,和web.xml文件
-
最后调整文件位置,WEB-INF文件放到WebApp文件下
-
配置Tomcat插件,在项目文件pom.xml里添加插件坐标
-
最后装一个插件——Maven Helper就可以跑项目了(这里也可以本地部署Tomcat运行)
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins> </build>
(二)Servlet快速入门
servlet是java提共的一门动态资源开发技术,实际上就是接口,我们需要定义Servlet类实现Servlet接口,并有Tomcat运行Servlet
-
创建web项目,导入Servlet依赖坐标
注意:Servlet需要限制其作用域,即
<scope>provided</scope>
,provided指定Servlet在编译和测试阶段可用-
冲突:应用服务器已经提供了 Servlet API,打包的依赖可能会与服务器提供的版本冲突。
-
冗余:Servlet API 会被重复包含,增加包的大小。
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <!-- 作用域(范围)--> <scope>provided</scope> </dependency> </dependencies>
-
-
定义一个类实现Servlet接口,并重写所有方法
@Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("hello world~"); } @Override public String getServletInfo() { return ""; } @Override public void destroy() { }
-
配置:在该类上使用@WebServlet,配置该Servlet的访问路径
@WebServlet("/demo1") public class ServletDemo1 implements Servlet {}
-
访问:启动Tomcat,输入url访问该Servlet
http://localhost:8080/tomcat/demo1
(三)Servlet执行流程
我们创建的实现Servlet接口的类由web服务器创建对象,并调用其中的方法
(四)Servlet生命周期
生命周期指一个对象从创建到被销毁的整个过程
Servlet运行在Servlet容器(web服务器)中,其生命周期由容器管理,分为四个阶段
-
加载和实例化:默认情况下,在Servlet被第一次访问时,容器就会创建Servlet对象。
-
通过给loadOnStartup赋值可以改变对象创建时机,默认为负整数数
@WebServlet(urlPatterns = "/demo1",loadOnStartup = 1)
负整数:当Servlet第一次被访问时创建对象
0或正整数:在启动服务器时创建Servlet对象,数字越小,优先级越高
-
-
初始化:在初始化之后,容器会调用Servlet的
init()
方法初始化该对象,完成一些加载文件配置等工作。该方法只调用一次。 -
请求处理:当每次请求Servlet时,容器会调用service()方法处理。
-
服务终止:当需要释放资源或容器关闭时,容器会调用destory()方法完成资源释放。最后该对象会被垃圾回收器回收。
注意:当urlPattern错误时会报错A child container failed during start
(五)Servlet体系结构
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post...");
}
}
HttpServlet根据请求类型进行判断,然后进行分别处理,以下代码实现类似效果
public class MyHttpServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//1.根据请求方式判断处理
HttpServletRequest request=(HttpServletRequest) servletRequest;
String method = request.getMethod();
//2.判断是get还是post
if("GET".equals(method)){
doGet(servletRequest,servletResponse);
}else if(method.equals("POST")){
doPost(servletRequest,servletResponse);
}
}
protected void doGet(ServletRequest servletRequest, ServletResponse servletResponse) {
System.out.println("get...");
}
protected void doPost(ServletRequest servletRequest, ServletResponse servletResponse) {
System.out.println("post...");
}
@Override
public String getServletInfo() {
return "";
}
@Override
public void destroy() {
}
}
(六)Servlet 的urlPattern配置
(七)Request对象
Request继承体系
Request获取请求数据
1.请求行:POST /users/12345/orders?status=completed&limit=10 HTTP/1.1
方法 | 作用 | 例子 |
---|---|---|
String getMethod() | 获取请求方式 | POST |
String getContextPath() | 获取虚拟目录(项目访问路径) | /users/12345/orders |
StringBuffer getRequestURL() | 获取url(统一资源定位符) | http://localhost:8080/tomcat/demo2 |
String getRequestURI() | 获取URI(统一资源标识符) | /tomcat/demo2 |
String getQueryString() | 获取请求参数(GET请求方式) | status=completed&limit=10 |
-
请求头:
方法 | 作用 |
---|---|
String getHeader(String name) | 根据请求头名称,获取值 |
-
请求体
方法 | 作用 |
---|---|
ServletInputStream getInputString() | 获取字节输入流(图片,视频,音频等) |
BufferReader getReader() | 获取字符输入流(纯字符) |
因为GET和POST获取请求参数的方式不同,无法进行统一编程,所以采用通用方式获取请求参数
-
Request会根据方式进行判断,分别获取请求参数,再将参数切割后放入一个Map集合存储
方法 | 作用 |
---|---|
Map<String,String[]> getParameterMap() | 获取所有参数的Map集合 |
String[] getParameterValues(String name) | 根据名称获取参数值(数组) |
String getParameter(String name) | 根据名称获取参数值(单个值) |
Request获取请求数据乱码解决
-
GET请求乱码
GET请求的参数是通过URL传递的,而URL默认使用ISO-8859-1编码(一种单字节编码)。如果参数中包含非ASCII字符(如中文),而服务器端没有正确解码,就会导致乱码。
解决方法:手动解码
String param = new String(request.getParameter("key").getBytes("ISO-8859-1"), "UTF-8");
String param = new String(request.getParameter("username").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
-
POST请求乱码
POST请求的参数是通过请求体传递的,默认情况下,服务器可能没有正确设置请求体的编码方式。如果客户端发送的是UTF-8编码的数据,而服务器端使用ISO-8859-1或其他编码解析,就会导致乱码。
-
解决方法:设置字符输入流编码
request.setCharacterEncoding("UTF-8");
请求转发(forward)
一种服务器内部资源跳转的方式
实现方式:
request.getRequestDispatcher("/req5").forward(request,response);
当请求转发间需要共享数据时,使用Request对象
方法 | 作用 |
---|---|
void setAttribute(String name, Object o): | 存储数据到Requst域中 |
Object getAttribute(String key): | 根据key获取值 |
void removeAttribute(String key): | 根据key删除键值对 |
特点:
-
浏览器地址栏路径不会改变
-
只能转发到当前服务器内部资源
-
一次转发,可以共享Request内部资源
-
在一次请求中,请求转发只能执行一次。
注意:与前端页面连接
-
<input>输入框name属性要与键值对中的键值一致
-
在浏览器中可以查看请求参数
-
表单要设置method,即请求方式,默认为GET
-
路径要用虚拟目录路径
(八)Response对象
Response设置响应数据功能
-
响应行:
HTTP/1.1 200 OK
方法 作用 示例 void setStatus(int sc): 设置响应状态码 200 OK -
响应头:
Content-Type: text/html; charset=UTF-8 Content-Length: 1234 Date: Mon, 23 Oct 2023 12:34:56 GMT
方法 | 作用 | 示例 |
---|---|---|
void setHeader(String key, String value): | 设置响应头键值对 | Content-Length: 1234 |
-
响应体
方法 作用 PrintWriter getWriter() 获取字符输出流 ServletOutputStream getOutputStream() 获取字节输出流
Response重定向
一种资源跳转方式
//重定向
response.setStatus(302);
response.setHeader("Location","/tomcat/resp2");
//简化写法
response.sendRedirect("/tomcat/resp2");//项目路径
特点:
-
浏览器地址栏路径发生改变
-
可以重定向到任意位置资源(服务器内部、外部均可)
-
两次请求不共享数据域
路径问题
是否需要添加虚拟目录(项目路径)?
-
根据适用对象来进行判断
-
如果是浏览器使用,需要加虚拟目录
-
如果是服务器使用,不需要加虚拟目录
<a ref="/request-demo/demo1"> 加虚拟目录
注意:动态获取虚拟目录
String contextPath = request.getContextPath();
//简化写法
response.sendRedirect(contextPath+"/resp2");
Response响应字符数据
//获取字符输出流
PrintWriter writer = response.getWriter();
response.setHeader("content-type","text/html");
writer.write("<h1>aaa<h1>");
解决中文乱码问题
原因:通过Response获取的字符输出流默认使用字符编码IOS-8859-1
response.setContentType("text/html;charset=utf-8");
注意:字符输出流不需要手动关闭,Response对象销毁时,会自动关闭
Response响应字节数据
//1.获取IO流
FileInputStream fis = new FileInputStream("E:\\a.jpg");
//2.获取输出流
ServletOutputStream outputStream = response.getOutputStream();
byte[] buff=new byte[1024];
int len =0;
while((len=fis.read(buff))!=-1){
outputStream.write(buff,0,len);
}
还可以通过IOUtils工具类
<-- 导入依赖 --></-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
IOUtils.copy(fis,outputStream);
(九)拓展
servlet获取json数据
package com.cqut.web;
import com.alibaba.fastjson.JSON;
import com.cqut.pojo.Brand;
import com.cqut.service.BrandService;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
private BrandService brandService=new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取页面传递JSON数据
request.setCharacterEncoding("utf-8");
BufferedReader reader = request.getReader();
String jsonString = reader.readLine();
//2.JSON转为java对象
Brand brand = JSON.parseObject(jsonString, Brand.class);
//3.调用添加方法
brandService.add(brand);
//4.相应数据
response.getWriter().write("success");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
最后,受限于本人水平,文章中如有疏漏或理解不当之处,欢迎指出交流。