登录注册,文件增删查改实现
登录注册文件增删查改实现
需求:实现登录功能,注册功能。登录后文件可以进行增加删除修改查看等基本功能的操作。
知识点: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需要的相关准备
创建的是mavenweb项目,且导入mybatis框架。需要在resources资源包下导入mybatis核心配置文件。写数据库连接和资源配置文件路径等。
在java项目下创建pojo包,里面写数据库中表对应的实体类,settergetter,toString,空参,满参构造。
在java项目下创建mapper包,里面写实体类对应的mapper接口。eg:实体类User mapper下就创建UserMapper接口,一个实体类对应一个mapper
在resources资源包下创建和mapper对应路径的mapper文件名.xml。详细SQL写这里,或者java中mappe的方法上写注解。
包名解析
pojo : 存放实体类
util:存放工具类
mapper : 存放操作数据库数据的类,
service : 存放业务处理的逻辑业务类,逻辑层
web : 存放与前端交互的类,界面层
登录
思路分析:
- 用户在登录页面输入用户名和密码,提交请求给LoginServlet
- 在LoginServlet中接收请求和数据[用户名和密码]
- 在LoginServlt中通过Mybatis实现调用UserMapper来根据用户名和密码查询数据库表
- 将查询的结果封装到User对象中进行返回
- 在LoginServlet中判断返回的User对象是否为null
- 如果为null,说明根据用户名和密码没有查询到用户,则登录失败,请求转发到登录页面,携带数据(用户名或者密码不正确,请重新登录)
- 如果不为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;}
}
细节分析:
- 这个类里面可以写关于user的所有逻辑处理,现在写的是登录判断selectDL方法
- 因为这个类需要连获取数据库连接,会写好多方法,所以直接写到类里面,所有方法可用。 private私有化其他类不可以用。
private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
- 方法内调用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);}
}
细节回顾:
- 前端传来的用户名和密码里面可能会包含中文,接收数据前需要处理中文乱码。乱码数据不能正确和数据库进行比对。
request.setCharacterEncoding("utf-8");
- 在响应时,有中文字符,也需要处理响应中文乱码
// 响应数据中文乱码处理response.setContentType("text/html;charset=utf-8");
判断用户名密码正确要进入页面时,需要用session保存下用户信息,
(1) : 页面里面需要展示用户信息
(2) : 后期优化过滤登录时做登录判断
// 用户信息存入session中,方便后期过滤登录和页面使用用户信息
HttpSession session = request.getSession();
session.setAttribute("user",user);
注册
思路分析:
验证码判断,验证码错误,直接返回注册页面,不判断用户信息
验证码通过,判断用户名是否存在,存在:提示用户名存在,重新注册。
不存在:注册账号,返回登录页面。
需要一个查询语句(查询用户名是否存在),一个添加账号语句(除去查询,都需要提交事务)
- 用户在注册页面输入用户名和密码,验证码,提交请求给RegisterServlet
- 在RegisterServlet中接收请求和数据[用户名和密码和验证码]
- 在界面层判断验证码,过了进行下面判断,不过直接返回注册页面
- 在RegisterServlet中通过Mybatis实现调用UserMapper来根据用户名查询数据库表
- 将查询的结果封装到User对象中进行返回
- 在RegisterServlet中判断返回的User对象是否为null
- 如果为null,说明根据用户名可用,则调用UserMapper来实现添加用户
- 如果不为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);}
}
代码分析:
- 请求有中文。处理中文乱码
request.setCharacterEncoding("utf-8");
- 验证码输入正常业务场景需要省略大小写
// 从数据库中取数据(验证码)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,2,3步骤,先处理数据,然后数据转发到展示页面。
现在引入新技术asion结合html进行异步请求,所有是html展示,然后异步这个查询功能,直接响应数据即可,不用转发了。
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
- 回显数据,查id,返回整条数据
- 根据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 {}
}
获取的结果为:
处理中文乱码
解决乱码:POST,getReader()
request.setCharacterEncoding("UTF-8");//设置字符输入流的编码
解决乱码: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请求转发
- 请求转发(forward):一种在服务器内部的资源跳转方式。
(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
通俗将,朋友A找我借钱,我带着A找朋友B去借钱,然后B给A钱。
- 请求转发的实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);
- 请求转发资源间共享数据:使用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);}
}
- 请求转发的特点
浏览器地址栏路径不发生变化
虽然后台从
/req5
转发到/req6
,但是浏览器的地址一直是/req5
,未发生变化
只能转发到当前服务器的内部资源
不能从一个服务器通过转发访问另一台服务器
一次请求,可以在转发资源间使用request共享数据
虽然后台从
/req5
转发到/req6
,但是这个只有一次请求
Response对象
- Request:使用request对象来获取请求数据
- Response:使用response对象来设置响应数据
Respones请求重定向
- 重定向方法:
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);}
}
- 重定向的特点
浏览器地址栏路径发送变化
当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化
可以重定向到任何位置的资源(服务内容、外部均可)
因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。
两次请求,不能在多个资源使用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.重定向,是由浏览器进行跳转,需要加。
- 问题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”);
接下来,我们实现通过些案例把响应字符数据给实际应用下:
- 返回一个简单的字符串
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);}
}
- 返回一串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对象就会被销毁掉,所以不要手动关闭流。
- 返回一个中文的字符串
你好
,需要注意设置响应数据的编码为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(字节数据);
接下来,我们实现通过些案例把响应字符数据给实际应用下:
- 返回一个图片文件到浏览器
/*** 响应字节数据:设置字节数据的响应体*/
@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);}
}
登录注册,文件增删查改实现相关推荐
- SSM_用户登录注册,管理员查改删用户(spring+springmvc+mybatis),学习了一个学期写出来的
时间:2019年6月20日 一. SSM框架的简单介绍应用 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson ...
- 微信小程序万能模板(tabBar\openid\授权登录\云开发之一个云函数实现云数据库增删查改!)
Step1:新建小程序 使用自己的appid 勾选不使用云服务(后面可以在项目中再使用,这里若勾选会多出很多乱七八糟的东西) 选择不使用模板 Step2:搭建tabBar 从阿里巴巴图标库https: ...
- Access+Vs 数据库增删查改——使用Asp.net的sqldatasource控件,根据如下Universtiy.mdb数据库,处理学生注册选课与授课老师的工作
Access+Vs 数据库增删查改--使用Asp.net的sqldatasource控件,根据如下Universtiy.mdb数据库,处理学生注册选课与授课老师的工作 文章目录 Access+Vs 数 ...
- SQL Server之 (四) ADO增删查改 登录demo 带参数的sql语句 插入自动返回行号
SQL Server之 (四) ADO增删查改 登录demo 带参数的sql语句 插入自动返回行号 自己学习笔记,转载请注明出处,谢谢!---酸菜 1.什么是ADO.NET ADO.NET是一组 ...
- java解析xml文件:创建、读取、遍历、增删查改、保存
全栈工程师开发手册 (作者:栾鹏) java教程全解 java使用JDOM接口解析xml文件,包含创建.增删查改.保存,读取等操作. 需要引入jdom.jar,下载 xercesImpl.jar,下载 ...
- Python学生信息管理系统(增删查改、模糊查找、txt文件输出)# 谭子
一.系统需求说明 本项目计划实现一个学生管理系统,学生信息包括:姓名.性别.手机号码,系统包含以下功能. 模块 子模块 说明 查询模块 查询全部学生的信息 显示当前系统内所有学员的信息 查询模块 精准 ...
- 安卓后端mysql_后端Spring Boot+前端Android交互+MySQL增删查改(Java+Kotlin实现)
1 前言&概述 这篇文章是基于这篇文章的更新,主要是更新了一些技术栈以及开发工具的版本,还有修复了一些Bug. 本文是SpringBoot+Android+MySQL的增删查改的简单实现,用到 ...
- JAVA原生mvc实现用户信息的增删查改
笔者最近学完jsp和servlet,于是心血来潮的打算写个简单的用户案例 环境准备: 开发工具eclipse jdk-1.8.0_72 tomcat-9.0.5 前端部分: 1.自己手写了一套样式 2 ...
- 初学jsp课,一个基于jsp+javabean+servlet+sql server小型房源网站,实现了用户表,房源表,及留言板的增删查改。使用deamwear编译器
1 设计目的 <Web应用开发课程设计>是实践性教学环节之一,是<Web程序设计>课程的辅助教学课程.通过课程设计,使学生掌握Web网站的基本概念,结合实际的操作和设计,巩固课 ...
- spring和mybatis结合做简单的增删查改系统_springbootamp;amp;vue简单的景点信息管理系统...
springboot&&vue简单的景点信息管理系统 这两天闲着没有什么事,就根据陈哥的教程,试着写了一个springboot和vue的简单的景点信息管理系统.也就大致实现了最基本的增 ...
最新文章
- 项目怎么查服务器,服务器查询项目标签
- 全球与中国InGaAs光电二极管传感器市场投资机会与市场风险评估报告2022-2028年
- java 安卓基础面试题_android-------Java 常问的基础面试题
- 进程间通信IPC(二)(共享内存、信号、信号量)
- tibco汉化包6.3.0_TIBCO BusinessWorks 6和Container Edition与BW5的比较
- 【并发技术01】传统线程技术中创建线程的两种方式
- 苹果Mac一定要学会的快捷键
- 上采样卷积转置的deconvolution方法实现双线性插值,代码实现,结果不一样
- 银行的起源---》阮一峰,
- matlab函数总结
- 图像的灰度化和二值化
- 虚拟机运行win95
- RxSwift使用初体验
- V-SLAM重读(3):SVO代码阅读和调试修改
- CloudSim Plus任务调度策略对比
- java集成友盟实现推送
- 网页在线倍速播放视频神器enounce myspeed
- html动画图片重叠,CSS3炫酷堆叠图片展示动画特效
- android webview 找不到网页,[疑难杂症] Android WebView 无法打开天猫页面
- 嵌入式Linux 的Cramfs 根文件系统配置成可读可写