登录注册文件增删查改实现

需求:实现登录功能,注册功能。登录后文件可以进行增加删除修改查看等基本功能的操作。

知识点:mybatis ,Tomcat,servlet , asion , json ,req , resp ,session

前提准备:

pom.xml坐标导入:

导入Mybatis和Mysql驱动坐标,日志坐标,Servlet坐标

 <dependencies><!--mybatis环境--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.3</version></dependency><!--mysql环境--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--分页插件坐标--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.2</version></dependency><!--servlet环境--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--jstl--><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency><!--其他组件--><!--junit单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.20</version></dependency><!-- 添加logback-classic依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- 添加logback-core依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency></dependencies><build><plugins><!-- tomcat 插件 --><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><port>80</port><path>/</path><uriEncoding>utf-8</uriEncoding></configuration></plugin></plugins></build>

mybatis需要的相关准备

  1. 创建的是mavenweb项目,且导入mybatis框架。需要在resources资源包下导入mybatis核心配置文件。写数据库连接和资源配置文件路径等。

  2. 在java项目下创建pojo包,里面写数据库中表对应的实体类,settergetter,toString,空参,满参构造。

  3. 在java项目下创建mapper包,里面写实体类对应的mapper接口。eg:实体类User mapper下就创建UserMapper接口,一个实体类对应一个mapper

  4. 在resources资源包下创建和mapper对应路径的mapper文件名.xml。详细SQL写这里,或者java中mappe的方法上写注解。

包名解析

pojo : 存放实体类

util:存放工具类

mapper : 存放操作数据库数据的类,

service : 存放业务处理的逻辑业务类,逻辑层

web : 存放与前端交互的类,界面层

登录

思路分析:

  1. 用户在登录页面输入用户名和密码,提交请求给LoginServlet
  2. 在LoginServlet中接收请求和数据[用户名和密码]
  3. 在LoginServlt中通过Mybatis实现调用UserMapper来根据用户名和密码查询数据库表
  4. 将查询的结果封装到User对象中进行返回
  5. 在LoginServlet中判断返回的User对象是否为null
  6. 如果为null,说明根据用户名和密码没有查询到用户,则登录失败,请求转发到登录页面,携带数据(用户名或者密码不正确,请重新登录)
  7. 如果不为null,则说明用户存在并且密码正确,则登录成功,请求转发到查询所有页面

代码实现:

数据处理mapper

写根据用户名和密码查询数据,返回一个user对象。给逻辑层查询使用

public interface UserMapper {//查询是否有这个用户名密码@Select("select * from tb_user where username=#{username} and password=#{password}")User selectNP(User user);
}

细节解析:这个接口中查询用户名和密码是否存在,是一个简单SQL查询。可以直接使用注解。

​ 查出来就是一条数据,没有数据就返回null

逻辑层

接收界面层传入数据,写一个对应的用户登录验证方法。类:UserService

public class UserService {//  获取数据库连接方式。使用了工具类private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();// 判断登录的方法public User selectDL(User user) {//1. 获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();//  2,调用登录对比查询方法UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user1 = mapper.selectNP(user);//  3, 返回数据return user1;}
}

细节分析:

  1. 这个类里面可以写关于user的所有逻辑处理,现在写的是登录判断selectDL方法
  2. 因为这个类需要连获取数据库连接,会写好多方法,所以直接写到类里面,所有方法可用。 private私有化其他类不可以用。
private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
  1. 方法内调用mapper中写的SQL语句,返回数据即可。

界面层:

接收请求和数据,判断是否登录成功,响应数据

//  登录
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 处理请求数据中文乱码request.setCharacterEncoding("utf-8");
//1.接收用户数据String username = request.getParameter("username");String password = request.getParameter("password");//2.封装用户对象User user = new User();user.setUsername(username);user.setPassword(password);//3.调用逻辑层进行判断UserService userService = new UserService();User user1 = userService.selectDL(user);//4. 判断用户对象是否为null// 响应数据中文乱码处理response.setContentType("text/html;charset=utf-8");if( user1 == null){// 用户名信息错误,返回提示信息和登录页面request.setAttribute("login_msg","用户名或密码错误");// 跳转到login.jsp,请求转发页面上路径不变,不走网络,直接要跳转到位置即可request.getRequestDispatcher("/login.jsp").forward(request,response);}else {//用户登录成功,显示用户信息和进入里面.携带用户信息// 用户信息存入session中,方便后期过滤登录和页面使用用户信息HttpSession session = request.getSession();session.setAttribute("user",user);request.getRequestDispatcher("/brand.html").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

细节回顾:

  1. 前端传来的用户名和密码里面可能会包含中文,接收数据前需要处理中文乱码。乱码数据不能正确和数据库进行比对。
request.setCharacterEncoding("utf-8");
  1. 在响应时,有中文字符,也需要处理响应中文乱码
 // 响应数据中文乱码处理response.setContentType("text/html;charset=utf-8");
  1. 判断用户名密码正确要进入页面时,需要用session保存下用户信息,

    (1) : 页面里面需要展示用户信息

    (2) : 后期优化过滤登录时做登录判断

// 用户信息存入session中,方便后期过滤登录和页面使用用户信息
HttpSession session = request.getSession();
session.setAttribute("user",user);

注册

思路分析:

  1. 验证码判断,验证码错误,直接返回注册页面,不判断用户信息

  2. 验证码通过,判断用户名是否存在,存在:提示用户名存在,重新注册。

​ 不存在:注册账号,返回登录页面。

需要一个查询语句(查询用户名是否存在),一个添加账号语句(除去查询,都需要提交事务)

  1. 用户在注册页面输入用户名和密码,验证码,提交请求给RegisterServlet
  2. 在RegisterServlet中接收请求和数据[用户名和密码和验证码]
  3. 在界面层判断验证码,过了进行下面判断,不过直接返回注册页面
  4. 在RegisterServlet中通过Mybatis实现调用UserMapper来根据用户名查询数据库表
  5. 将查询的结果封装到User对象中进行返回
  6. 在RegisterServlet中判断返回的User对象是否为null
  7. 如果为null,说明根据用户名可用,则调用UserMapper来实现添加用户
  8. 如果不为null,则说明用户不可以,返回"用户名已存在"数据给前端

代码实现

mapper

查询用户名和添加账号两个SQL直接写

public interface UserMapper {//    查询是否用户名存在@Select("select * from tb_user where username=#{username}")User selectName(String username);//   添加用户名,密码@Insert("INSERT into  tb_user(username,password) VALUES (#{username},#{password})")int insertNP(User user);
}

逻辑层

写两个方法,一个验证用户名,一个添加账号

public class UserService {//   获取数据库连接方式private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();// 查询数据库用户名是否存在public User selectName(String username) {//        获取数据库连接SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);return mapper.selectName(username);}//添加数据,注册账号public int inster(User user) {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        返回影响行数int i = mapper.insertNP(user);sqlSession.commit();// 提交事务return i;}
}

**代码分析:**添加数据方法返回int,添加成功 mapper.insertNP(user)返回影响行数,若是返回0,就是没有添加。

界面层

接收注册的用户名和密码,验证码,调用逻辑层代码进行判断。

把数据库里面的验证码和前端传来的验证码进行对比。

判断用户名是否存在,存在:直接返回注册页面重新注册,给出提示。

​ 不存在:添加账号,返回登录页面。

// 注册
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");//1. 接收用户数据String username = request.getParameter("username");String password = request.getParameter("password");String checkCode = request.getParameter("checkCode");  //验证码// 先判断验证码是否正确,再进行用户名重复判断HttpSession session = request.getSession();String yzm = (String) session.getAttribute("yzm");if(!yzm.equalsIgnoreCase(checkCode)){// 如果不相等,直接结束判断,重新输入// 验证码错误,忽略大小写request.setAttribute("register_msg","验证码错误,请重新输入");// 转发到注册页面request.getRequestDispatcher("/register.jsp").forward(request,response);return;// 不再往下执行}//封装用户对象User user = new User();user.setUsername(username);user.setPassword(password);UserService service = new UserService();User user1 = service.selectName(username);if( user1 == null){// 用户名不存在,添加用户 返回提示信息和登录页面service.inster(user);request.setAttribute("login_msg","注册成功啦,请登录");// 转发到登录页面request.getRequestDispatcher("/login.jsp").forward(request,response);}else {// 用户名存在,给出提示信息request.setAttribute("register_msg","此用户名已存在,请重新注册");// 转发到注册页面request.getRequestDispatcher("/register.jsp").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

代码分析:

  1. 请求有中文。处理中文乱码
 request.setCharacterEncoding("utf-8");
  1. 验证码输入正常业务场景需要省略大小写
  // 从数据库中取数据(验证码)HttpSession session = request.getSession();String yzm = (String) session.getAttribute("yzm");// 验证码对比,忽略大小写if(!yzm.equalsIgnoreCase(checkCode)){// 如果不相等,直接结束判断,重新输入  // 业务代码...return;// 不再往下执行}

工具类(验证码)

util中:

/*** 生成验证码工具类*/
public class CheckCodeUtil {public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";private static Random random = new Random();/*** 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)** @param width 图片宽度* @param height 图片高度* @param os  输出流* @param verifySize 数据长度* @return 验证码数据* @throws IOException*/public static String outputVerifyImage(int width, int height, OutputStream os, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(width, height, os, verifyCode);return verifyCode;}/*** 使用系统默认字符源生成验证码** @param verifySize 验证码长度* @return*/public static String generateVerifyCode(int verifySize) {return generateVerifyCode(verifySize, VERIFY_CODES);}/*** 使用指定源生成验证码** @param verifySize 验证码长度* @param sources    验证码字符源* @return*/public static String generateVerifyCode(int verifySize, String sources) {// 未设定展示源的字码,赋默认值大写字母+数字if (sources == null || sources.length() == 0) {sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for (int i = 0; i < verifySize; i++) {verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));}return verifyCode.toString();}/*** 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少)** @param w* @param h* @param outputFile* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件** @param w* @param h* @param outputFile* @param code* @throws IOException*/public static void outputImage(int w, int h, File outputFile, String code) throws IOException {if (outputFile == null) {return;}File dir = outputFile.getParentFile();//文件不存在if (!dir.exists()) {//创建dir.mkdirs();}try {outputFile.createNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch (IOException e) {throw e;}}/*** 输出指定验证码图片流** @param w* @param h* @param os* @param code* @throws IOException*/public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = image.createGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 创建颜色集合,使用java.awt包下的类Color[] colors = new Color[5];Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,Color.PINK, Color.YELLOW};float[] fractions = new float[colors.length];for (int i = 0; i < colors.length; i++) {colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];fractions[i] = rand.nextFloat();}Arrays.sort(fractions);// 设置边框色g2.setColor(Color.GRAY);g2.fillRect(0, 0, w, h);Color c = getRandColor(200, 250);// 设置背景色g2.setColor(c);g2.fillRect(0, 2, w, h - 4);// 绘制干扰线Random random = new Random();// 设置线条的颜色g2.setColor(getRandColor(160, 200));for (int i = 0; i < 20; i++) {int x = random.nextInt(w - 1);int y = random.nextInt(h - 1);int xl = random.nextInt(6) + 1;int yl = random.nextInt(12) + 1;g2.drawLine(x, y, x + xl + 40, y + yl + 20);}// 添加噪点// 噪声率float yawpRate = 0.05f;int area = (int) (yawpRate * w * h);for (int i = 0; i < area; i++) {int x = random.nextInt(w);int y = random.nextInt(h);// 获取随机颜色int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}// 添加图片扭曲shear(g2, w, h, c);g2.setColor(getRandColor(100, 160));int fontSize = h - 4;Font font = new Font("Algerian", Font.ITALIC, fontSize);g2.setFont(font);char[] chars = code.toCharArray();for (int i = 0; i < verifySize; i++) {AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);g2.setTransform(affine);g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);}g2.dispose();ImageIO.write(image, "jpg", os);}/*** 随机颜色** @param fc* @param bc* @return*/private static Color getRandColor(int fc, int bc) {if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = random.nextInt(255);}return rgb;}private static void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private static void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private static void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}
}

web调用工具类:

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//        生成验证码ServletOutputStream os = response.getOutputStream();String s = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);//         存入session中,验证码是一存一取一验证HttpSession session = request.getSession();session.setAttribute("yzm",s);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

验证码是一刷新换一张,所以需要清理缓存;

在前端里面:刷新数据是带参数,形成新的页面。参数用时间显示,一秒一个。

<script>document.getElementById("changeImg").onclick = function () {document.getElementById("checkCodeImg").src = "/checkCodeServlet?" + new Date().getMilliseconds();}
</script>

查询所有数据:

思路分析:

账号验证后,进入页面,直接展示所有数据。就是登录界面层跳转到查询所有的界面层。

查询不需要前端请求参数,直接查询,在页面展示即可。

mapper层代码

因为实体类名称有些和数据库列名不一致

需要在对应的.xml文件标注

<resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"></result><result column="company_name" property="companyName"></result></resultMap>
public interface BrandMapper {//    查询所有数据返回到 List集合中@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand> selectAll();}

逻辑层

public class BrandService {private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();//    查询所有数据,调用对应方法(数据库)public List<Brand> selectAll() {//     调用工具类中获取mybatis连接的方法//获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);List<Brand> brands = mapper.selectAll();sqlSession.close();return brands;}
}

页面层代码

  1. 正常应该是1,2,3步骤,先处理数据,然后数据转发到展示页面。

  2. 现在引入新技术asion结合html进行异步请求,所有是html展示,然后异步这个查询功能,直接响应数据即可,不用转发了。

  3. JSON是一种新的编码语言,下面详细写(需要坐标依赖)

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//        查询所有表单//1. 调用BrandService完成查询BrandService service = new BrandService();List<Brand> brands = service.selectAll();// 设置编码,处理中文乱码问题text/json,针对jsonString s = JSON.toJSONString(brands);response.setContentType("text/json;charset=utf-8");//A. 响应数据  application/json   text/jsonresponse.getWriter().write(s);//2. 存入request域中
//        request.setAttribute("brands",brands);//3. 转发到brand.jsp
//        request.getRequestDispatcher("/brand.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

添加数据

brand.jsp展示数据时,有添加按钮,会跳转到添加页面:addBrand.jsp。

addBrand.jsp会把请求参数传入后端。

思路分析:

后台接收请求数据,进行封装,然后给逻辑层,逻辑层调用mapper中对应的添加功能,完成添加。

上图是做 添加 功能流程。点击 新增 按钮后,会先跳转到 addBrand.jsp 新增页面,在该页面输入要添加的数据,输入完毕后点击 提交 按钮,需要将数据提交到后端,而后端进行数据添加操作,并重新将所有的数据查询出来。整个流程如下:

接下来我们根据流程来实现功能:(使用了Ajax的ASION工具+html)就直接跳转到查询,直接跳转到展示页面,Brand.html,html自己异步请求查询即可。

代码实现

mapper层

public interface BrandMapper {//    添加商品数据@Insert("INSERT into tb_brand VALUES(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")@ResultMap("brandResultMap")void add(Brand brand);
}

逻辑层

public class BrandService {private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();//     添加商品数据public void add(Brand brand){SqlSession sqlSession = sqlSessionFactory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);mapper.add(brand);sqlSession.commit();// 提交事务sqlSession.close();}
}

界面层

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//       处理中文乱码request.setCharacterEncoding("utf-8");
//        获取用户信息String brandName = request.getParameter("brandName");String companyName = request.getParameter("companyName");String ordered = request.getParameter("ordered");  //IntegerString description = request.getParameter("description");String status = request.getParameter("status");  //IntegerInteger orderedInteger = Integer.getInteger(ordered);Integer statusInteger = Integer.getInteger(status);//        封装Brand brand = new Brand(null, brandName, companyName, orderedInteger, description, statusInteger);BrandService service = new BrandService();service.add(brand);//     转发request.getRequestDispatcher("/brand.html").forward(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

修改数据

根据id修改,修改时需要显示数据(数据回显)。然后修改提交。

有待提高:可以动态修改,全部不修改不调用修改功能

mapper:

根据id修改,不可以修改id

  1. 回显数据,查id,返回整条数据
  2. 根据id修改数据
public interface BrandMapper {//根据id回显数据@Select("select * from tb_brand where id = #{id}")@ResultMap("brandResultMap")Brand selectId(Integer id);//    根据id修改数据@Update("UPDATE tb_brand set brand_name = #{brandName} ,company_name = #{companyName} ," +"ordered=#{ordered},description=#{description},status=#{status} where id=#{id}")@ResultMap("brandResultMap")void updateBrand(Brand brand);}

逻辑层

public class BrandService {private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();//    修改时的回显数据public Brand selectId(Integer id){SqlSession sqlSession = sqlSessionFactory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);Brand brand = mapper.selectId(id);return brand;}//    修改商品信息public void updateBrand(Brand brand) {SqlSession sqlSession = sqlSessionFactory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);mapper.updateBrand(brand);sqlSession.commit();sqlSession.close();}
}

页面层

回显数据代码

//修改时的回显数据
@WebServlet("/selectByIdServlet")
public class SelectByIdServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String id = request.getParameter("id");Integer idInteger = Integer.parseInt(id);BrandService service = new BrandService();Brand brand = service.selectId(idInteger);request.setAttribute("brand",brand);request.getRequestDispatcher("/update.jsp").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

修改数据代码

@WebServlet("/updateServlet")
public class UpdateServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//处理POST请求的乱码问题request.setCharacterEncoding("utf-8");// 获取信息String id = request.getParameter("id");String brandName = request.getParameter("brandName");String companyName = request.getParameter("companyName");String ordered = request.getParameter("ordered");String description = request.getParameter("description");String status = request.getParameter("status");Integer idInteger = Integer.parseInt(id);Integer orderedInteger = Integer.parseInt(ordered);Integer statusInteger = Integer.parseInt(status);// 封装信息Brand brand = new Brand(idInteger, brandName, companyName, orderedInteger, description, statusInteger);BrandService service = new BrandService();service.updateBrand(brand);request.getRequestDispatcher("/brand.html").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

删除数据

根据id删除。

有待提高:给出提示,确认要删除吗,删除后可以查看已删除数据,永久删除等。

mapper

public interface BrandMapper {//    根据id删除@Delete("DELETE from tb_brand where id=#{id}")@ResultMap("brandResultMap")int dlectId(Integer id);
}

逻辑层

public class BrandService {private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();//    根据id删除商品数据public int deleteId(Integer id) {//2. 获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);int i = mapper.dlectId(id);sqlSession.commit();sqlSession.close();return i;}
}

页面层

@WebServlet("/deleteIdServlet")
public class DeleteIdServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String id = request.getParameter("id");Integer i = Integer.parseInt(id);BrandService service = new BrandService();int deleteId = service.deleteId(i);request.getRequestDispatcher("/brand.html").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

请求响应常见方法

request对象:

常见方法

  • 获取所有参数Map集合
Map<String,String[]> getParameterMap()
  • 根据名称获取参数值(数组)
String[] getParameterValues(String name)
  • 根据名称获取参数值(单个值)
String getParameter(String name)

接下来,我们通过案例来把上述的三个方法进行实例演示:

1.修改req.html页面,添加爱好选项,爱好可以同时选多个

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/request-demo/req2" method="get"><input type="text" name="username"><br><input type="password" name="password"><br><input type="checkbox" name="hobby" value="1"> 游泳<input type="checkbox" name="hobby" value="2"> 爬山 <br><input type="submit"></form>
</body>
</html>

2.在Servlet代码中获取页面传递GET请求的参数值

2.1获取GET方式的所有请求参数

/*** request 通用方式获取请求参数*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑System.out.println("get....");//1. 获取所有参数的Map集合Map<String, String[]> map = req.getParameterMap();for (String key : map.keySet()) {// username:zhangsan lisiSystem.out.print(key+":");//获取值String[] values = map.get(key);for (String value : values) {System.out.print(value + " ");}System.out.println();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}

获取的结果为:

2.2获取GET请求参数中的爱好,结果是数组值

/*** request 通用方式获取请求参数*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑//...System.out.println("------------");String[] hobbies = req.getParameterValues("hobby");for (String hobby : hobbies) {System.out.println(hobby);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}

获取的结果为:

2.3获取GET请求参数中的用户名和密码,结果是单个值

/*** request 通用方式获取请求参数*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑//...String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username);System.out.println(password);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}

获取的结果为:

处理中文乱码

  1. 解决乱码:POST,getReader()

        request.setCharacterEncoding("UTF-8");//设置字符输入流的编码
    
  2. 解决乱码:get,获取参数的方式:getQueryString

// 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
/* //3.1 先对乱码数据进行编码:转为字节数组
byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
//3.2 字节数组解码
username = new String(bytes, StandardCharsets.UTF_8);*/username  = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);

Request请求转发

  1. 请求转发(forward):一种在服务器内部的资源跳转方式。

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求

(2)资源A处理完请求后将请求发给资源B

(3)资源B处理完后将结果响应给浏览器

(4)请求从资源A到资源B的过程就叫请求转发

通俗将,朋友A找我借钱,我带着A找朋友B去借钱,然后B给A钱。

  1. 请求转发的实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);
  1. 请求转发资源间共享数据:使用Request对象

此处主要解决的问题是把请求从/req5转发到/req6的时候,如何传递数据给/req6

需要使用request对象提供的三个方法:

  • 存储数据到request域[范围,数据是存储在request对象]中
void setAttribute(String name,Object o);
  • 根据key获取值
Object getAttribute(String name);
  • 根据key删除该键值对
void removeAttribute(String name);

接着上个需求来:

1.在RequestDemo5的doGet方法中转发请求之前,将数据存入request域对象中

2.在RequestDemo6的doGet方法从request域对象中获取数据,并将数据打印到控制台

3.启动访问测试

(1)修改RequestDemo5中的方法

@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("demo5...");//存储数据request.setAttribute("msg","hello");//请求转发request.getRequestDispatcher("/req6").forward(request,response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

(2)修改RequestDemo6中的方法

/*** 请求转发*/
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("demo6...");//获取数据Object msg = request.getAttribute("msg");System.out.println(msg);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
  1. 请求转发的特点
  • 浏览器地址栏路径不发生变化

    虽然后台从/req5转发到/req6,但是浏览器的地址一直是/req5,未发生变化

  • 只能转发到当前服务器的内部资源

    不能从一个服务器通过转发访问另一台服务器

  • 一次请求,可以在转发资源间使用request共享数据

    虽然后台从/req5转发到/req6,但是这个只有一次请求

Response对象

  • Request:使用request对象来获取请求数据
  • Response:使用response对象来设置响应数据

Respones请求重定向

  1. 重定向方法:
resposne.sendRedirect("全部路径(模块名+路径名)");
//resposne.sendRedirect("/request-demo/resp2");

代码实现:

@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("resp1....");//重定向resposne.sendRedirect("/request-demo/resp2");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
  1. 重定向的特点
  • 浏览器地址栏路径发送变化

    当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化

  • 可以重定向到任何位置的资源(服务内容、外部均可)

    因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。

  • 两次请求,不能在多个资源使用request共享数据

    因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据

介绍完请求重定向和请求转发以后,接下来需要把这两个放在一块对比下:


重定向需要全部路径,模块名,路径防止错误和修改可以直接使用方法

request.getContextPath();
    //简化方式完成重定向//动态获取虚拟目录String contextPath = request.getContextPath();response.sendRedirect(contextPath+"/resp2");

路径问题

问题1:转发的时候路径上没有加/request-demo而重定向加了,那么到底什么时候需要加,什么时候不需要加呢?

其实判断的依据很简单,只需要记住下面的规则即可:

  • 浏览器使用:需要加虚拟目录(项目访问路径)
  • 服务端使用:不需要加虚拟目录

对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录

对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。

掌握了这个规则,接下来就通过一些练习来强化下知识的学习:

  • <a href='路劲'>
  • <form action='路径'>
  • req.getRequestDispatcher(“路径”)
  • resp.sendRedirect(“路径”)

答案:

1.超链接,从浏览器发送,需要加
2.表单,从浏览器发送,需要加
3.转发,是从服务器内部跳转,不需要加
4.重定向,是由浏览器进行跳转,需要加。
  1. 问题2:在重定向的代码中,/request-demo是固定编码的,如果后期通过Tomcat插件配置了项目的访问路径,那么所有需要重定向的地方都需要重新修改,该如何优化?

    可以在代码中动态去获取项目访问的虚拟目录,借助request对象中的getContextPath()方法,

重定向需要全部路径,模块名,路径防止错误和修改可以直接使用方法

request.getContextPath();
    //简化方式完成重定向//动态获取虚拟目录String contextPath = request.getContextPath();response.sendRedirect(contextPath+"/resp2");

Response响应字符数据

要想将字符数据写回到浏览器,我们需要两个步骤:

  • 通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();

  • 通过字符输出流写数据: writer.write(“aaa”);

接下来,我们实现通过些案例把响应字符数据给实际应用下:

  1. 返回一个简单的字符串aaa
/*** 响应字符数据:设置字符数据的响应体*/
@WebServlet("/resp3")
public class ResponseDemo3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");//1. 获取字符输出流PrintWriter writer = response.getWriter();writer.write("aaa");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

  1. 返回一串html字符串,并且能被浏览器解析
response.setHeader("content-type","text/html");
PrintWriter writer = response.getWriter();
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");

==注意:==一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。

  1. 返回一个中文的字符串你好,需要注意设置响应数据的编码为utf-8
//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");

总结:

响应

response.setContentType("text/html;charset=utf-8");
writer.write("aaa");

响应数据写html,识别html标签

//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");

响应中文数据,解决中文乱码

//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");

Response响应字节数据

要想将字节数据写回到浏览器,我们需要两个步骤:

  • 通过Response对象获取字节输出流:
ServletOutputStream outputStream = resp.getOutputStream();
  • 通过字节输出流写数据:
outputStream.write(字节数据);

接下来,我们实现通过些案例把响应字符数据给实际应用下:

  1. 返回一个图片文件到浏览器
/*** 响应字节数据:设置字节数据的响应体*/
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 读取文件FileInputStream fis = new FileInputStream("d://a.jpg");//2. 获取response字节输出流ServletOutputStream os = response.getOutputStream();//3. 完成流的copybyte[] buff = new byte[1024];int len = 0;while ((len = fis.read(buff))!= -1){os.write(buff,0,len);}fis.close();}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

上述代码中,对于流的copy的代码还是比较复杂的,所以我们可以使用别人提供好的方法来简化代码的开发,具体的步骤是:

(1)pom.xml添加依赖

<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>

(2)调用工具类方法

//fis:输入流
//os:输出流
IOUtils.copy(fis,os);

优化后的代码:

/*** 响应字节数据:设置字节数据的响应体*/
@WebServlet("/resp4")
public class ResponseDemo4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 读取文件FileInputStream fis = new FileInputStream("d://a.jpg");//2. 获取response字节输出流ServletOutputStream os = response.getOutputStream();//3. 完成流的copyIOUtils.copy(fis,os);fis.close();}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}

登录注册,文件增删查改实现相关推荐

  1. SSM_用户登录注册,管理员查改删用户(spring+springmvc+mybatis),学习了一个学期写出来的

    时间:2019年6月20日 一. SSM框架的简单介绍应用 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson ...

  2. 微信小程序万能模板(tabBar\openid\授权登录\云开发之一个云函数实现云数据库增删查改!)

    Step1:新建小程序 使用自己的appid 勾选不使用云服务(后面可以在项目中再使用,这里若勾选会多出很多乱七八糟的东西) 选择不使用模板 Step2:搭建tabBar 从阿里巴巴图标库https: ...

  3. Access+Vs 数据库增删查改——使用Asp.net的sqldatasource控件,根据如下Universtiy.mdb数据库,处理学生注册选课与授课老师的工作

    Access+Vs 数据库增删查改--使用Asp.net的sqldatasource控件,根据如下Universtiy.mdb数据库,处理学生注册选课与授课老师的工作 文章目录 Access+Vs 数 ...

  4. SQL Server之 (四) ADO增删查改 登录demo 带参数的sql语句 插入自动返回行号

    SQL Server之 (四) ADO增删查改  登录demo  带参数的sql语句  插入自动返回行号 自己学习笔记,转载请注明出处,谢谢!---酸菜 1.什么是ADO.NET ADO.NET是一组 ...

  5. java解析xml文件:创建、读取、遍历、增删查改、保存

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java使用JDOM接口解析xml文件,包含创建.增删查改.保存,读取等操作. 需要引入jdom.jar,下载 xercesImpl.jar,下载 ...

  6. Python学生信息管理系统(增删查改、模糊查找、txt文件输出)# 谭子

    一.系统需求说明 本项目计划实现一个学生管理系统,学生信息包括:姓名.性别.手机号码,系统包含以下功能. 模块 子模块 说明 查询模块 查询全部学生的信息 显示当前系统内所有学员的信息 查询模块 精准 ...

  7. 安卓后端mysql_后端Spring Boot+前端Android交互+MySQL增删查改(Java+Kotlin实现)

    1 前言&概述 这篇文章是基于这篇文章的更新,主要是更新了一些技术栈以及开发工具的版本,还有修复了一些Bug. 本文是SpringBoot+Android+MySQL的增删查改的简单实现,用到 ...

  8. JAVA原生mvc实现用户信息的增删查改

    笔者最近学完jsp和servlet,于是心血来潮的打算写个简单的用户案例 环境准备: 开发工具eclipse jdk-1.8.0_72 tomcat-9.0.5 前端部分: 1.自己手写了一套样式 2 ...

  9. 初学jsp课,一个基于jsp+javabean+servlet+sql server小型房源网站,实现了用户表,房源表,及留言板的增删查改。使用deamwear编译器

    1 设计目的 <Web应用开发课程设计>是实践性教学环节之一,是<Web程序设计>课程的辅助教学课程.通过课程设计,使学生掌握Web网站的基本概念,结合实际的操作和设计,巩固课 ...

  10. spring和mybatis结合做简单的增删查改系统_springbootamp;amp;vue简单的景点信息管理系统...

    springboot&&vue简单的景点信息管理系统 这两天闲着没有什么事,就根据陈哥的教程,试着写了一个springboot和vue的简单的景点信息管理系统.也就大致实现了最基本的增 ...

最新文章

  1. 项目怎么查服务器,服务器查询项目标签
  2. 全球与中国InGaAs光电二极管传感器市场投资机会与市场风险评估报告2022-2028年
  3. java 安卓基础面试题_android-------Java 常问的基础面试题
  4. 进程间通信IPC(二)(共享内存、信号、信号量)
  5. tibco汉化包6.3.0_TIBCO BusinessWorks 6和Container Edition与BW5的比较
  6. 【并发技术01】传统线程技术中创建线程的两种方式
  7. 苹果Mac一定要学会的快捷键
  8. 上采样卷积转置的deconvolution方法实现双线性插值,代码实现,结果不一样
  9. 银行的起源---》阮一峰,
  10. matlab函数总结
  11. 图像的灰度化和二值化
  12. 虚拟机运行win95
  13. RxSwift使用初体验
  14. V-SLAM重读(3):SVO代码阅读和调试修改
  15. CloudSim Plus任务调度策略对比
  16. java集成友盟实现推送
  17. 网页在线倍速播放视频神器enounce myspeed
  18. html动画图片重叠,CSS3炫酷堆叠图片展示动画特效
  19. android webview 找不到网页,[疑难杂症] Android WebView 无法打开天猫页面
  20. 嵌入式Linux 的Cramfs 根文件系统配置成可读可写

热门文章

  1. excel表格打印每页都有表头_如何给将要打印的excel表格设置统一的表头
  2. 反函数法生成服从特定概率密度函数的随机数
  3. 老男孩网络安全第八期
  4. SQLServer下载安装详细图解
  5. 如何配置luogu,codeforces的spj(special judge)
  6. Hadoop初入门的坑
  7. 刚性捆绑,无线运营新模式
  8. DirectX11海洋模拟实践
  9. 温德姆集团加速麦客达品牌在华扩张;柏悦酒店将进驻长沙;希尔顿惠庭中国首店将在深圳开业 | 美通社头条...
  10. 水深6到9米有鱼吗_红黄尾鲴鱼钓法大全(附配方)