目录
主要实现的功能
用户登录,查询文章列表,获取文章详情,新增文章、修改文章、删除文章。
使用的主要技术
- Maven:使用Maven来管理依赖,打包Web项目。
- Tomcat:Tomcat作为Web项目部署的服务器。
- Servlet:每一个页面的请求对应一个Servlet来实现业务。
- MySql: 使用Mysql来存储数据——用户信息及对应的文章信息。
- jackson框架:使用jackson框架来进行Java对象和JSON字符串的序列化和反序列化操作。
- Filter:实现对用户会话的统一管理。
- 富文本编辑器:实现博客文章的展示,图片上传。
- HTML、JavaScript:使用html和JavaScript结合实现前端页面,其中使用到了jquery框架以及其中的Ajax异步请求实现对页面的更新。
- Java Server Pages:使用这种动态网页技术,通过html和Java代码的结合,动态显示网页。
- 使用模板模式进行统一数据类型的设置,统一进行异常的处理,前后端统一数据封装。
项目流程
创建Web项目
- 创建Maven项目
- 配置pom.xml文件,配置的内容包括<packaging>war</packaging>,jdk版本,dependencies依赖等
- 准备web资源文件夹:webapp/WEB-INF/web.xml
- 把项目部署到tomcat
- 验证配置,执行packaging命令,查看是否能够打出war包
数据库中数据表的设计
设计数据库的实体类
将数据库中的两个数据表,分别设计成实体类。
- 用户类,对应数据库中的用户表
- 文章类,对应数据库中的文章表
连接数据库
连接数据库使用JDBC编程的知识,设计一个DBUtil工具类,使用DataSource作为数据库连接的方式,并进行统一释放JDBC资源。
设计模板方法
要实现上面的每一个功能,每一个请求发来,都要进行请求的解析,以及最终返回响应。
为了实现代码的复用,所以设计一个AbstractBaseServlet类,来处理重复操作的事情,具体的Servlet代码只需要继承该类,并重写自己的业务逻辑代码即可。
/**
* ClassName org.example.servlet
* Description TODO 定义模板方法 ,父类定义好逻辑,定义好子类可以重写的方法,可以实现代码的复用
* 解析请求和响应都是由该父类来完成的,其他的每一个Servlet子类都只是重写了该类的process方法,主要的执行逻辑,因为每一个Servlet都要进行请求的解析,并进行响应的包装
*/
//使用抽象类,抽象的统一的基类;
//自己的子类只需要继承AbstractBaseServlet 就可以了
public abstract class AbstractBaseServlet extends HttpServlet {
//HttpServlet中有doGet和doPost方法
//我们实现自己的,重写doGet和doPost方法
@Override
//protected 子类可以使用
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");//设置请求体的编码格式
resp.setCharacterEncoding("UTF-8");//设置响应体的编码
resp.setContentType("application/json");//设置响应体的数据类型,浏览器要根据什么方式执行
//resp.setContentType("text/html");
JSONResponse json = new JSONResponse();//返回给前端一个约定好的json格式
try{
//调用子类重写方法
Object data = process(req,resp);
//子类的process方法执行完没有抛异常,表示业务成功
json.setSuccess(true);//业务成功,只需要返回true和对应的data
json.setData(data);
}catch (Exception e) {
//异常处理;JDBC异常(SQLException),JSON处理的异常(序列化和反序列化异常)
e.printStackTrace();//打印异常
// 自定义异常返回错误消息
//json.setSuccess(false)不需要设置,new的时候就是false
String code = "UNKNOWN";
String s = "未知错误";
if(e instanceof AppException) {
code = ((AppException) e).getCode();
s = e.getMessage();
}
json.setCode(code);//设置code和message
json.setMessage(s);
}
PrintWriter pw = resp.getWriter();
//把pw对象序列化成json字符串
pw.println(JSONUtil.serialize(json));//json字符串序列化打印出来
pw.flush();
pw.close();
}
//每一个Servlet执行的process的内容是不一样的,让子类重写process方法
protected abstract Object process(HttpServletRequest req, HttpServletResponse resp) throws Exception;
}
除了这个模板方法以外,还设计了统一的数据格式,先将所有的响应都以一个JSON字符串的格式(将字符串的格式进行统一)进行返回,然后再通过解析JSON字符串来进行相应的页面渲染操作。
主要功能实现
登录
使用Filter进行会话管理,在用户没有登录之前会返回一个json的字符串,显示没有登录,不允许进行访问。【json字符串的格式在Servlet中设定了一个统一的标准】
登录界面的实现:
在浏览器中输入URL,浏览器将URL包装成对应的html的请求,服务端通过解析http请求将对应的内容以相应的格式进行返回。
由于在html页面中插入了js的代码,前端的js中使用ajax请求,在html页面加载完毕之后会带着前端的内容作为请求的数据再次发起请求。
服务端进行请求的解析,返回响应数据为json格式的响应体,浏览器接收到响应之后,再解析响应体动态设置网页的内容或者是触发另一个事件。
点击登录之后,发送的Ajax请求中的请求的服务路径是../login,通过这个服务路径再去寻找对应的Servlet代码进行处理
通过解析请求中的username和password,去数据库中寻找对应的用户,如果查找到用户,登录成功,创建session会话,后面的操作都是基于目前的这个用户来进行的。
解析之后,返回统一的json格式的字符串,通过app.js代码中解析响应的json字符串。
在上面的js代码中,如果解析的结果是success,证明用户登录成功,就会跳转到对应articleList.jsp 这个页面,直接显示出该用户的文章列表。
接下来,就可以实现 查询文章列表,获取文章详情,新增文章、修改文章、删除文章操作。
查询文章列表
前端请求的URL为:http://localhost:8080/sblog/jsp/articleList.jsp ,通过URL查找对应的资源(包括静态资源和Servlet)
通过URL进行查找的过程:IP对应主机地址,端口号对应进程,应用上下文路径对应项目,URI对应项目中的资源
ArticleListServlet后端解析:
- 获取登录时创建的session保存的用户信息
- 根据用户id获取文章列表
获取登录时候创建的session保存的用户信息,通过用户的id使用JDBC操作来获取用户对应的文章信息,返回一个用户的列表。
如果操作成功,给前端ajax success 方法使用,解析响应json数据,渲染网页内容,最终就会得到我们现在看到的网页的界面。
获取文章详情
获取某一个文章的文章详情,请求的服务路径是 /articleDetail
ArticleDetailServlet进行后端解析:
- 解析请求得到文章id
- 通过文章的id,使用query()方法的得到文章的内容
新增文章
在文章列表的页面,点击“发表新文章”,就会跳转到如下的界面:
点击提交按钮之后,才会请求到ArticleAddServlet。
ArticleAddServlet进行后端解析:
- 从session中获取用户信息
- 将请求的数据使用输入流进行获取
- 获取之后使用反序列化操作,将输入流的数据反序列化为Article对象
- 设置用户的id(将这篇文章,指定给对应的用户)
- 使用ArticleDAO中数据库的操作,将Article对象插入到数据库中
修改文章
修改文章的操作,首先选中要删除的文章,选中之后按钮的状态会被重置,只选中一条文章才能进行修改。
点击“修改”按钮之后,会触发一个事件进行页面的跳转:跳转到当前文章的详情页面
将文章的内容进行修改之后点击“提交”按钮,就会发起请求,相当于带着已经更改的数据去请求ArticleUpdateServlet
ArticleUpdateServlet进行后端解析:
- 请求的数据是json格式的,使用输入流进行获取
- 反序列化成Java对象——Article对象
- update操作,更改文章的内容
删除文章
在前端页面选中对应要删除的文章,点击删除按钮,在弹出窗确认之后调用删除接口
ArticleDeleteServlet解析:
- 解析请求得到文章id
- 根据文章id,通过JDBC操作,删除对应的文章内容
Filter过滤器:通过过滤器机制,分发请求到对应的Servlet
实现Filter接口:
- init() :进行一次初始化
- destory():进行一次销毁
- doFilter():每一次请求被调用一次
配置过滤器对哪些URL生效:
-
web.xml中进行配置
-
@WebFilter("/*"):配置用户统一会话管理的过滤器,会匹配所有的请求路径,所有的Servlet都先要经过Filter
每一次http请求匹配到过滤器路径时,会执行该过滤器的doFilter:
- 如果往下执行,就调用filterChain.doFilter(request,response)
- 否则就自行进行处理
总结
服务端解析请求数据
-
queryString:写在url中的请求数据
-
表单数据类型:x-www-form-urlencoed
-
请求数据Content-Type:application/json
通过request.getInputStream获取请求体,数据作为输入流获取
-
再通过json框架反序列化为一个Java对象。请求数据和对象属性要一致,否则就会报错
服务端响应数据
-
都返回的application/json 数据类型
Servlet 代码逻辑
-
获取请求数据
-
如果请求数据类型为application/json ,反序列化为Java对象
-
执行业务操作,包括数据库的CRUD
-
返回响应数据:返回一个Java对象,使用该对象序列化为json字符串,然后返回
文章相关的后端接口
- 都是需要登录状态才能进行操作;
- 返回内容都是JSON格式;
- 请求和响应的数据载体都是JSON格式;
- 有统一的API标准。