Java Web 入门项目 | 二手车交易平台(保姆级指导)

一、需求分析

本项目实现的功能是一个网上二手车交易平台,主要围绕二手车的交易进行开发。
在该系统,分为两个角色,一个是普通用户角色,即会员,另一个角色是管理员用户,两个角色分别有不同的权限。具体如下:
普通用户(会员):

  1. 注册、登录
  2. 个人信息的查询
  3. 个人信息及密码修改
  4. 二手车的添加、修改、发布、删除
  5. 查询并维护自己的出售信息并支持留言、同时支持对其他人的留言进行回复
  6. 查看平台所有二手车信息并进行留言
  7. 支持禁止他人对自己发布的车辆留言

管理员用户:

  1. 登录
  2. 个人信息及密码的修改
  3. 车辆管理:能查看平台所有车辆,并进行留言操作、屏蔽操作
  4. 会员管理:支持修改、删除会员的信息
  5. 查询所有会员信息(支持模糊查询)
  6. 可取消会员资格(使之可正常登录但无法浏览网站信息)

二、使用的技术

本系统是基于 MVC 模式搭建的,使用的技术包括

Servlet
JSP
JDBC
EL 表达式
JSTL
Filter 过滤器

三、系统的结构层次

本系统的代码结构逻辑清晰,具体的实现分为Web层(表示层)、业务层、数据访问层,利用MVC架构将JSP、Servlet、JavaBean分层操作并联系起来,形成一种弱耦合关系,在后期对系统的维护上少了很多麻烦,例如要增加一个功能,只需在Servlet进行逻辑的控制,并调用Service业务服务层的代码,业务层就去调用数据访问层的具体逻辑实现,完成对数据库项的增加操作,实现数据的持久化,在Servlet控制层里,只需完成2件事,一件是调用业务逻辑层的实现方法,另一件事是将相关属性放在request中,并转发给其他JSP页面去做显示或输入处理。代码逻辑条理十分清晰,具体的代码结构如下:
在这里插入图片描述在这里插入图片描述
不同层次的实现放在不同的 package 中,将代码模块化,方便维护。
其中:

com.bean:主要放实体类
com.controller:主要放Servlet
com.dao:主要放接口
com.daoImpl:主要放接口的实现类
com.filter:主要放filter过滤器
com.service:主要是业务逻辑的实现
com.utils:主要放工具类(对数据库的连接和资源释放)

MVC 模式的逻辑图如下:
MVC模式逻辑图
其中,JSP页面即MVC模式中的V(view),Servlet为MVC中的C(Controller),然后Service、Dao、MySql组成MVC中的M(model),每个层次每个模块的功能如下:
1. JSP:
(1)呈现数据:从request中获取Servlet放入的属性
(2)接收用户的输入
(3)编写前端页面显示代码给出对于的提示,参与用户交互

2. Servlet:
(1)获取请求信息:获取请求参数
(2)验证请求参数的合法性:验证失败需要返回页面,并给出提示
(3)把请求参数封装为一个JavaBean
(4)调用业务逻辑方法获取返回的结果
(5)把返回的结果放入request中
(6)响应页面:转发、重定向

3. Service:
(1)实现业务逻辑
(2)返回结果

4. Dao:
(1)执行增删改查操作(CRUD)
(2)返回结果

5. MySql:
(1)存储数据,对数据进行持久化操作

四、系统部分功能和逻辑分析

1. MySQL 数据库

该系统包含两个数据表,一个是 user 表,一个是 car 表。它们分别包含的属性如下
(1)user表

id:用户 id 号(主键)
name:用户登录名称
pwd:用户登录密码
limit:该用户的受限情况(int)
isadmin:该用户是否是管理员(int)

(2)car表

userid:用户 id 号(主键,同时是 user 表的 userid 属性的外键)
carid:二手车 id 号
brand:车辆品牌
model:车辆型号
price:车辆价格
color:车辆颜色
dateposted:发布日期(timestamp)
isrelease:发布状态(int)
canmessage:是否支持用户留言(int)
carcomment:留言板(text)
isfake:是否是虚假消息(该属性的操作属于管理员权限)(int)

2. Servlet 控制器部分

其中控制器,即 MVC 模式中的 C(Controller),我通过使用通配符,对Servlet进行配置,然后在doGet()方法利用反射机制分辨从JSP传过来的请求,并映射到相应的Servlet中。通过使用这一方法,可以将同一类型的Servlet放在一个.java文件中,不需要每个servlet写一个java文件进行配置。
在这里插入图片描述
其中
CarServlet 配置为:@WebServlet(".car")
UserServlet配置为:@WebServlet("
.do")

通过.do或.car将车辆管理和用户管理这两个业务分离开,这样处理业务就变得非常方便,这一做法,可以让在编码过程中思路逻辑变得更加的清晰。而且采取上面所说的结构,在编码过程中遇到报错能更快的定位到bug,并进行更正。

3. JSP 视图部分

系统采取的JSP显示界面也进行了分类管理(结构如下图),使编程思路更加清晰。
在这里插入图片描述
这里关键的一点是登录页面,即首页,要放在WebContent下面,不能放在WEB-INF下面,因为WEB-INF属于保护目录,不能直接被访问,本项目的登录页面 login.jsp 放在 WebContent 下,并在 web.xml 配置为首页,如下图所示:
在这里插入图片描述
如果需要访问 WEB-INF 下的 jsp 文件,需要通过servlet转发,才能实现访问操作。这同时也能保证系统的安全性,保证用户权限得到有效的管理。

同时为保证系统代码结构各个层次各司其职,在JSP页面没有多余的Java代码,业务逻辑执行操作都在其他层次完成。

本系统在界面的显示上,虽然没有加入太多的样式使界面更加高级,但基本保证了界面的可读性和用户交互性。

4. Filter过滤器

Filter是一个实现了Filter接口的Java类,与Servlet相似,它由Servlet容器进行调用和执行,Filter需要在web.xml文件中进行注册和设置它所能拦截的资源。在注册之后,该Filter就可以对Servlet容器发送给Servlet程序的请求Servlet程序回送给Servlet容器的响应进行拦截,可以决定是否将请求继续传递给Servlet程序,以及对请求和响应信息是否进行修改。
该系统利用了Filter过滤器对Servlet容器调用Servlet的过程进行拦截,进行编码的转换,从而在Servlet进行响应处理的前后保证了编码的统一,统一为utf-8格式,如下图:
在这里插入图片描述
同时需要在web.xml进行配置,如下图:
在这里插入图片描述

5. EL表达式 和JSTL

在JSP页面获取request中的数据时并没有出现JAVA代码,而是采用EL表达式获取值,实现0 Java代码。让JSP页面的功能更加纯粹。利用点访问符访问对象的属性。
本系统采用JSTL与EL表达式结合使用,其中JSTL需要导入相应的jar包,并在JSP页面导入标签库

<%@ taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c”%>

本系统使用到的主要有 c:if、c:foreach 标签。

6. 弱耦合逻辑结构关联方式

其中的层层调用,除了类对象调用方法实现层层调用外,还有就是通过转发将数据放在request域内,在jsp页面可以通过requestScope去取到数据,在Servlet也可以接收jsp页面传过来的数据,通过request.getParameter( )可以获取。

7. 接口设计

该系统还有一个比较好的一点就是在对业务逻辑进行处理时,利用接口,然后再在接口的实现类进行操作。面向接口编程可以增加复用性和通用性。
在这里插入图片描述

其中
Dao和DaoImpl分别是通用接口和通用接口的实现类,
CarDao和CarDaoImpl是二手车车辆管理的接口和实现类
UserDao和UserDaoImpl是用户管理(包括管理员及普通用户)的接口和实现类

为了使接口更具通用性,这里采用了“泛型”,代码如下图:
在这里插入图片描述

8. 数据库操作和JDBC

使用JDBC可以直接访问数据库,JDBC是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源。JDBC为访问不同的数据库提供了一种统一的途径,方便开发(本系统采用的是MySql数据库)。
JDBC API 是一系列的接口,使应用程序能够进行数据库连接,执行SQL语句,并且得到返回结果。

基本的流程是:
(1)在Driver Manager中注册
(2)获取连接(Connection)
(3)调用相应的方法做增删改查
(4)获取处理结果数据

下面对这几个基本过程进行解析:
<1>注册
调用Class类的静态方法forName(),向其传递要加载的JDBC驱动的类名,代码如下:

String driverClass="com.mysql.cj.jdbc.Driver";
Class.forName(driverClass);

<2>建立连接
调用DriverManager类的getConnection()方法建立到数据库的连接。JDBC URL标识一个被注册的驱动程序,从而建立到数据库的连接。通俗来说,就是JDBC URL说明要连接数据库管理系统中的哪个数据库。代码如下:

String jdbcUrl="jdbc:mysql://localhost:3306/SecondCarTrade?serverTimezone=Hongkong";
Connection connection=DriverManager.getConnection(jdbcUrl, user, password);

<3>调用方法实现数据库永久化操作
调用数据库有3种方式,分别为:

Statement
PreparedStatement
CallableStatement

该系统使用的是PreparedStatement。
因为考虑到如果使用Statement的话,获取sql语句是通过字符串拼接的方式,所以就必须得考虑到它的拼写规则,并且得时刻注意不能和关键字和特殊字符进行冲突,这对编码来说不方便,且容易出错。
而PreparedStatement优势就比较凸显,使用PreparedStatement可以进行预编译,提高性能,同时还可以防止SQL注入,对sql语句也不需要进行字符串拼接,直接写sql语句就可以调用执行方法操作数据库。对于语句中的属性值,可以通过“?”作为占位符,可以传入参数。
以添加用户来举例,参数传递过来user对象,在方法内部获取user对象的所需的相应属性,通过问号占位符填入sql语句,然后调用update方法操作数据库,代码结构如下:
在这里插入图片描述

<4>获取返回数据
将对数据库操作的结果通过List或者ResultSet的方式返回,以“获取所有用户所有车辆”方法举例,代码如下:
在这里插入图片描述

五、代码解析和功能演示

下面对具体的逻辑结构和具体实现代码进行解析,JSP页面的显示代码就不一一演示了,具体查看源代码去看就行了,注释都写得很清晰。
首先从登录页面 login.jsp 启动,登录时会根据用户类型和账号密码进行身份验证:

//登录
	public void LoginUserServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
		//得到jsp页面传过来的参数
				//(因为在同个request域中,所以可以用request获取其数据)
				String name=request.getParameter("name");
				String pwd=request.getParameter("pwd");
				int userType=Integer.parseInt(request.getParameter("userType"));// 会员0 /管理员1
				
				
				System.out.println("userType="+userType);
				/*这里id不能直接request.getParameter获取,因为在用户登录的时候没有填id,所以jsp页面没有传"id"信息过来,这里获取不到的*/
				int id=service.LoginFindId(name, pwd);//根据name和pwd查找id
				UserDao ud =new UserDaoImpl();//创建接口的实现类,ud对象可以操作UserDaoImpl类内容
				System.out.println("id="+id);	
				
				//service.LimitUser(id)执行成功,返回true,则该用户变为受限
				//service.isLimit(id)返回true,则该用户变为受限
				//userType==0  会员
				if(service.login(name, pwd) && (!service.isLimit(id)) && (userType==0) && !service.isAdmin(id)) {
   //如果登录通过,并且不受限
					//request.setAttribute("xiaoxi", "welcom "+name);//向request域中放置信息
					System.out.println("(会员)登录成功");
					String message="个人会员 登录成功";
					
					//注:个人用户登录成功,将他的id放在request域中,在jsp页面可以获取,然后通过jsp可以再把该id信息转到其他servlet中(比如下面的SearchUserSelfById() )
					request.setAttribute("id", id);//设置id到request域,在每个个人用户登录后分别显示他个人的信息(通过这个id去获取)
					request.setAttribute("message", message);
					//转发到个人用户主页UserHomePage.jsp
					request.getRequestDispatcher("/WEB-INF/user/UserHomePage.jsp").forward(request, response);//转发到成功页面
				}
				//userType==1  管理员
				else if(service.login(name, pwd) && (!service.isLimit(id)) && (userType==1) && service.isAdmin(id)) {
   //如果登录通过,并且不受限
					//request.setAttribute("xiaoxi", "welcom "+name);//向request域中放置信息
					System.out.println("(管理员)登录成功");
					String message="管理员登录成功";
					request.setAttribute("message", message);
					request.getRequestDispatcher("/WEB-INF/admin/AdminHomePage.jsp").forward(request, response);//转发到成功页面
				}
				//个人用户(受限用户)
				else if(service.login(name, pwd) && service.isLimit(id) && (userType==0) && !service.isAdmin(id)){
   //登录成功,但受限
					System.out.println("登录成功,但您的会员资格受限,无法访问汽车信息");
					String message="登录成功,但您的会员资格受限,无法访问汽车信息";
					request.setAttribute("ERRMESSAGE", message);
					request.getRequestDispatcher("/WEB-INF/admin/LimitedUser.jsp").forward(request, response);//转发到成功页面
				
				}
				//共用
				else {
   //登录不通过,重定向到失败界面(respnse 响应)
					System.out.println("登录失败,请确认账号密码以及身份是否正确");
					String message="登录失败,请确认账号密码以及身份是否正确";
					request.setAttribute("message", message);
					//response.sendRedirect("/WEB-INF/view/Fail.jsp"); 重定向不在一个request里面
					request.getRequestDispatcher("/WEB-INF/view/LoginFail.jsp").forward(request, response);//转发到失败页面
				}
	}

登录成功会跳转到个人用户主页,如下图:
个人用户主页
下面演示”显示个人信息“:

	/*根据个人id查询个人信息(个人用户)*/
	public void SearchUserSelfById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
	
		int id=Integer.parseInt(request.getParameter("id"));//从jsp页面传过来,用getParameter

		request.setAttribute("id", id);//把id放在request域中,然后在ShowUserInfoSelf可以获取到,显示用
		User user=service.getUser(id);
		
		/*转发提交到request,到相应jsp页面显示*/
		request.setAttribute("user", user);	/*将取出来的user对象保存在request域里面*/
		
		String message="个人信息查询成功";
		request.setAttribute("message", message);
		request.getRequestDispatcher("/WEB-INF/user/ShowUserInfoSelf.jsp").forward(request, response);
		
	}

在这里插入图片描述
我们可以对个人信息进行更新:

	//个人用户修改信息触发界面(跳转到修改的界面)
	public void editUserSelfInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
		int id=Integer.parseInt(request.getParameter("id"));
		User user=service.getUser(id);
		
		/*转发提交到request,到相应jsp页面显示*/
		request.setAttribute("user", user);	/*将取出来的user对象保存在request域里面*/
		request.getRequestDispatcher("/WEB-INF/update/UpdateUserInfoSelf.jsp").forward(request, response);//转发到jsp页面显示
	}

在这里插入图片描述
修改完成后提交,完成数据库持久化操作,如下:

	//个人用户信息修改成功后回到这里
	public void UpdateUserInfoSelfServlet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   	
		/*获取从 Update.jsp 页面输入的信息(用户修改后的信息)*/
		System.out.println("进入 UpdateUserInfoSelfServlet ");
		int id=Integer.parseInt(request.getParameter("id"));//从jsp页面传过来,用getParameter
		
		String name=request.getParameter("name");
		String pwd=request.getParameter("pwd");
		String sex=request.getParameter("sex");
		System.out.println("name="+name+"  pwd="+pwd+"  sex="+sex);
	
		User user=new User(id,name,pwd,sex,0,0);//User类必须有个带参构造方法(因为这是在个人信息修改的方法里,所以直接把limit和isAdmin默认0)
		service.UpdateUserServlet(user);//Userservice的同名方法
		System.out.println("update successfully");
		String message="个人信息修改成功";
		request.setAttribute("message", message);
		
		//修改成功回到显示个人信息的界面
		request.setAttribute("user",user);//传回ShowUserInfoSelf.jsp,不然那边无法显示更新后的信息
		request.getRequestDispatcher("/WEB-INF/user/ShowUserInfoSelf.jsp").forward(request, response);
		
	}

下面进行”二手车管理首页“进行二手车的相关操作:

	//二手车辆管理首页
	public void CarsManageHomePageServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
		List<Car> cars=new ArrayList<Car>();
		int userid=Integer.parseInt(request.getParameter("userid"));//这里是userid,不是id
		
		User user = serviceOfUser.getUser(userid);//根据jsp传过来的用户id,定位到用户
		cars=serviceOfCar.getCarsListOfUserid(userid);//根据userid获取到
		//String message="-------二手车管理首页---------";
		request.setAttribute("user", user);//放在request,到CarsManageHomePage.jsp可以取出来用
		request.setAttribute("cars", cars);
		request.setAttribute("userid", userid);//单独传userid过去,因为CarsManageHomePageServlet不仅连接user,又连接对car的一系列操作
		//request.setAttribute("message", message);
		request.getRequestDispatcher("/WEB-INF/car/CarsManageHomePage.jsp").forward(request, response);
		
	}

来到了二手车管理首页
在这里插入图片描述
下面一一进行演示
添加二手车:

	//添加车辆 触发界面(编辑界面)
	public void AddCarPageServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
		
		/*实现*/
		int userid=Integer.parseInt(request.getParameter("userid"));//通过 " ?userid " 传过来了
		System.out.println("AddCarServlet()---userid="+userid);
	
		User user = serviceOfUser.getUser(userid);//根据jsp传过来的用户id,定位到用户
		
		

		/*转发*/
		String message="添加车辆页面";		
		request.setAttribute("user", user);//user放在这个request里
		/*将消息message转到一个jsp页面success.jsp,在页面打印一个“成功”消息*/
		request.setAttribute("message", message);
		request.getRequestDispatcher("/WEB-INF/add/AddCarPage.jsp").forward(request, response);

	}

在AddCarPage.jsp页面进行车辆信息的添加后,来到AddCarServlet

//添加车辆
	//获取添加界面的信息
	public void AddCarServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
		/*实现*/
		int userid=Integer.parseInt(request
  • 34
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值