什么是servlet ?
抖音是一个动态页面:https://www.douyin.com/
我们在加载静态页面时:一般在第一次加载完静态页面之后后面再次加载部分资源都走缓存,所以当我们在写前端项目对部分资源进行修改时,我们一定要记得清除浏览器中的缓存。
二.创建第一个servlet程序
1.创建项目
生成目录结构
2.设置编码格式
3.引入依赖:我们一般需要什么依赖时,直接在maven仓库中直接引入:https://mvnrepository.com/对于servlet程序而言,第一步要先引入servlet依赖。
4.完善目录结构:在main包下创建webapp的包,同时创建子包WEB-INF,传入web.xml的配置文件,这样一来,基本的结构就比较完整了
5.编写代码
6.修改打包方式并进行打包
我们在maven中进行打包, 打包结果如下:
当提示打包成功后我们查看其相关的包:我们发现打包的结果是一个jar包,但是在tomcat环境下运行需要将其打成war包,因此,我们需要修改一下打包方式:
这时候的打包结果如下:
除打包之外,我们也应该了解一下有关项目声明周期的其他指令:url如下:
Maven – Introduction to the Build Lifecycle
7.将打包的程序部署到tomcat:把生成的war包部署到tomcat中的webapps的文件夹中
在Windows的打开tomcat的文件是以bat结尾的文件,因此使用startup.bat运行tomcat,以.sh结尾的文件是在Linux系统下运行的,而使用关闭tomcat连接的方式是:Ctrl+v或者双击shutdown.bat
我们发现运行时出现的提示信息均为乱码,这是因为编码集的差别,Windows环境下默认的编码方式是GBK,而我们在tomcat 中的设置的编码集是utf-8,所以在解码时出现乱码,如果想要恢复正常,则可以修改其logging.properties这个文件的部分内容:
8.测试验证程序:我们发现我们能打开tomcat的主页,这时说明tomcat启动成功了。
我们在运行tomcat之后会生成一个与war包名称一致的文件夹,我们以这个文件夹作为
但是如果以后都使用这种方式运行servlet,我们每次对源码进行更新都要重新打包然后部署到tomcat,操作起来非常麻烦,但是如果将tomcat导入到ideal中,直接在ideal中使用tomcat运行程序,会简单很多,所以我们直接使用tomcat server将tomcat导入到ideal中,但是很多小伙伴对这个过程比较陌生,推荐大家去看我的另一篇博客:听说你也在为配置tomcat server而烦恼,看我这一篇,让你醍醐灌顶!_努力努力再努力mlx的博客-CSDN博客
如果能够保证服务器能够正常运行,一般而言,出现的404错误都是由于访问路径出错了,我们可以尝试从以下这几方面进行考虑:
①没有写 contextpath
②没有写servletpath
③ servletpath 路径错误
我们拿这个路径进行说明:servlet_ljl_war_exploded是context path,index.jsp是servlet path,如果我们的程序中出现404错误,我们可以从这两个方面进行考虑。
方法错误是后端提供的方法和我们访问的方法不一致,即后端是通过get方法进行请求,但是我们却使用post方法进行请求,这时则会出现405错误:方法不允许,其实出现这个错误进行异常检验也相对简单,直接对接前后端接口的方法类型即可。
3.500异常
出现这个问题的原因主要是因为服务器内部出现错误,这时候我们需要从服务器内部进行调错。
4.出现“空白页面”
一般而言,如果页面没有给出响应,也没有报出任何错误,其实这时候大多数情况下是因为我们在后端并没有给出任何响应。
5.无法访问网页
HttpServlet 的主要作用之一是转发请求
4.2servlet的生命周期
package exer;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
* @author tongchen
* @create 2023-04-01 15:36
* 测试请求中的各种方法
*/
//设置注解,使浏览器可以访问
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//在涉及前后端交互的过程中,最先要确定的就是在数据传输过程中的编码格式问题
//确定传输过来数据的编码格式
req.setCharacterEncoding("utf-8");
//确定返回响应的编码格式
resp.setContentType("text/html;charset=utf-8");
//创建StringBuilder
StringBuilder stringBuilder = new StringBuilder();
//获取请求方法
String method = req.getMethod();
stringBuilder.append(method);
//换行
stringBuilder.append("
");
//获取URL
String requestURI = req.getRequestURI();
stringBuilder.append(requestURI);
stringBuilder.append("
");
//获取协议和版本号
String protocol = req.getProtocol();
stringBuilder.append(protocol);
stringBuilder.append("
");
//获取跟路径
String contextPath = req.getContextPath();
stringBuilder.append(contextPath);
stringBuilder.append("
");
//获取queryString
String queryString = req.getQueryString();
stringBuilder.append(queryString);
stringBuilder.append("
");
stringBuilder.append("++++++++++++++++++++");
//获取请求报头信息
Enumeration headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String elementKey = headerNames.nextElement();
String elementValue = req.getHeader(elementKey);
stringBuilder.append(elementKey+" "+ elementValue);
stringBuilder.append("
");
}
//将全部信息写回浏览器
resp.getWriter().write(stringBuilder.toString());
}
}
结果显示:
4.4关于前后端传输过程中的乱码问题:
通常我们在数据传输到后端或者前端的时候,出现最多的问题中文数据在传输到后端或者前端时出现了乱码:但其实乱码问题只是前后端交互过程中的一个小问题,我们千万不要感觉慌张,把大问题分解为小问题,有条不紊,一步一步地将问题解决。
我们可以将数据传输过程中出现的乱码问题分为这三个阶段进行校验和处理:①浏览器将数据发送给服务器过程中出现乱码②服务器在处理数据过程中出现乱码③服务器将响应数据返回给浏览器时出现乱码:我们对此进行逐层分析即可。
我们使用以下的例子对此进行说明:
package exer;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
/**
* @author tongchen
* @create 2023-04-01 16:29
*/
@WebServlet("/parameter")
public class GetParameter extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置接收格式
req.setCharacterEncoding("utf-8");
String studentId = req.getParameter("studentId");
String studentName = req.getParameter("studentName");
String format = MessageFormat.format("studentId={0},studentName={1}", studentId, studentName);
//在控制台打印
System.out.println(format);
//设置返回格式
// resp.setContentType("text/html;charset=utf-8");
//返回数据
resp.getWriter().write(format);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
我们在服务器响应给浏览器的数据中发现studentName这一属性成了乱码,我们按照以上的三个方面对此进行分析:
从控制台中打印的代码来看的话,前端往后端传来的数据并没有出现乱码,这说明从前端往服务器传输数据没有出现乱码,而我们只是将数据进行了简单的输出,数据处理过程也不会出现乱码,所以我们将问题锁定在从服务器往前端的数据传输过程中出现了乱码,我们对此来进行分析:我们并没有对服务器到前端传输数据时规定好数据格式,因此存在由于前后端编码解码方式不一致所导致的乱码问题,因此我们需要规定好数据从后端传往前端的数据格式问题。
加入这样一条语句即可:
resp.setContentType("text/html;charset=utf-8");
我们发现了上面语句中出现了我们不了解的陌生知识点,关于text/html,这是个什么东东呢?这是规定了后端往前端传输数据的格式。
关于前后端数据传输的格式,通常有以下几种:常见的type有,如text,如果是*号代表所有;
常见的subtype有,如果是*号代表所有,用“/”与主类型type隔开;
以get请求获取参数,通常是使用getParameter()这个方法来获取参数,而get请求没有请求的请求体,所以是在其的queryString中根据参数的名称来获取相应的值。
tring studentId = req.getParameter("studentId");
String studentName = req.getParameter("studentName");
String format = MessageFormat.format("studentId={0},studentName={1}", studentId, studentName);
①如果是通过form表单,即通过application/x-www-form-urlencoded这样的数据格式来传输数据,我们也可以使用getparameter()这个方法来获取数据,code如下:
前端:
Document
后端:
package exer;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
/**
* @author tongchen
* @create 2023-04-01 16:29
*/
@WebServlet("/parameter")
public class GetParameter extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置接收格式
//req.setCharacterEncoding("utf-8");
String studentId = req.getParameter("studentId");
String studentName = req.getParameter("studentName");
String format = MessageFormat.format("studentId={0},studentName={1}", studentId, studentName);
//在控制台打印
System.out.println(format);
//设置返回格式
// resp.setContentType("text/html;charset=utf-8");
//返回数据
resp.getWriter().write(format);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
②使用json的数据格式提交数据,然后使用第三方的jackson库来解析json字符串,其作用原理如下:在接收前端发来的请求时使用objectMapper类将json字符串转化为Java对象,在给前端发送响应时把java对象转化为json字符串发挥数据,具体code如下:
ObjectMapper objectMapper = new ObjectMapper();
Message message = objectMapper.readValue(req.getInputStream(), Message.class);
String s = objectMapper.writeValueAsString(message);
package exer;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-04-02 16:04
*/
@WebServlet("/status")
public class GetStatus extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//首先设置两个数据格式
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//根据不同的type设置编码格式
String type = req.getParameter("type");
System.out.println(type);
if(type.equals("1")){
resp.setStatus(200);
}
if(type.equals("2")){
resp.setStatus(404);
//跳转到tomcat页面
resp.sendError(404);
}
if(type.equals("3")){
resp.setStatus(403);
}
if(type.equals("4")){
resp.setStatus(500);
}
//写回最终数据
resp.getWriter().write(resp.getStatus()+" ");
}
}
package exer;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-04-02 16:37
*/
@WebServlet("/refresh")
public class Refresh extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求数据的编码集
req.setCharacterEncoding("utf-8");
//设置响应数据的格式
resp.setContentType("application/json;charset=utf-8");
//设置编码格式
//测试refresh并通过结果显示变化
resp.setHeader("refresh", "1");
resp.getWriter().write("当前时间为"+System.currentTimeMillis());
}
}
code如下:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*/
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置跳转的目标,
resp.sendRedirect("https://www.baidu.com");
// 跳转之后的代码依然会执行
System.out.println("hello");
System.out.println("hello");
System.out.println("hello");
System.out.println("hello");
System.out.println("hello");
}
}
具体实现请大家看我另一篇博客:
(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
(5)所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中
code如下:
前端:
Document
后端:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-04-05 16:27
*/
@WebServlet("/login")
public class Login extends HttpServlet {
//使用dopost方法测试登录
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
//获取两个变量
String user=req.getParameter("user");
String password=req.getParameter("password");
System.out.println("测试账号密码....." +
user+password);
//判断账号密码的正确情况
if("zhangsan".equals(user)&&"123456".equals(password)){
//
//登录成功,设置cookie并直接跳转
HttpSession session = req.getSession(true);
session.setAttribute("userInfo", user);
//跳转
resp.sendRedirect("index");
}else{
//错误直接将错误写回
resp.getWriter().write("账号密码错误");
}
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-04-05 16:33
*/
@WebServlet("/index")
public class Index extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session
HttpSession session = req.getSession(false);
String name =(String) session.getAttribute("userInfo");
//将name写回
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write(name+"欢迎回来");
}
}
前端代码:
Document
后端代码:
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-04-05 17:31
*/
@WebServlet("/upload")
@MultipartConfig
public class Upload extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取上传上来的文件:
Part uploadFile = req.getPart("uploadFile");
//测试方法
System.out.println(uploadFile.getSubmittedFileName());
System.out.println(uploadFile.getContentType());
System.out.println(uploadFile.getSize());
//存储文件
uploadFile.write("D:/360安全浏览器下载/"+uploadFile.getSubmittedFileName());
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write("文件下载成功");
}
}
结果分析:
这个我后续更新~~~