前段时间看完了javaWeb,打算想综合一下,巩固一下知识,所有上网找了个小项目,并根据自己的感觉进行了一些修改
主要技术:
后端:servlet+filter+mybatis
前端:jsp+css+html
工具:idea+navicat+tomcat
数据库:mysql
界面框架用的就是原本画好,懒得用bootstrap了....
购书系统
实现功能
用户:
- 图书列表
- 搜索图书
- 个人中心
- 购物车
- 结算
- 退出系统
管理员 :
- 新增图书
- 搜索图书
- 图书列表
- Excel批量导入图书
- 退出系统
权限
- 用户只能访问用户功能的范围,当访问其他资源时,提示未授权
- 管理员只能访问管理员功能的范围,当访问其他资源时,提示未授权
最终效果:
登录界面:
用户界面:
管理员页面:
Mybatis
之前用的是jdbc,jdbc操作起来复杂繁琐,而且有很多重复的代码,所以在学了mybatis后,对系统进行了升级从jdbc转为mybatis
首先创建mybatis-config.xml配置好数据库驱动
接着创建两个mapper接口,一个是UserMapper,另一个是BookMapper
在UserMapper.xml和BookMapper.xml文件写入sql语句
再写个工具类,能够获得SqlSession
最后再servlet中,通过工具类获得SqlSession后,创建对应得Mapper对象,使用对应的方法即可
SqlSession sqlSession = GetSqlSession.getSqlSession();
xxxMapper xxxMapper = sqlSession.getMapper(xxxMapper.class);//创建对应的Mapper对象
bookMapper.xxxx//使用对应的方法
myabtis只是刚刚入门,但是用的过程中发现比JDBC好用不少,少写了好多代码
在使用的过程中,遇到了一个问题,就是查询成功了,但返回的结果是空,其原因是我java实体类对象的属性没有与数据库的字段名相对应,所以出现了返回结果是空的现象
总结就是:
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功
实体类的属性名必须与数据的字段名一致,或者实体类的属性名必须与别名一致
如果使用select * 来查询的 那么实体类中的属性必须和数据表中对应的字段一模一样,如果使用select 字段名 as 别名来查询的 ,那么实体类中的属性必须和你取的别名对应
监听器
本系统加入了监听器,实现对在线人数的实时登记和显示,目前有个问题就是只有再退出系统时人数才会减一,关闭浏览器就没法减一,后续再想办法完善
首先在servletcontext里加入一个count属性,初始化为0,因为servletcontext是在服务器启动时就初始化,服务器关闭才会被销毁,所以把计数存在servletcontext中,能够很方便的实现计数,接着在session的attributeAdded方法中,每当session增加一个属性时,计数器加一,在这个系统中,只有在登录成功时,会把user添加到session中,所以就不必担心其他属性的添加对计数器造成影响,在 attributeRemoved方法中,当把session中的user属性删除时,session就会减一。
@WebListener()
public class MyListener implements ServletContextListener,
HttpSessionListener, HttpSessionAttributeListener {
ServletContext servletContext = null;
// Public constructor is required by servlet spec
public MyListener() {
}
// -------------------------------------------------------
// ServletContextListener implementation
// -------------------------------------------------------
@Override
public void contextInitialized(ServletContextEvent sce) {
/* This method is called when the servlet context is
initialized(when the Web application is deployed).
You can initialize servlet context related data here.
*/
servletContext = sce.getServletContext();
System.out.println("ServletContext初始化");
int count = 0;
servletContext.setAttribute("count",count );
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
/* This method is invoked when the Servlet Context
(the Web application) is undeployed or
Application Server shuts down.
*/
}
// -------------------------------------------------------
// HttpSessionListener implementation
// -------------------------------------------------------
@Override
public void sessionCreated(HttpSessionEvent se) {
/* Session is created. */
System.out.println("session初始化");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
/* Session is destroyed. */
System.out.println("session销毁");
}
// -------------------------------------------------------
// HttpSessionAttributeListener implementation
// -------------------------------------------------------
@Override
public void attributeAdded(HttpSessionBindingEvent sbe) {
/* This method is called when an attribute
is added to a session.
*/
int count = (int) servletContext.getAttribute("count");
servletContext.setAttribute("count",++count );
System.out.println("session加:"+count);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent sbe) {
/* This method is called when an attribute
is removed from a session.
*/
int count = (int) servletContext.getAttribute("count");
servletContext.setAttribute("count",--count );
System.out.println("session减:"+count);
}
@Override
public void attributeReplaced(HttpSessionBindingEvent sbe) {
/* This method is invoked when an attibute
is replaced in a session.
*/
}
}
在显示效果中,先用jstl中的if判断当前是否有用户登录,有才会显示当前在线人数
最终效果
过滤器
在系统中加入了过滤器进行权限管理,没有登录的话没有权限访问其他页面
效果展示:
因为要对所有的请求进行拦截,所以
@WebFilter(filterName = "AllFilter",urlPatterns = {"/*"})
拦截所有的请求,但有些的请求不能被拦截,比如获取验证码图片的请求,登录页面的请求还有登录后的action=login也得放行,
所以就得对请求进行判断
if("index.jsp".equals(path)||"login".equals(action)||"drawImage".equals(path)){
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
response.setContentType("text/html;charset=utf-8");
return;
}
当接收的是其他的请求,就先进行判断是否有用户存在,如果有用户,则说明已经登录可以放行,如果没有,则不允许放行,转发到登录界面
//如果没有用户说明无权限不给放行
User user = (User) request.getSession().getAttribute("user");
if(user != null){
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
response.setContentType("text/html;charset=utf-8");
}else{
request.setAttribute("message","无权限操作,请先登录!" );
request.getRequestDispatcher("/index.jsp").forward(request,response );
}
}
这次新用到了 commons-fileload.jar和jxl.jar两个jar包来进行文件的上传和对excel文件的读取,有时间会对从这两个jar包中所学到的进行记录
本次项目是参照:RealJava 可以加群获得源代码,个人感觉写的都很好
我自己的源代码在:GitHub