深圳航空公司官方网站招聘,seo公司中国,前端转网站建设,手机网站 返回顶部一、项目开发流程 程序框架图 项目具体分层方案 MVC
1、说明是MVC
MVC全称: Mode模型、View视图、Controller控制器。
MVC最早出现在JavaEE三层中的Web层#xff0c;它可以有效的指导WEB层的代码如何有效分离#xff0c;单独工作。
View视图:只负责数据和界面的显示…一、项目开发流程 程序框架图 项目具体分层方案 MVC
1、说明是MVC
MVC全称: Mode模型、View视图、Controller控制器。
MVC最早出现在JavaEE三层中的Web层它可以有效的指导WEB层的代码如何有效分离单独工作。
View视图:只负责数据和界面的显示不接受任何与显示数据无关的代码便于程序员和美工的分工(Vue/JSP/Thymeleaf/HTML)
Controller控制器:只负责接收请求调用业务层的代码处理请求然后派发页面是一个调度者的角色(Servlet)
Model模型:将与业务逻辑相关的数据封装为具体的JavaBean类其中不掺杂任何与数据处理相关的代码(JavaBean/Domain/Pojo)
2、MVC是一种思想
MVC的理念是将软件代码拆分成为组件单独开发组合使用(目的还是为了解耦合) ,也有很多落地的框架比如SpringMVC 二、实现1 正确加载静态页面 前端人员给的静态页面 三、实现功能02 会员注册前端JS校验
1.验证用户名:必须字母数字下划线组成并且长度为6到10位 JQuery 正则表达式
2.验证密码:必须由字母数字下划线组成并且长度为6到10位
3.邮箱格式验证:常规验证即可
4.验证码:后面实现 script typetext/javascript src ../../script/jquery-3.6.0.min.js/scriptscript$(function () {//页面加载完成后执行function//绑定点击事件$(#sub-btn).click(function (){//获取输入的用户名 自己看前端给的页面var $userName $(#username).val();// alert(usernameVal $userName)//使用正则表达式进行验证var usernamePattern /^\w{6,10}$/;if(!usernamePattern.test($userName)){//查看前端给的代码是否有错误提示信息// span classerrorMsg// stylefloat: right; font-weight: bold; font-size: 20pt; margin-left: 10px;/span//jquery的属性过滤器$(span[class errorMsg]).text(用户格式不对 需要6-10字符);return false;//不提交 需要返回false 不返回false会导致页面跳转}var password $(#password).val();var passwordPattern /^\w{6,10}$/;if(!passwordPattern.test(password)){//jquery的基本过滤器$(span.errorMsg).text(密码格式不对 需要6-10字符);return false;}//验证两次密码是否正确var repwd $(#repwd).val();if(repwd ! password){$(span.errorMsg).text(输入的两次密码不同);return false;}var email $(#email).val();var emailPattern /^[\w-]([a-zA-Z]\.)[a-zA-Z]$/;if(!emailPattern.test(email)){$(span[class errorMsg]).text(电子邮件格式不对);return false;}//到这里就全部过关 我们暂时不提交$(span.errorMsg).text(验证通过);return false;})})/script 四、实现功能03 - 会员注册后端 导入mhl使用的BasicDAO以及JDBCbyDruid 测试是否成功
BasicDAO
package com.yinhai.furns.dao;import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;/*** author 韩顺平* version 1.0* 开发BasicDAO , 是其他DAO的父类*/
public class BasicDAOT { //泛型指定具体类型private QueryRunner qr new QueryRunner();//开发通用的dml方法, 针对任意的表public int update(String sql, Object... parameters) {Connection connection null;try {//这里从数据库连接池获取connection//老师说明: 每次从连接池中取出Connection , 不能保证是同一个//1.我们目前已经是从当前线程关联的ThreadLocal获取的connection//2.所以我们可以保证是同一个连接(在同一个线程/同一个请求)connection JDBCUtilsByDruid.getConnection();int update qr.update(connection, sql, parameters);return update;} catch (SQLException e) {throw new RuntimeException(e); //将编译异常-运行异常 ,抛出}}//返回多个对象(即查询的结果是多行), 针对任意表/**** param sql sql 语句可以有 ?* param clazz 传入一个类的Class对象 比如 Actor.class* param parameters 传入 ? 的具体的值可以是多个* return 根据Actor.class 返回对应的 ArrayList 集合*/public ListT queryMulti(String sql, ClassT clazz, Object... parameters) {Connection connection null;try {connection JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanListHandlerT(clazz), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常-运行异常 ,抛出}}//查询单行结果 的通用方法public T querySingle(String sql, ClassT clazz, Object... parameters) {Connection connection null;try {connection JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanHandlerT(clazz), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常-运行异常 ,抛出}}//查询单行单列的方法,即返回单值的方法public Object queryScalar(String sql, Object... parameters) {Connection connection null;try {connection JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new ScalarHandler(), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常-运行异常 ,抛出} }}JDBC工具类
package com.yinhai.furns.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** author 韩顺平* version 1.0* 基于druid数据库连接池的工具类*/
public class JDBCUtilsByDruid {private static DataSource ds;//定义属性ThreadLocal, 这里存放一个Connectionprivate static ThreadLocalConnection threadLocalConn new ThreadLocal();//在静态代码块完成 ds初始化static {Properties properties new Properties();try {//因为我们是web项目他的工作目录在out, 文件的加载需要使用类加载器//找到我们的工作目录properties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream(druid.properties));//properties.load(new FileInputStream(src\\druid.properties));ds DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}//编写getConnection方法//public static Connection getConnection() throws SQLException {// return ds.getConnection();//}/*** 从ThreadLocal获取connection, 从而保证在同一个线程中* 获取的是同一个Connection* return* throws SQLException*/public static Connection getConnection() {Connection connection threadLocalConn.get();if (connection null) {//说明当前的threadLocalConn没有连接//就从数据库连接池中,取出一个连接放入, threadLocalConntry {connection ds.getConnection();//将连接设置为手动提交, 即不要自动提交connection.setAutoCommit(false);} catch (SQLException throwables) {throwables.printStackTrace();}threadLocalConn.set(connection);}return connection;}/*** 提交事务, java基础 mysql事务线程过滤器机制ThreadLocal*/public static void commit() {Connection connection threadLocalConn.get();if(connection ! null) {//确保该连接是有效try {connection.commit();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();//关闭连接} catch (SQLException throwables) {throwables.printStackTrace();}}}//老师说明//1. 当提交后需要把connection从 threadLocalConn 清除掉//2. 不然会造成 threadLocalConn 长时间持有该连接, 会影响效率//3. 也因为我们Tomcat底层使用的是线程池技术threadLocalConn.remove();}/*** 老师说明: 所谓回滚是回滚/撤销和 connection管理的操作删掉修改添加*/public static void rollback() {Connection connection threadLocalConn.get();if(connection ! null) {//保证当前的连接是有效try {connection.rollback();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}threadLocalConn.remove();}//关闭连接, 老师再次强调 在数据库连接池技术中close 不是真的断掉连接//而是把使用的Connection对象放回连接池public static void close(ResultSet resultSet, Statement statement, Connection connection) {try {if (resultSet ! null) {resultSet.close();}if (statement ! null) {statement.close();}if (connection ! null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}
}实现Member的功能 查询等
一个规范接口
package com.yinhai.furns.dao;import com.yinhai.furns.javabean.Member;/*** author 银小海* version 1.0* email yinhai14qq.com*/
public interface MemberDAO {//小伙伴要自己分析需要哪些方法//提供一个通过用户名返回对应的Memberpublic Member queryMemberByUsername(String username);//提供一个保存Member对象到数据库/表member表public int saveMember(Member member);/*** 根据用户名和密码返回Member* param username 用户名* param password 密码* return 返回的对象如果不存在返回null**/public Member queryMemberByUsernameAndPassword(String username, String password);
}实现Member的功能 查询 添加等
package com.yinhai.furns.dao.impl;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.dao.MemberDAO;import com.yinhai.furns.javabean.Member;/*** author 银小海* version 1.0* email yinhai14qq.com*/
public class MemberDAOImpl extends BasicDAOMember implements MemberDAO {/*** 通过用户名返回对应的Member** param username 用户名* return 对应的Member, 如果没有该Member, 返回 null*/Overridepublic Member queryMemberByUsername(String username) {//老师提示sql 先在sqlyog 测试然后再拿到程序中//这里可以提高我们的开发效率减少不必要的bugString sql SELECT id,username,password,email FROM member\n WHERE username ?;return querySingle(sql, Member.class, username);}/*** 保存一个会员** param member 传入Member对象* return 返回-1 就是失败返回其它的数字就是受影响的行数*/Overridepublic int saveMember(Member member) {String sql INSERT INTO member(username,password,email) VALUES(?,MD5(?), ?);return update(sql, member.getUsername(),member.getPassword(), member.getEmail());}Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql SELECT id,username,password,email FROM member WHERE username? and passwordmd5(?);return querySingle(sql, Member.class, username, password);}}测试
package com.yinhai.furns.test;import com.yinhai.furns.dao.MemberDAO;
import com.yinhai.furns.dao.impl.MemberDAOImpl;
import com.yinhai.furns.javabean.Member;/*** author 银小海* version 1.0* email yinhai14qq.com*/
public class MemberTest {public static void main(String[] args) {MemberDAO memberDAO new MemberDAOImpl();if (memberDAO.queryMemberByUsername(admin) null){System.out.println(null);}else {System.out.println(exist);}Member member new Member(null,jack,jack,135465qq.com);if(memberDAO.saveMember(member) 0){System.out.println(添加失败);}else{System.out.println(添加成功);}}
}服务端 提供注册
package com.yinhai.furns.test;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.junit.jupiter.api.Test;/*** author 银小海* version 1.0* email yinhai14qq.com*/
public class MemberServiceTest {public static void main(String[] args) {MemberService memberService new MemberServiceImpl();if (memberService.isExistsUsername(admin)){System.out.println(用户存在);}else{System.out.println(用户不存在);}}Testpublic void test(){Member member new Member(null, tom, tom, 643013242qq.com);MemberService memberService new MemberServiceImpl();boolean b memberService.registerMember(member);if (b){System.out.println(注册成功);}else{System.out.println(注册失败);}JDBCUtilsByDruid.commit();}
}一个Servlet提供前后端交流
注册成功 请求转发到注册完成的页面
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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 银小海* version 1.0* email yinhai14qq.com*/
WebServlet(name RegisterServlet,urlPatterns /registerServlet)
public class RegisterServlet extends HttpServlet {private MemberService memberService new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username request.getParameter(user-name);String password request.getParameter(user-password);String email request.getParameter(user-email);if(!memberService.isExistsUsername(username)){System.out.println(username 用户可用 password email);Member member new Member(null,username,password,email);if (memberService.registerMember(member)) {request.getRequestDispatcher(/views/member/register_ok.jsp).forward(request,response);JDBCUtilsByDruid.commit();}else {request.getRequestDispatcher(/views/member/login_ok.jsp).forward(request,response);}}else{// System.out.println(用户不存在 返回注册页面);request.getRequestDispatcher(/views/member/register_fail.jsp).forward(request,response);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}五、实现功能04-会员登录 1.输入用户名、密码后提交
2.判断会员是否存在
3.会员存在(数据库),显示登录成功页面
在DAO类编写对数据库操作 也需要在父类以及接口内写该方法
public class MemberDAOImpl extends BasicDAOMember implements MemberDAO {Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql SELECT id,username,password,email FROM member WHERE username? and passwordmd5(?);return querySingle(sql, Member.class, username, password);}} 在Service调用该方法
public class MemberServiceImpl implements MemberService {Overridepublic Member login(Member member) {//返回对象return memberDAO.queryMemberByUsernameAndPassword(member.getUsername(), member.getPassword());}
}
LoginServlet 用于验证前端
package com.yinhai.furns.web;import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;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 银小海* version 1.0* email yinhai14qq.com*/
WebServlet(name LoginServlet,urlPatterns /loginServlet)
public class LoginServlet extends HttpServlet {private MemberService memberService new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username request.getParameter(user-name);String password request.getParameter(user-password);if (!memberService.isExistsUsername(username)){System.out.println(不存在 请重新登录);request.getRequestDispatcher(/views/member/login.html).forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) null){System.out.println(密码错误 重新登录);request.getRequestDispatcher(/views/member/login.html).forward(request,response);return;}System.out.println(登录成功);request.getRequestDispatcher(/views/member/login_ok.jsp).forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}六、实现功能05 - 登录错误提示 表单回显 在LoginServlet内添加回显以及消息提示
WebServlet(name LoginServlet,urlPatterns /loginServlet)
public class LoginServlet extends HttpServlet {private MemberService memberService new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username request.getParameter(user-name);String password request.getParameter(user-password);if (!memberService.isExistsUsername(username)){System.out.println(用户名或者密码错误);request.setAttribute(msg,用户名或者密码错误);request.setAttribute(user-name,username);request.getRequestDispatcher(/views/member/login.jsp).forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) null){System.out.println(密码错误 重新登录);request.setAttribute(msg,密码错误 重新登录);request.setAttribute(user-name,username);request.getRequestDispatcher(/views/member/login.jsp).forward(request,response);return;}System.out.println(登录成功);request.getRequestDispatcher(/views/member/login_ok.jsp).forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
将前段页面改为jsp 并使用EL表达式 div idlg1 classtab-pane activediv classlogin-form-containerdiv classlogin-register-formspan stylefloat: right; font-weight: bold; font-size: 20pt; margin-left: 10px;${msg}/span 添加动态显示用户名 在对应的地方使用el表达式即可 七、实现功能06 - 合并servlet
1.使用if else解决 使用switch - case进行判断
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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 银小海* version 1.0* email yinhai14qq.com*/
WebServlet(name MemberServlet, urlPatterns /memberServlet)
public class MemberServlet extends HttpServlet {private MemberService memberService new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username request.getParameter(user-name);String password request.getParameter(user-password);String email request.getParameter(user-email);String action request.getParameter(action);System.out.println(action);switch (action) {case login:if (!memberService.isExistsUsername(username)) {System.out.println(用户不存在);request.setAttribute(msg, 用户不存在);request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);return;}if (memberService.login(new Member(null, username, password, null)) null) {System.out.println(密码错误 重新登录);request.setAttribute(msg, 密码错误 重新登录);request.setAttribute(username, username);request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);return;}System.out.println(登录成功);request.getRequestDispatcher(/views/member/login_ok.jsp).forward(request, response);break;case register:if (!memberService.isExistsUsername(username)) {System.out.println(username 用户可用 password email);Member member new Member(null, username, password, email);if (memberService.registerMember(member)) {request.getRequestDispatcher(/views/member/register_ok.jsp).forward(request, response);JDBCUtilsByDruid.commit();} else {request.getRequestDispatcher(/views/member/register_fail.jsp).forward(request, response);}} else {System.out.println(用户存在 无法注册);request.setAttribute(msg, 用户存在 无法注册);request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);}break;}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}2.反射 模版设计 动态绑定 package com.yinhai.furns.web;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.lang.reflect.Method;/*** author 银小海* version 1.0* email yinhai14qq.com*/
public abstract class BasicServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//解决接收到的数据中文乱码问题request.setCharacterEncoding(utf-8);//System.out.println(BasicServlet doPost());//获取到action的值//老韩提示如果我们使用了模板模式反射动态绑定要满足action的value 和 方法名一致!!!String action request.getParameter(action);//System.out.println(action action);//使用反射,获取当前对象的方法//老韩解读//1.this 就是请求的Servlet//2.declaredMethod 方法对象就是当前请求的servlet对应的action名字 的方法, 该方法对象(declaredMethod)// 是变化的,根据用户请求//3.使用模板模式反射动态机制 简化多个 if--else if---..try {Method declaredMethod this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);System.out.println(declaredMethod declaredMethod);//使用方法对象进行反射调用declaredMethod.invoke(this, request, response);} catch (Exception e) {//java基础-异常机制//将发生的异常,继续throw//老师心得体会: 异常机制是可以参与业务逻辑throw new RuntimeException(e);}}}然后子类servlet继承该Servlet 随后只写login以及register方法即可
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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 银小海* version 1.0* email yinhai14qq.com*/
WebServlet(name MemberServlet, urlPatterns /memberServlet)
public class MemberServlet extends BasicServlet {private MemberService memberService new MemberServiceImpl();/*** 处理会员的注册** param request* param response* throws ServletException* throws IOException*/protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(MemberServlet register());//接收用户注册信息- 一定要去看前端页面字段..//用户名String username request.getParameter(user-name);String password request.getParameter(user-password);String email request.getParameter(user-email);//获取用户提交验证码String code request.getParameter(code);//从session中获取到验证码// String token (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);//立即删除session验证码-防止该验证码被重复使用// request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);//如果token为空并且和用户提交的验证码一致,就继续// if (token ! null token.equalsIgnoreCase(code)) {//判断这个用户名是不是可用if (!memberService.isExistsUsername(username)) {//注册//System.out.println(用户名 username 不存在, 可以注册);//构建一个Member对象Member member new Member(null, username, password, email);if (memberService.registerMember(member)) {//请求转发request.getRequestDispatcher(/views/member/register_ok.jsp).forward(request, response);} else {//请求转发request.getRequestDispatcher(/views/member/register_fail.jsp).forward(request, response);}} else {//返回注册页面//后面可以加入提示信息...request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);}// } else { //验证码不正确// request.setAttribute(msg, 验证码不正确~);// //如果前端需要回显某些数据// request.setAttribute(username, username);// request.setAttribute(email, email);// //带回一个信息 要显示到注册选项页// request.setAttribute(active, register);// request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);// }}/*** 处理会员登录** param request* param response* throws ServletException* throws IOException*/protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(MemberServlet login());//System.out.println(LoginServlet 被调用..);//老韩说明:如果在登录页面, 用户没有输入内容就直接提交后台接收到的是String username request.getParameter(user-name);String password request.getParameter(user-password);Member member memberService.login(new Member(null, username, password, null));if (member null) { //用户没有在DB//System.out.println(member 登录失败...);//把登录错误信息,放入到request域 如果忘了可以看servlet / jsprequest.setAttribute(msg, 用户名或者密码错误);request.setAttribute(username, username);//页面转发request.getRequestDispatcher(/views/member/login.jsp).forward(request, response);} else { //用户在DB//System.out.println(member 登录成功~...);//将得到member对象放入到sessionrequest.getSession().setAttribute(member, member);//老师做了一个简单处理if (admin.equals(member.getUsername())) {request.getRequestDispatcher(/views/manage/manage_menu.jsp).forward(request, response);} else {request.getRequestDispatcher(/views/member/login_ok.jsp).forward(request, response);}}}
}八、功能07 - 后台管理家具 创建furn表 package com.yinhai.furns.web;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.javabean.Furn;
import com.yinhai.furns.service.FurnService;
import com.yinhai.furns.service.impl.FurnServiceImpl;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.List;/*** author 银小海* version 1.0* email yinhai14qq.com*/
WebServlet(name FurnServlet,urlPatterns /manager/furnServlet)
public class FurnServlet extends BasicServlet {private FurnService furnService new FurnServiceImpl();/*** 这里我们使用前面的模板设计模式反射动态绑定来的调用到list方法** param req* param resp* throws ServletException* throws IOException*/protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(FurnServlet list方法被调...);ListFurn furns furnService.queryFurns();//把furns集合放入到request域req.setAttribute(furns, furns);for (Furn furn : furns) {System.out.println(furn);}//请求转发req.getRequestDispatcher(/views/manage/furn_manage.jsp).forward(req, resp);}
}通过jstl标签取出并输出 c:forEach items${requestScope.furns} varfurntrtd classproduct-thumbnaila href#img classimg-responsive ml-3 src${furn.imgPath}alt//a/tdtd classproduct-namea href#${furn.name}/a/tdtd classproduct-namea href#${furn.maker}/a/tdtd classproduct-price-cartspan classamount${furn.price}/span/tdtd classproduct-quantity${furn.sales}/tdtd classproduct-quantity${furn.stock}/tr 编写admin的DAO
public class AdminDAOImpl extends BasicDAO implements AdminDAO {Overridepublic int saveAdmin(Admin admin) {String sql INSERT INTO admin(username,password) VALUES(?,MD5(?));return update(sql, admin.getUsername(),admin.getPassword());}Overridepublic Admin queryAdminByUsernameAndPassword(String username, String password) {String sql SELECT id,username,password FROM admin WHERE username? and passwordmd5(?);return (Admin) querySingle(sql, Admin.class,username,password);}}
编写对应的和前端交互的servlet
WebServlet(name AdminServlet,urlPatterns /adminServlet)
public class AdminServlet extends BasicServlet {private AdminService adminService new AdminServiceImpl();protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username request.getParameter(username);String password request.getParameter(password);Admin admin new Admin(null, username, password);if(adminService.login(admin) null){System.out.println(管理员不存在);request.getRequestDispatcher(/views/manage/manage_login.jsp).forward(request,response);return;}request.getRequestDispatcher(/views/manage/manage_menu.jsp).forward(request,response);}
}九、功能08 - 后台管理 添加家具 WebServlet(name FurnServlet,urlPatterns /manage/furnServlet)
public class FurnServlet extends BasicServlet {private FurnService furnService new FurnServiceImpl();protected void add(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {//获取家居信息String uname request.getParameter(name);String maker request.getParameter(maker);String price request.getParameter(price);String sales request.getParameter(sales);String stock request.getParameter(stock);String defaultPath assets/images/product-image/default.jpg;Furn furn new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);System.out.println(furn);furnService.addFurn(furn);request.getRequestDispatcher(/manage/furnServlet?actionlist).forward(request, response);}
public class FurnServiceImpl implements FurnService {private FurnDAO furnDAO new FurnDAOImpl();//定义属性FurnDAO对象/*** 返回家居信息* return*/Overridepublic ListFurn queryFurns() {return furnDAO.queryFurns();}Overridepublic int addFurn(Furn furn) {return furnDAO.addFurn(furn);}
}
public class FurnDAOImpl extends BasicDAO implements FurnDAO {Overridepublic int addFurn(Furn furn) {String sql INSERT INTO furn(id,name,maker,price,sales,stock,img_path)\n \tVALUES(NULL,?,?,?,?,?,?);return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath());}
}细节 解决中文乱码问题 在BasicDAO上设置request response的文本格式 细节 解决表重复提交问题 使用重定向即可 细节 后端验证添加家具的合法性 //我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验则直接返回furn_add.jsp - request.setAttribute(mes,xx)//3. 这里可以直接进行转换//try {// int i Integer.parseInt(sales);//}catch (NumberFormatException e) {// //System.out.println(转换异常...);// req.setAttribute(mes, 销量数据格式不对...);// //返回到furn_add.jsp// req.getRequestDispatcher(/views/manage/furn_add.jsp)// .forward(req, resp);// return;//}//String stock req.getParameter(stock);//图片的路径 imgPath 使用默认即可//Furn furn null;//try {// furn new Furn(null, name, maker, new BigDecimal(price),// new Integer(sales), new Integer(stock), assets/images/product-image/default.jpg);//} catch (NumberFormatException e) {// req.setAttribute(mes, 添加数据格式不对...);// //返回到furn_add.jsp// req.getRequestDispatcher(/views/manage/furn_add.jsp)// .forward(req, resp);// return;//}//后面我们会学习SpringMVC - 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator
细节 使用工具类DataUtils 完成自动封装JavaBean
1. BeanUtils工具类它可以一次性的把所有请求的参数注入到JavaBean中。
2. BeanUtils工具类经常用于把Map中的值注入到JavaBean中或者是对象属性值的拷贝操作
3. BeanUtils不是Jdk的类需要导入需要的jar包: commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar
//使用BeanUtils完成javabean对象的自动封装.//// Furn furn new Furn();// try {// //讲 req.getParameterMap() 数据封装到furn 对象// //使用反射将数据封装, 有一个前提就是表单提交的数据字段名// //input namemaker stylewidth: 90% typetext value/// //需要和封装的Javabean的属性名一致// BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {// e.printStackTrace();// }// 自动将提交的数据封装到Furn对象Furn furn DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);
public class DataUtils {//将方法封装到静态方法方便使用public static T T copyParamToBean(Map value, T bean) {try {BeanUtils.populate(bean, value);} catch (Exception e) {e.printStackTrace();}return bean;}}
在构造javabean的时候在Furn内赋予一个默认值 给这个类自动装入 十、功能09 后台管理 删除家具
前端对x图标进行绑定事件 弹出是否删除该名字的家具 Servlet增加功能
WebServlet(name FurnServlet,urlPatterns /manage/furnServlet)
public class FurnServlet extends BasicServlet {
protected void del(HttpServletRequest request,HttpServletResponse response){int id DataUtils.parseInt(request.getParameter(id), 0);System.out.println(furnService.deleteFurnById(id));}
}
Service增加功能 public int deleteFurnById(int id) {return furnDAO.deleteFurnById(id);}
DAO类增加功能
public class FurnDAOImpl extends BasicDAO implements FurnDAO {public int deleteFurnById(int id) {String sql DELETE FROM furn WHERE id ?;return update(sql,id);}
}
十一、功能实现 10 后台管理 修改家具
查询对应的id的家具 protected void showFurn(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {int id DataUtils.parseInt(request.getParameter(id),0);Furn furn furnService.queryFurnById(id);System.out.println(furn);request.setAttribute(furn,furn);//请求转发request.getRequestDispatcher(/views/manage/furn_update.jsp).forward(request,response);} 以上完成回显操作 下一步做修改的操作 Overridepublic int updateFurn(Furn furn) {String sql UPDATE furn SET name ? , maker ? , price ? , sales ? , stock ? , img_path ? WHERE id ?;return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath(),furn.getId());} 前端页面也调整 使用jstl标签拿出 十二、功能实现11 分页显示 将分页作为一个Bean模型
package com.yinhai.furns.javabean;import java.util.List;/*** author 银小海* version 1.0* email yinhai14qq.com* 一个分页的数据模型 包含了分页的各种信息*/
//用一个泛型 分页模型对应的数据类型是不确定的
public class PageT {//每页显示多少条记录可以在其他地方也用到 建议置为常量//ctrl shift u 切换大小写public static final Integer PAGE_SIZE 3;//表示显示当前页private Integer pageNo;//每页显示多少记录private Integer pageSize PAGE_SIZE;//表示共有多少页private Integer pageTotalCount;//表示的是共有多少条记录 通过totalRow和pageSize计算得到pageTotalCountprivate Integer totalRow;//表示当前页要显示的数据private ListT items;//分页导航的字符串private String url;public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo pageNo;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize pageSize;}public Integer getPageTotalCount() {return pageTotalCount;}public void setPageTotalCount(Integer pageTotalCount) {this.pageTotalCount pageTotalCount;}public Integer getTotalRow() {return totalRow;}public void setTotalRow(Integer totalRow) {this.totalRow totalRow;}public ListT getItems() {return items;}public void setItems(ListT items) {this.items items;}public String getUrl() {return url;}public void setUrl(String url) {this.url url;}
}分析 page的那些属性可以从数据库获取 就把对应的属性交给DAO赋值
Overridepublic int getTotalRow() {String sql SELECT COUNT(*) FROM furn;// return (int) queryScalar(sql); 会报转换异常return ((Number) queryScalar(sql)).intValue();}Overridepublic ListFurn getPageItems(int begin, int pageSize) {String sql SELECT id,name,maker,price,sales,stock,img_path imgPath\n FROM furn ;return null;} 其他的交给Service处理
public class FurnServiceImpl implements FurnService {Overridepublic PageFurn page(int pageNo, int pageSize) {PageFurn page new Page();page.setPageNo(pageNo);page.setPageSize(pageSize);int totalRow furnDAO.getTotalRow();page.setTotalRow(totalRow);//pageTotalCount最大页数 需要通过算法计算得到int pageTotalCount totalRow / pageSize;if(totalRow % pageSize 0){pageTotalCount 1;}page.setPageTotalCount(pageTotalCount);//private ListT items//计算begin//private ListT items//老师开始计算begin- 小小算法//验证: pageNo 1 pageSize 3 begin 0//验证: pageNo 3 pageSize 2 begin 4//OK 但是注意这里隐藏一个坑, 现在你看不到, 后面会暴露int begin (pageNo - 1) * pageSize;ListFurn pageItems furnDAO.getPageItems(begin, pageSize);page.setItems(pageItems);//还差一个url 分页导航先放一放return page;}
}Servlet调用
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo DataUtils.parseInt(req.getParameter(pageNo), 1);int pageSize DataUtils.parseInt(req.getParameter(pageSize), Page.PAGE_SIZE);//调用service方法, 获取Page对象PageFurn page furnService.page(pageNo, pageSize);//将page放入到request域req.setAttribute(page, page);//请求转发到furn_manage.jspreq.getRequestDispatcher(/views/manage/furn_manage.jsp).forward(req, resp);}十三、功能实现 12 - 分页导航 !-- Pagination Area Start 分页导航条 --div classpro-pagination-style text-center mb-md-30px mb-lm-30px mt-6 data-aosfade-upul%--如果当前页 1 , 就显示上一页--%c:if test${requestScope.page.pageNo 1}lia hrefmanage/furnServlet?actionpagepageNo${requestScope.page.pageNo - 1}上一页/a/li/c:if%--lia classactive href#3/a/li--%%--lia href#4/a/li--%%--lia href#5/a/li--%%-- 显示所有的分页数 先容易再困难老师思路: 先确定开始页数 begin 第1页再确定结束页数 end 第pageTotalCount页学生困惑如果页数很多怎么办? 算法最多显示5页[这个规则可以由程序员决定.]希望小伙伴自己先想一想... 后面老师分析1. 如果总页数5, 就全部显示2. 如果总页数5, 按照如下规则显示(这个规则是程序员/业务来确定):2.1 如果当前页是前3页, 就显示1-52.2 如果当前页是后3页, 就显示最后5页2.3 如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页这里的关键就是要根据不同的情况来初始化begin, end--%c:choose%--如果总页数5, 就全部显示--%c:when test${requestScope.page.pageTotalCount 5 }c:set varbegin value1/c:set varend value${requestScope.page.pageTotalCount}//c:when%--如果总页数5--%c:when test${requestScope.page.pageTotalCount 5}c:choose%--如果当前页是前3页, 就显示1-5--%c:when test${requestScope.page.pageNo 3}c:set varbegin value1/c:set varend value5//c:when%--如果当前页是后3页, 就显示最后5页--%c:when test${requestScope.page.pageNo requestScope.page.pageTotalCount - 3}c:set varbegin value${requestScope.page.pageTotalCount - 4}/c:set varend value${requestScope.page.pageTotalCount}//c:when%--如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页--%c:otherwisec:set varbegin value${requestScope.page.pageNo - 2}/c:set varend value${requestScope.page.pageNo 2}//c:otherwise/c:choose/c:when/c:choosec:forEach begin${begin} end${end} vari%--如果i是当前页, 就使用classactive 修饰--%c:if test${i requestScope.page.pageNo}lia classactive hrefmanage/furnServlet?actionpagepageNo${i}${i}/a/li/c:ifc:if test${i ! requestScope.page.pageNo}lia hrefmanage/furnServlet?actionpagepageNo${i}${i}/a/li/c:if/c:forEach%--如果当前页 总页数 , 就显示下一页--%c:if test${requestScope.page.pageNo requestScope.page.pageTotalCount}lia hrefmanage/furnServlet?actionpagepageNo${requestScope.page.pageNo 1}下一页/a/li/c:iflia href#共 ${requestScope.page.pageTotalCount} 页/a/li/ul/div!-- Pagination Area End -- 进行修改 删除 添加 家具之后 能够回显到原来操作所在的页面
修改一步步转发 到最后重定向到page页面 这几个都这么做都在修改请求转发地址上完成
WebServlet(name FurnServlet, urlPatterns /manage/furnServlet)
public class FurnServlet extends BasicServlet {protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取家居信息// String uname request.getParameter(name);// String maker request.getParameter(maker);// String price request.getParameter(price);// String sales request.getParameter(sales);////// String stock request.getParameter(stock);// String defaultPath assets/images/product-image/default.jpg;// Furn furn new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);//我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验则直接返回furn_add.jsp - request.setAttribute(mes,xx)//3. 这里可以直接进行转换//try {// int i Integer.parseInt(sales);//}catch (NumberFormatException e) {// //System.out.println(转换异常...);// req.setAttribute(mes, 销量数据格式不对...);// //返回到furn_add.jsp// req.getRequestDispatcher(/views/manage/furn_add.jsp)// .forward(req, resp);// return;//}//String stock req.getParameter(stock);//图片的路径 imgPath 使用默认即可//Furn furn null;//try {// furn new Furn(null, name, maker, new BigDecimal(price),// new Integer(sales), new Integer(stock), assets/images/product-image/default.jpg);//} catch (NumberFormatException e) {// req.setAttribute(mes, 添加数据格式不对...);// //返回到furn_add.jsp// req.getRequestDispatcher(/views/manage/furn_add.jsp)// .forward(req, resp);// return;//}//后面我们会学习SpringMVC - 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator//这里我们使用第二种方式, 完成将前端提交的数据 封装成Furn的Javabean对象//使用BeanUtils完成javabean对象的自动封装.//// Furn furn new Furn();// try {// //讲 req.getParameterMap() 数据封装到furn 对象// //使用反射将数据封装, 有一个前提就是表单提交的数据字段名// //input namemaker stylewidth: 90% typetext value/// //需要和封装的Javabean的属性名一致// BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {// e.printStackTrace();// }// 自动将提交的数据封装到Furn对象Furn furn DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);//老师说明: 因为这里使用请求转发, 当用户刷新页面时, 会重新发出一次添加请求// request.getRequestDispatcher(/manage/furnServlet?actionlist)// .forward(request, response);//就会造成数据重复提交 解决方案使用 重定向即可.//因为重定向实际是让浏览器重新发请求, 所以我们回送的url , 是一个完整url// response.sendRedirect(request.getContextPath() /manage/furnServlet?actionlist);//以分页的方式显示response.sendRedirect(request.getContextPath() /manage/furnServlet?actionpagepageNo request.getParameter(pageNo));}protected void del(HttpServletRequest request, HttpServletResponse response) throws IOException {int id DataUtils.parseInt(request.getParameter(id), 0);System.out.println(furnService.deleteFurnById(id));response.sendRedirect(request.getContextPath() /manage/furnServlet?actionpagepageNo request.getParameter(pageNo));}protected void showFurn(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int id DataUtils.parseInt(request.getParameter(id), 0);Furn furn furnService.queryFurnById(id);System.out.println(furn);request.setAttribute(furn, furn);//再把获取到的showPage再传回去// request.setAttribute(pageNo,request.getParameter(pageNo));// 如果是在同一个作用域request内的请求是不需要再转发的 在下个页面可以用param.pageNo获取//请求转发request.getRequestDispatcher(/views/manage/furn_update.jsp).forward(request, response);}protected void update(HttpServletRequest request, HttpServletResponse response) throws IOException {Furn furn DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(update furn);System.out.println(furnService.updateFurn(furn));//请求重定向// response.sendRedirect(request.getContextPath() /manage/furnServlet?actionlist);//这里考虑分页转发System.out.println(request.getContextPath() /manage/furnServlet?actionpagepageNo request.getParameter(pageNo));response.sendRedirect(request.getContextPath() /manage/furnServlet?actionpagepageNo request.getParameter(pageNo));}protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo DataUtils.parseInt(req.getParameter(pageNo), 1);int pageSize DataUtils.parseInt(req.getParameter(pageSize), Page.PAGE_SIZE);//调用service方法, 获取Page对象PageFurn page furnService.page(pageNo, pageSize);if(page.getItems().size() 0){page furnService.page(page.getPageTotalCount(), pageSize);}//将page放入到request域req.setAttribute(page, page);//请求转发到furn_manage.jspreq.getRequestDispatcher(/views/manage/furn_manage.jsp).forward(req, resp);}}
十四、功能实现13 - 首页分页