书城项目
第一阶段:表单验证
验证用户名:必须由字母,数字下划线组成,并且长度在5-12位
验证密码:必须由字母,数字下划线组成,并且长度为5-12位
验证确认密码:和密码相同
邮箱验证:[email protected]
验证码:现在只需要验证用户已输入,因为还没将到服务器,验证码生成。
1、新建一个模块
2、把书城的静态资源拷贝到模块工程下
<script type="text/javascript">
//页面加载完成之后
$(function(){
//给注册绑定单击事件
$("#sub_btn").click(function() {
// 验证用户名:必须由字母,数字下划线组成,并且长度在5-12位
//1、获取用户输入框里的内容
var usernameText = $("#username").val();
//2、创建正则表达式对象
var usernamePatt =/^\w{5,12}$/;
//3、使用test方法验证
if (!usernamePatt.test(usernameText)) {
//4、提示用户结果
$("span.errorMsg").text("用户名不合法!");
return false;
}
// 验证密码:必须由字母,数字下划线组成,并且长度为5-12位
//1、获取密码输入框里的内容
var passwordText = $("#password").val();
//2、创建正则表达式对象
var passwordPatt = /^\w{5,12}$/;
//3、使用test方法验证
if (!passwordPatt.test(passwordText)) {
//4、提示用户结果
$("span.errorMsg").text("密码不合法!");
return false;
}
// 验证确认密码:和密码相同
//1、获取确认密码的内容
var repwdText = $("#repwd").val();
//2、和密码比较
if(repwdText!=passwordText){
//3、提示用户
$("span.errorMsg").text("确认密码和密码不一致!")
return false;
}
// 邮箱验证:[email protected]
//1、获取邮箱里的内容
var emailText = $("#email").val();
//2、创建正则表达式对象
var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
//3、使用test方法验证
if(!emailPatt.test(emailText)){
//4、提示用户
$("span.errorMsg").text("邮箱格式不正确!")
return false;
}
// 验证码:现在只需要验证用户已输入,因为还没将到服务器,验证码生成。
var codeText = $("#code").val();
//去掉验证码前后空格
codeText = $.trim(codeText);
if(codeText==null ||codeText=="" ){
$("span.errorMsg").text("验证码不能为空!")
return false;
}
$("span.errorMsg").text("");
});
});
第二阶段:用户注册和登录
1、JavaEE项目的三层架构
分层的目的是为了解耦,解耦就是为了降低代码的耦合度,方便项目后期的维护和升级。
web层 com.lxg.web/servlet/controller
service层 com.lxg.service Service接口包
com.lxg.service.impl Service接口实现类
dao持久层 com.lxg.dao Dao接口包
com.lxg.dao.impl Dao接口实现类
实体bean对象 com.lxg.pojo/entity/domain/bean JavaBean类
测试包 com.lxg.test/junit
工具类 com.lxg.utils
2、编码环节
1、先创建书城需要的数据库和表
drop database if EXISTS book;
CREATE DATABASE book;
use book;
CREATE table t_user(
`id` int PRIMARY key auto_increment,
`username` varchar(20) not null unique,
`password` VARCHAR(32) not null,
`email` varchar(200)
);
INSERT INTO t_user(`username`,`password`,`email`) VALUES ('admin','admin','[email protected]');
select * from t_user;
2、编写数据库表对应的JavaBean对象
package com.lxg.domain;
public class User {
private Integer id;
private String username;
private String password;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public User() {
}
}
3、编写工具类JdbcUtils
package com.lxg.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class JdbcUtils {
private static DruidDataSource dataSource;
static {
try{
Properties properties = new Properties();
//读取jdbc.properties属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//从流中读取数据
properties.load(inputStream);
//创建数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取数据库连接池中的连接
* @return 如果返回null说明获取连接失败,反之成功
*/
public static Connection getConnection(){
Connection conn =null;
try{
conn = dataSource.getConnection();
}catch (Exception e){
e.printStackTrace();
}
return conn;
}
/**
* 关闭连接,返回数据库连接池
* @param conn
*/
public static void close(Connection conn){
if(conn!=null){
try{
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
测试
@Test
public void testJdbcUtils(){
for (int i = 0; i < 100; i++) {
Connection connection = JdbcUtils.getConnection();
System.out.println(connection);
JdbcUtils.close(connection);
}
}
4、编写BaseDao
package com.lxg.dao;
import com.lxg.utils.JdbcUtils;
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;
public abstract class BaseDao {
//使用DBUtils操作数据库
private QueryRunner queryRunner = new QueryRunner();
/**
* update()方法用来执行:Insert\update\Delete语句
* @param sql
* @param args
* @return如果返回-1,说明执行失败,其他表示影响的行数
*/
public int update(String sql,Object...args){
Connection connection = JdbcUtils.getConnection();
try{
return queryRunner.update(connection,sql,args);
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return -1;
}
/**
* 查询返回一个javaBean的sql语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @param <T> 返回的类型的泛型
* @return
*/
public<T> T queryForOne(Class<T> type,String sql,Object...args){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
/**
* 查询返回多个javaBean的sql语句
* @param type 返回的对象类型
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @param <T> 返回的类型的泛型
* @return
*/
public <T> List<T> queryForList(Class<T> type,String sql,Object...args){
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
/**
* 执行返回一行一列的sql语句
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @return
*/
public Object queryForSingleValue(String sql,Object...args){
Connection connection = JdbcUtils.getConnection();
try {
queryRunner.query(connection,sql,new ScalarHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(connection);
}
return null;
}
}
5、编写UserDao和测试
package com.lxg.test;
import com.lxg.dao.UserDao;
import com.lxg.dao.impl.UserDaoImpl;
import com.lxg.domain.User;
import org.junit.Test;
import static org.junit.Assert.*;
public class UserDaoTest {
UserDao userDao = new UserDaoImpl();
@Test
public void queryUserByUsername() {
if(userDao.queryUserByUsername("admin")==null){
System.out.println("用户名可用");
}else{
System.out.println("用户名已存在");
}
}
@Test
public void queryUserByUsernameAndPassword() {
if(userDao.queryUserByUsernameAndPassword("admin","123456")==null){
System.out.println("用户名或密码错误");
}else{
System.out.println("登录成功");
}
}
@Test
public void saveUser() {
System.out.println(userDao.saveUser(new User(null,"lxg","123456","[email protected]")));
}
}
6、编写UserService和测试
package com.lxg.test;
import com.lxg.domain.User;
import com.lxg.service.UserService;
import com.lxg.service.impl.UserServiceImpl;
import org.junit.Test;
import static org.junit.Assert.*;
public class UserServiceTest {
UserService userService = new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"zs","123456","[email protected]"));
userService.registUser(new User(null,"ls","123456","[email protected]"));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"zs","123456",null)));
}
@Test
public void existsUsername() {
if(userService.existsUsername("zs")){
System.out.println("用户名已存在");
}else {
System.out.println("用户名可用");
}
}
}
7、编写web层
1、用户注册
需求如下:
1、访问注册页面
2、填写注册信息,提交给服务器
3、服务器应该保存用户
4、当用户已经存在——提示用户注册失败,用户名已存在
5、当用户不存在——注册成功
package com.lxg.web;
import com.lxg.domain.User;
import com.lxg.service.UserService;
import com.lxg.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegistServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
//2、检查验证码是否正确===写死,要求验证码为:abcde
if ("abcde".equalsIgnoreCase(code)) {
//正确
//3、检查用户名是否可用
if(userService.existsUsername(username)){
//用户名已存在,不可用
System.out.println("用户名["+username+"]已存在!");
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}else{
//用户名可用
//调用service保存到数据库
userService.registUser(new User(null,username,password,email));
//跳转到注册成功页面
req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
}
}else{
System.out.println("验证码["+code+"]错误");
//跳回注册页面
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}
}
}
2、用户登录
需求如下:
1、访问登录页面
2、填写用户名和密码后提交
3、服务器判断用户是否存在
4、如果登录失败——返回用户名或密码的错误信息
package com.lxg.web;
import com.lxg.domain.User;
import com.lxg.service.UserService;
import com.lxg.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//2、调用userService.login完成业务逻辑
User loginUser= userService.login(new User(null,username, password,null));
//如果等于null,说明登录失败
if(loginUser==null){
//3、跳转到登录页面
req.getRequestDispatcher("/pages/user/login.html").forward(req,resp);
}else {
//4、登录成功,跳转到登录成功页面
req.getRequestDispatcher("/pages/user/login_success.html").forward(req,resp);
}
}
}
3、IDEA中的Debug调试的使用
Debug调试代码,首先需要两个元素:断点+Debug启动服务器
1、断点:只需要在代码需要停的行的左边上单击,就可以添加和取消
2、Debug服务器启动Tomcat运行代码:点击调试按钮
测试工具栏:
变量窗口,它可以查看当前方法范围内所有有效变量
方法调用窗口
1、方法调用栈可以查看当前线程有哪些方法调用信息
2、下面一行的方法调用上面一行的方法
其他常用调试相关按钮:
第三阶段:优化
a:页面jsp动态化
- 在html页面顶行添加page指令
- 修改文件后缀名为:.jsp
3.使用idea搜索替换.html为.jsp
CTRL+SHIF+R:或者CTRL+R
b:抽取页面相同的内容
c:登录,注册错误提示以及表单回显
在Servlet后端代码中将用户信息保存进域对象,
在jsp前端页面代码中使用EL表达式获取信息并显示
d:BaseServlet的抽取
在实际的项目开发中,一个模块,一般只使用一个Servlet程序。
LoginServlet和RegistServle优化为UserServlet:
package main.java.com.lxg.web;
import main.java.com.lxg.domain.User;
import main.java.com.lxg.service.UserService;
import main.java.com.lxg.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
/**
* 处理登录功能
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//System.out.println("处理登录的需求");
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 调用 userService.login()登录处理业务
User loginUser = userService.login(new User(null, username, password, null));
// 如果等于null,说明登录 失败!
if (loginUser == null) {
// 把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg", "用户或密码错误!");
req.setAttribute("username", username);
// 跳回登录页面
req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
} else {
// 登录 成功
//跳到成功页面login_success.html
req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);
}
}
/**
* 处理注册功能
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
//2、检查 验证码是否正确 === 写死,要求验证码为:abcde
if ("abcde".equalsIgnoreCase(code)) {
//3、检查 用户名是否可用
if (userService.existsUsername(username)) {
System.out.println("用户名[" + username + "]已存在!");
// 把回显信息,保存到Request域中
req.setAttribute("msg", "用户名已存在!!");
req.setAttribute("username", username);
req.setAttribute("email", email);
//跳回注册页面
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
} else {
//可用
//调用Sservice保存到数据库
userService.registUser(new User(null, username, password, email));
//跳到注册成功页面 regist_success.jsp
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
}
} else {
// 把回显信息,保存到Request域中
req.setAttribute("msg", "验证码错误!!");
req.setAttribute("username", username);
req.setAttribute("email", email);
System.out.println("验证码[" + code + "]错误");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if ("login".equals(action)) {
login(req, resp);
} else if ("regist".equals(action)) {
regist(req, resp);
}
}
}
doPost还可以继续优化为:
String action = req.getParameter("action");
try {
//通过action业务鉴别字符串,获取对应的业务,方法反射对象
Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
//System.out.println(method);
//调用目标业务方法
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
如若系统又有其他模块,这个代码可以抽取出来变成BaseServlet
e:数据的封装和抽取BeanUtils的使用
-
BeanUtils工具类,它可以一次性的把请求的参数注入到javaBean中。
-
BeanUtils不是jdk的类,是第三方的工具类,所以需要导包
-
导入需要的jar包:
commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar -
使用BeanUti类方法实现注入
-
package main.java.com.lxg.utils;
import org.apache.commons.beanutils.BeanUtils;
import java.util.Map;
public class WebUtils {
/**
* 把Map中的值注入到对应的JavaBean属性中。
* @param value
* @param bean
*/
public static <T> T copyParamToBean(Map value, T bean){
try {
System.out.println("注入之前:"+bean);
/**
* 把所有请求的参数全都注入到user对象中
*/
BeanUtils.populate(bean,value);
System.out.println("注入之后:"+bean);
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
//给参数注入值
User user = WebUtils.copyParamToBean(req.getParameterMap(),new User());
CTRL+ALT+T快捷键:
第四阶段:使用EL表达式修改表单回显(上面已修改)
第五阶段:图书模块
1、MVC概念
MVC全称:Model模型、View视图、Controller控制器
MVC最早出现在JavaEE三层的web层,它可以有效的指导web层的代码如何有效分离,单独工作
View视图:只负责数据和界面的显示,不接受任何域显示数据无关的代码,便于程序员和美工的分工合作---jsp/Html
Controller控制器:只负责接收请求,调用业务层的代码请求,然后派发页面,是一个“调度者”的角色--Servlet。转到某个页面,或者是重定向到某个页面。
Model模型:将与业务逻辑相关的数据封装成为具体的JavaBean类,其中不掺杂任何与数据处理相关的代码--JavaBean、domain、entity。
MVC是一种思想
MVC的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了解耦合)。
MVC的作用还是为了降低耦合,让代码合理分层,方便后期升级和维护。
2、图书模块
2.1、编写图书模块的数据库表
2.2、编写图书模块的JavaBean
package main.java.com.lxg.domain;
import java.math.BigDecimal;
public class Book {
private Integer id;
private String name;
private String author;
private BigDecimal price;
private Integer sales;
private Integer stock;
private String imgPath="static/img/default.jpg";
public Book() {
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", sales=" + sales +
", stock=" + stock +
", imgPath='" + imgPath + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Integer getSales() {
return sales;
}
public void setSales(Integer sales) {
this.sales = sales;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getImgPath() {
return imgPath;
}
public void setImgPath(String imgPath) {
//要求给定的图书封面图书路径不能为空
if (imgPath!=null && !"".equals(imgPath)){
this.imgPath = imgPath;
}
}
public Book(Integer id, String name, String author, BigDecimal price, Integer sales, Integer stock, String imgPath) {
this.id = id;
this.name = name;
this.author = author;
this.price = price;
this.sales = sales;
this.stock = stock;
//要求给定的图书封面图书路径不能为空
if (imgPath!=null && !"".equals(imgPath)){
this.imgPath = imgPath;
}
}
}
2.3、编写图书模块的Dao和测试Dao
package main.java.com.lxg.dao;
import main.java.com.lxg.domain.Book;
import java.util.List;
public interface BookDao {
public int addBook(Book book);
public int deleteBookById(Integer id);
public int updateBook(Book book);
public Book queryBookById(Integer id);
public List<Book> queryBooks();
}
package main.java.com.lxg.dao.impl;
import main.java.com.lxg.dao.BookDao;
import main.java.com.lxg.domain.Book;
import java.util.List;
public class BookDaoImpl extends BaseDao implements BookDao {
@Override
public int addBook(Book book) {
String sql = "insert into t_book(`name`,`author`,`price`,`sales`,`stock`,`img_path`) \n" +
"values(?,?,?,?,?,?)";
return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath());
}
@Override
public int deleteBookById(Integer id) {
String sql = "delete from t_book where id=?";
return update(sql,id);
}
@Override
public int updateBook(Book book) {
String sql="update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=? where id=?";
return update(sql,book.getName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath(),book.getId());
}
@Override
public Book queryBookById(Integer id) {
String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` imPath from t_book where id=? ";
return queryForOne(Book.class,sql,id);
}
@Override
public List<Book> queryBooks() {
String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book";
return queryForList(Book.class,sql);
}
}
生成测试快捷键:CTRL+SHIFT+T
2.4、编写图书模块的Service和测试Service
package main.java.com.lxg.service;
import main.java.com.lxg.domain.Book;
import java.util.List;
public interface BookService {
public void addBook(Book book);
public void deleteBookById(Integer id);
public void updateBook(Book book);
public Book findBookById(Integer id);
public List<Book> findAllBooks();
}
package main.java.com.lxg.service.impl;
import main.java.com.lxg.dao.BookDao;
import main.java.com.lxg.dao.impl.BookDaoImpl;
import main.java.com.lxg.domain.Book;
import main.java.com.lxg.service.BookService;
import java.util.List;
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
@Override
public void addBook(Book book) {
bookDao.addBook(book);
}
@Override
public void deleteBookById(Integer id) {
bookDao.deleteBookById(id);
}
@Override
public void updateBook(Book book) {
bookDao.updateBook(book);
}
@Override
public Book findBookById(Integer id) {
return bookDao.queryBookById(id);
}
@Override
public List<Book> findAllBooks() {
return bookDao.queryBooks();
}
}
2.5、编写图书模块的Web层,和页面联调测试
BookServlet:
package main.java.com.lxg.web;
import main.java.com.lxg.domain.Book;
import main.java.com.lxg.service.BookService;
import main.java.com.lxg.service.impl.BookServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
public class BookServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、通过BookService查询全部图书
List<Book> books = bookService.findAllBooks();
//2、把全部图书信息保存到Req域中
req.setAttribute("books",books);
//3、请求转发到pages/manager/book_manager.jsp页面
req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
}
}
需要给BaseServlet加上doGet方法才可处理get请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
实现展示所有图书功能:
使用jstl标签遍历获取数据显示在前端页面:
<c:forEach items="${requestScope.books}" var="book">
<tr>
<td>${book.name}</td>
<td>${book.price}</td>
<td>${book.author}</td>
<td>${book.sales}</td>
<td>${book.stock}</td>
<td><a href="book_edit.jsp">修改</a></td>
<td><a href="#">删除</a></td>
</tr>
</c:forEach>
前后台的介绍:
实现添加图书功能:
请求转发定位到工程目录
请求重定向定位到端口号
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求的参数==封装成为Book对象
Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
//2、调用BookService.addBook()保存图书
bookService.addBook(book);
//3、跳到图书列表页面
//req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req,resp);
resp.sendRedirect(req.getContextPath()+"/manager/bookServlet?action=list");
}
实现图书删除功能:
<script type="text/javascript">
$(function (){
//给删除的a标签绑定单击事件
$("a.deleteClass").click(function () {
//在事件的function函数中,有一个this对象,这个this对象,是当前正在响应事件的dom对象
/**
* confirm是确认提示框函数
* 参数是它提示的内容
* 它有两个按钮,一个确定,一个是取消
* 返回true表示点击了确定,返回false表示点击了取消
*/
return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】?");
})
});
</script>
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求的参数id,图书编号
int id = WebUtils.parseInt(req.getParameter("id"),0);
//2、调用BookService.deleteBookById(id);
bookService.deleteBookById(id);
//3、重定向会图书列表管理页面
resp.sendRedirect(req.getContextPath()+"/manager/bookServlet?action=list");
}
<td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}">删除</a></td>
实现图书修改功能:
获取前端页面数据:
protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求的参数,图书编号
int id = WebUtils.parseInt(req.getParameter("id"),0);
//2、调用bookService.queryBookById查询图书
Book book = bookService.findBookById(id);
//3、保存图书信息到request域中
req.setAttribute("book",book);
//4、请求转发到,pages/maanger/book_edit.jsp页面
req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp);
}
回显数据:
<tr>
<td><input name="name" type="text" value="${book.name}"/></td>
<td><input name="price" type="text" value="${book.price}"/></td>
<td><input name="author" type="text" value="${book.author}"/></td>
<td><input name="sales" type="text" value="${book.sales}"/></td>
<td><input name="stock" type="text" value="${book.stock}"/></td>
<td><input type="submit" value="提交"/></td>
</tr>
保存修改:
<%--<input type="hidden" name="action" value="${param.method}">--%>
<%--<input type="hidden" name="action" value="${empty param.id ? "add" : "update"}">--%>
<input type="hidden" name="action" value="${empty requestScope.book ? "add" : "update"}">
<%--<td><a href="pages/manager/book_edit.jsp?method=add">添加图书</a></td>--%>
<td><a href="pages/manager/book_edit.jsp">添加图书</a></td>
<%--<td><a href="manager/bookServlet?action=getBook&id=${book.id}&method=update">修改</a></td>--%>
<td><a href="manager/bookServlet?action=getBook&id=${book.id}">修改</a></td
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、获取请求的参数==封装成Book对象
Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
//2、调用BookService.updateBook(book);修改图书
bookService.updateBook(book);
//3、重定向会图书列表管理页面
resp.sendRedirect(req.getContextPath()+"/manager/bookServlet?action=list");
}
3、图书分页
-
分页功能分析
-
分页模型Page对象的创建
-
分页初步实现
-
首页,上一页,末页的实现
-
跳转到指定页码的功能
-
数据边界有效的检验
-
分页条页码的显示(显示5个连续的页码,而且当前页码在中间,除了当前页码之外,每个页码都可以点击跳转到相应的指定页面
-
修改分页对原来添加修改删除功能的影响
4、前台分页
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>书城首页</title>
<%--静态包含base标签,css样式,jQuery文件--%>
<%@ include file="/pages/common/head.jsp"%>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
<span class="wel_word">网上书城</span>
<div>
<a href="pages/user/login.jsp">登录</a> |
<a href="pages/user/regist.jsp">注册</a>
<a href="pages/cart/cart.jsp">购物车</a>
<a href="pages/manager/manager.jsp">后台管理</a>
</div>
</div>
<div id="main">
<div id="book">
<div class="book_cond">
<form action="" method="get">
价格:<input id="min" type="text" name="min" value=""> 元 -
<input id="max" type="text" name="max" value=""> 元
<input type="submit" value="查询" />
</form>
</div>
<div style="text-align: center">
<span>您的购物车中有3件商品</span>
<div>
您刚刚将<span style="color: red">时间简史</span>加入到了购物车中
</div>
</div>
<c:forEach items="${requestScope.page.items}" var="book" >
<div class="b_list">
<div class="img_div">
<img class="book_img" alt="" src="${book.imgPath}" />
</div>
<div class="book_info">
<div class="book_name">
<span class="sp1">书名:</span>
<span class="sp2">${book.name}</span>
</div>
<div class="book_author">
<span class="sp1">作者:</span>
<span class="sp2">${book.author}</span>
</div>
<div class="book_price">
<span class="sp1">价格:</span>
<span class="sp2">¥${book.price}</span>
</div>
<div class="book_sales">
<span class="sp1">销量:</span>
<span class="sp2">${book.sales}</span>
</div>
<div class="book_amount">
<span class="sp1">库存:</span>
<span class="sp2">${book.stock}</span>
</div>
<div class="book_add">
<button>加入购物车</button>
</div>
</div>
</div>
</c:forEach>
</div>
<div id="page_nav">
<%--大于首页才显示--%>
<c:if test="${requestScope.page.pageNo>1}">
<a href="client/bookServlet?action=page&pageNo=1">首页</a>
<a href="client/bookServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a>
</c:if>
<%--页码输出的开始--%>
<c:choose>
<%--1、总页码小于等于五,页码范围1-总页码--%>
<c:when test="${requestScope.page.pageTotal<=5}">
<c:set var="begin" value="1"/>
<c:set var="end" value="${requestScope.page.pageTotal}"/>
</c:when>
<%--2、总页码大于五--%>
<c:when test="${requestScope.page.pageTotal>5}">
<c:choose>
<%--2.1当前页码为前面三个,1,2,3的情况-,页码范围为1到5--%>
<c:when test="${requestScope.page.pageNo <=3}">
<c:set var="begin" value="1"/>
<c:set var="end" value="5"/>
</c:when>
<%--2.2当前页码为最后三个,页码范围为总页码减4到总页码--%>
<c:when test="${requestScope.page.pageNo>requestScope.page.pageTotal-3}">
<c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
<c:set var="end" value="${requestScope.page.pageTotal}"/>
</c:when>
<%--2.3:剩下的页码--%>
<c:otherwise>
<c:set var="begin" value="${requestScope.page.pageNo-2}"/>
<c:set var="end" value="${requestScope.page.pageNo+2}"/>
</c:otherwise>
</c:choose>
</c:when>
</c:choose>
<c:forEach begin="${begin}" end="${end}" var="i">
<c:if test="${i==requestScope.page.pageNo}">
【${i}】
</c:if>
<c:if test="${i!=requestScope.page.pageNo}">
<a href="client/bookServlet?action=page&pageNo=${i}">${i}</a>
</c:if>
</c:forEach>
<%--页码输出的结束--%>
<%--如果已经是最后一页,则不显示下一页和末页--%>
<c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
<a href="client/bookServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a>
<a href="client/bookServlet?action=page&pageNo=${requestScope.page.pageTotal}">末页</a>
</c:if>
共${requestScope.page.pageTotal}页,${requestScope.page.pageTotalCount}条记录
到第<input value="${param.pageNo}" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
<script type="text/javascript">
$(function (){
//跳到指定的页码
$("#searchPageBtn").click(function (){
var pageNo = $("#pn_input").val();
//js语言提供了一个location地址栏对象
//它有一个属性叫href,它可以获取浏览器地址栏中的地址
location.href="${pageScope.basePath}client/bookServlet?action=page&pageNo="+pageNo;
});
});
</script>
</div>
</div>
<%--静态包含页脚内容--%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
根据价格区间查询数据并分页:
第六阶段:登录登出
1、登录
a、显示用户名
2、登出
a、注销用户
1、销毁session中用户登录的信息(或者销毁session)
2、重定向到首页或者登录界面
3、表单重复提交
有三种常见情况:
1、提交完表单,服务器使用请求转发来进行页面跳转,这个时候用户按下F5功能键,就会发起最后一次的请求,造成表单重复提交问题。
解决方法是使用重定向来进行页面跳转
2、用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交
3、用户正常提交服务器,服务器也没有延迟,但是提交完成之后,用户回退浏览器,重新提交,也会造成表单重复提交
后两种因没有可直接解决的方法,后引入验证码,使用验证码防止用户恶意提交
a、验证码
验证码解决表单重复提交的底层原理
b、谷歌kaptcha图片验证码的使用
使用步骤如下:
1、导入谷歌验证码的jar包(kaptcha-2.3.2.jar)
2、在web.xml中去配置用于生成验证码的Servlet程序
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
3、在表单中使用img标签去显示验证码图片并使用它
验证码:<input type="text" style="width: 50px; " name="code">
<img src="http://localhost:8080/bookTest/kaptcha.jpg" style="width:110px;height: 20px; " alt=""><br/>
4、在服务器获取谷歌生成的验证码,和客户端发送过来的验证码比较使用
4、购物车模块
1、编写购物车模型
2、加入购物车功能的实现
3、购物车的展示
4、删除购物车商品项的功能
5、清空购物车
6、修改商品数量
7、加入购物车提醒功能
5、订单模块
1、创建数据库表
2、编写对应实体类
3、编写dao和测试dao
4、编写service和测试service
5、配置web.xml
6、编写OrderServlet
7、修改页面
第七阶段:权限检查
1、使用过滤器拦截
2、ThreadLocal的使用
它可以解决多线程的数据安全问题
ThreadLocal它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数据,集合)
特点:
1、ThreadLocal可以为当前线程关联一个数据(它可以是像Map一样存储数据,key为当前线程)
2、每一个ThreadLocal对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal对象实例
3、每个ThreadLocal对象实例定义的时候一般都是static类型
4、ThreadLocal中保存数据,在线程销毁后,会由JVM虚拟自动释放
3、使用Filter和ThreadLocal组合管理事务
1、使用ThreadLocal确保所有操作对象都使用同一个连接对象
2、使用Filter统一给所有Service方法都加上try—catch,来实现事物的管理
3、将所有异常都统一交给Tomcat,让Tomcat展示友好的错误信息页面
在web.xml配置错误页面跳转
第八阶段:AJAx
1、使用Ajax验证用户名是否可用
2、使用ajax修改加入购物车功能
第九阶段:
1、库存问题
2、其他模块
var msg = $(this).attr('orderMsg');
alert(msg);
标签:项目,req,lxg,book,import,com,public,书城
From: https://www.cnblogs.com/SilverStar/p/17415192.html