欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javaweb开发基础知识应用之实训周

程序员文章站 2024-02-26 18:53:28
...

之前一直在自己学习Javaweb的基础知识,比如学了servlet,jsp,jdbc,jstl等,输入做个实践但是都限于使用一类技术去进行巩固,即使是都用到了一些也是小作坊式的,没有条理章法。在为期五天的项目实践中让我将所有的基础知识都串起来了,也学了和理解了许多东西,所以我们打算把这个小项目的开发流程和技术做一个总结。

  1. 开发前的准备:mysql数据库,eclipse开发工具,jdbc和jstl(jsp标签库)的jar包——》在相对应的官网可以下载或者在我的百度云盘上可以下载:
    链接:https://pan.baidu.com/s/18ixwF_aT6lEnhoPpPoBBpw
    提取码:y5d3
  2. MVC开发模式的简介:javaweb开发基础知识应用之实训周
    为了节省篇幅就以一个登陆功能具体分析怎么开发
    1. 创建View层
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<!--引入jstl和核心标签库-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="LoginService" method="post">
		昵称:<input type="text" name="username" />
		密码:<input type="password" name="password" />
		<input type="submit" value="提交">
	</form>
</body>
</html>
  1. 创建数据库表

这里不累述数据库表的创建,主要创建字段及时 id,name,pass。id设为主键并且自增。

  1. 创建实体模型(pojo)(实体模型的属性与数据库的表的字段要对于)
package com.jk.blog.pojo;

public class User {
	  private Integer id;
	  private String name;
      private String pass;
      public User(int id,String name,String pass) {
    	  this.id=id;
    	  this.name=name;
    	  this.pass=pass;
      }
      public User() {}
	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 getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
}

  1. 创建数据库连接类(Dao)

封装数据库的连接和关闭操作,因为连接数据库时加载驱动只加载一次所以将它放在静态块中

package com.jk.blog.utils;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverAction;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DButils {
	private static String user = "root";
	private static String password="root";
	private static String url="url = jdbc:mysql://localhost:3306/ts_demo";
	
	//加载驱动
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		}
   }
	//创建连接
	public static Connection getConnection() {
		try {
			
			return DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	//关闭数据库
	public static void close(ResultSet rs , PreparedStatement ps, Connection conn) {
		//正向打开,逆向关闭
		try {
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			ps.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		try {
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

使用反射和可变参数封装数据库的增删改查

package com.jk.blog.dao.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jk.blog.utils.DButils;

public class BaseDao {
	private Connection conn;
	private PreparedStatement ps;
	private ResultSet rs;
	/*
	 * 根据条件查询一个对象
	 * */
	public <T>T selectOne(Class clazz,String sql,Object...param){
		conn = DButils.getConnection();
		try {
			ps = conn.prepareStatement(sql);
			if(param!=null) {//不为空在进行给占位符赋值
				for(int i=0;i<param.length;i++) {
				ps.setObject(i+1,param[i]);
				}
			}
			rs = ps.executeQuery();
			if(rs.next()) {
				//获得当前封装实体的实例
				//调用所有的set方法完成给属性赋值
				//返回这个实例
				Object obj = clazz.newInstance();//获得的是一个超类的对象
				//获得它所有的方法
				Method[] method = clazz.getDeclaredMethods();//通过类对象可以得到所有的方法
				for(Method m : method) {
					if(m.getName().startsWith("set")) {//过滤掉不是set的方法
						m.invoke(obj, rs.getObject(m.getName().substring(3).toLowerCase()));//执行set方法,第一个是这个实例,第二个是方法的值,m.getName().substring(3)从第4个开始到最后一个
					}
				}
				return (T) obj;
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
	//查询多个值
	public <T>List<T> selectAll(Class clazz,String sql,Object...param){
		List<T> list = new ArrayList<>();
		conn = DButils.getConnection();
		try {
			ps = conn.prepareStatement(sql);
			if(param!=null) {//不为空在进行给占位符赋值
				for(int i=0;i<param.length;i++) {
				ps.setObject(i+1,param[i]);
				}
			}
			rs = ps.executeQuery();
			while(rs.next()) {
				//获得当前封装实体的实例
				//调用所有的set方法完成给属性赋值
				//返回这个实例
				Object obj = clazz.newInstance();//获得的是一个超类的对象
				//获得它所有的方法
				Method[] method = clazz.getDeclaredMethods();//通过类对象可以得到所有的方法
				for(Method m : method) {
					if(m.getName().startsWith("set")) {//过滤掉不是set的方法
						m.invoke(obj, rs.getObject(m.getName().substring(3).toLowerCase()));//执行set方法,第一个是这个实例,第二个是方法的值,m.getName().substring(3)从第4个开始到最后一个
						
					}
				}
				list.add((T) obj);
			}
			return list;
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
	//插入多个值
	public void insertAll(String sql,Object...param){
		conn = DButils.getConnection();
		try {
			ps = conn.prepareStatement(sql);
			if(param!=null) {//不为空在进行给占位符赋值
				for(int i=0;i<param.length;i++) {
				ps.setObject(i+1,param[i]);
				}
			}
			ps.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		}
		
	}
	//删除一个值

创建操作数据库的类

public class UserDao{

	private Connection conn;
	private PreparedStatement ps;
	private ResultSet rs;

	@Override
	public User verifyUser(String name ,String pass) {
		User user=null;//创建登录的实体类,并且赋值为null
		conn = DButils.getConnection();//根据封装的类得到数据库连接
		String sql="SELECT id,name,pass FROM user_table where name=? and pass=?";
		try {
			ps = conn.prepareStatement(sql);
			ps.setString(1, name);
			ps.setString(2, pass);
			rs = ps.executeQuery();
			
			if(rs.next()) {//rs.next 就将指针指向下一行,所以后面在使用就是其他的行了
				user = new User(rs.getInt(1),rs.getString(2), rs.getString(3));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			DButils.close(rs, ps, conn);
			}
		return user;
	}
	
}
  1. 创建servlet
    使用反射封装servlet的(service方法会覆盖doPost方法和doGet方法)
package com.jk.blog.service;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class BaseServlet
 */
@WebServlet("/BaseServlet")
public class BaseService extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String action = request.getParameter("action");//在传数据表单的时候必须带一个action属性,通过反射会去找和它对于的servlet方法,进行数据的处理
		System.out.println(action);
		Class clazz = this.getClass();///获得子类的类对象
		try {
			Method method = clazz.getDeclaredMethod(action, HttpServletRequest.class,HttpServletResponse.class);//获得给子类对象的action对应的方法
			method.invoke(this, request,response);//执行方法:第一个是类对象,后面是本方法的参数
		} catch (NoSuchMethodException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

}

//创建service的子类

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jk.blog.dao.impl.ArticleDaoImpl;
import com.jk.blog.dao.impl.ArticleSortDaoImpl;
import com.jk.blog.dao.impl.UserDaoIpml;
import com.jk.blog.pojo.Article;
import com.jk.blog.pojo.ArticleSort;
import com.jk.blog.pojo.User;

/**
 * Servlet implementation class LoginServlice
 */
@WebServlet("/LoginService")
public class LoginService extends BaseService {//继承父类
	private static final long serialVersionUID = 1L;
	private UserDao uDao = new  UserDao;//查询类
	protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String name = request.getParameter("username");
		String password = request.getParameter("password");
		
		User user = uDao.verifyUser(name, password);返回一个User对象
		if(user!=null) {//不为空登录成功转发到主页面
			request.getRequestDispatcher("index.jsp").forward(request, response);
		}else{//登录不成功,携带错误信息转发到登录页面重新登录
		request.setAttribute("error", "没有该用户信息!");
		request.getRequestDispatcher("login.jsp").forward(request, response);
		}
	}
	

总结

反射技术

封装数据库操作类和servlet的时候都使用了反射技术,
获得本类的类对象的技术主要有三种

三种方式如下:
a、超类Object方法getClass()
b、Class.forName(className);
c、类.class
要执行本类的某一方法的时候

Method method = clazz.getDeclaredMethod(方法名, 参数(可变型).class);//获得给子类对象的action对应的方法
			method.invoke(this, 参数(可以多个也可以没有));//执行方法:第一个是类对象,后面是本方法的参数

封装

在开发的过程中将重复的代码进行合理的封装会大大降低开发的代码复杂度,减少重复代码,方便维护

心得

在本次的实践周中,不是学到了多少的新技术,而是可以将以前学过的散装技术打包成可以用于实际开发的技术,这可能比学一些新的技术更加的重要,总言之,在这5天中有很多的bug虽然让人崩溃,大多数就是对这中开发流程的不熟悉导致的,在后面慢慢的理解和渐渐的熟悉这种开发流程后很明显的开发的效率有所提升,就连bug也出的有技术含量了,哈哈哈!