java web中分层MVC的意义
在web编程中,由于高内聚、低耦合的特点,需要将多个类实现多层,大致有以下几层:
①entity,实体类,如user,role等,这些类里边包含了私有属性和公共的get、set方法这和数据库中的表相对应,更严格一些,包括字段的顺序和type都要保持一致。
②base,封装了基本的操作数据库的方法(增删改查)
③dao,访问并操作数据库,若想从数据库获取数据,必须调用dao层。dao层没有一点业务逻辑,全是跟数据库操作有关的类
④service,业务逻辑层,里边可以是接口。只要没有访问数据库的操作,都写到service层中。
举个例子说明什么是业务。如做一个分页功能,数据1000条,每页20条,则可以把这个功能写成工具类封装起来,然后在业务层调用这个封装的方法,这才是业务层要做的事。
service层和dao层有什么区别?
再举个例子,如注册用户时,还想往日志表里添加一个日志,那么就要在业务层来实现这个操作,并对该操作添加事务,效果会更好。若不使用service,只用dao的话,那么就要连续使用userDao和logDao,那么万一某一步出错,就可能造成user加进去而log没有添加成功。
⑤action,也就是原来的servlet,位于jsp和service层之间进行交互。主要的操作就是请求(request)和响应(response)。存取某个功能的整体实现方法。
以后不要在servlet中调用dao层,而要写到serviceImpl(对接口的实现层)中,如以前的userServlet中有
private UserDao udao = new UserDaoImpl();//private必须写
以后这一句要写到UserServiceImpl内。
⑥vo,数据传输层,用来转入转出数据,跟前台有关。
⑦util,工具类,用来封装一些公用的方法,如字符串的处理,字符集过滤等。
⑧impl,用来实现接口。一个接口可以有多种实现,用来满足不同需要。
一般的调用情况如下:
贴一张很重要的图,大致说明了各层的继承和implements关系
举一个小项目的例子,实现往数据库增删改查用户。缩略图如下:
其中User.java和UserVO.java现在看起来内容相同,区别在于User类是底层数据,一般不轻易改变。UserVO层业余数据库中内容相对应,将DB中检索出数据,或者要往DB中反映的数据保存在vo实例中。以后若想再有什么扩展,直接在VO层改就行,不用动底层代码。
这里边,UserDao,BaseDao,UserService都是接口类,相应的impl则是对其的实现。
1.BaseDao代码:
- import java.util.List;
- /**
- * 基本的方法
- * @author Administrator
- *
- */
- public interface BaseDao<Entity> {
- /**
- * 保存
- * @param obj
- * @throws Exception
- */
- void save(Entity entity) throws Exception;
- /**
- * 删除
- * @param id
- * @throws Exception
- */
- void delete(int id) throws Exception;
- /**
- * 更新
- * @param obj
- * @throws Exception
- */
- void update(Entity entity) throws Exception ;
- /**
- * 根据id查询指定记录
- * @param id
- * @return
- * @throws Exception
- */
- Entity findById(int id) throws Exception;
- /**
- * 查询所有记录
- * @return
- * @throws Exception
- */
- List<Entity> findAll() throws Exception;
- }
2.BaseDaoImpl代码,利用反射获取数据库数据
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.lang.reflect.ParameterizedType;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- import com.bjsxt.util.DBUtil;
- public class BaseDaoImpl<Entity> implements BaseDao<Entity> {
- protected Class clazz;
- public BaseDaoImpl(){
- ParameterizedType pz = (ParameterizedType) this.getClass().getGenericSuperclass();
- //利用反射返回当前类的父类的类型,并强制转换
- clazz = (Class) pz.getActualTypeArguments()[0];
- //返回此类型实际类型参数的Type对象数组的第一个
- //这两步的作用就是获取父类泛型参数的实际类型
- System.out.println(clazz + "这是测试代码,打印出来的");
- }
- @Override
- public void save(Entity entity) throws Exception {
- Connection conn = DBUtil.getConn();//连接数据库
- String sql = "insert into " + clazz.getSimpleName() + " values(null";
- Field[] fs = clazz.getDeclaredFields();
- for (int i = 0; i < fs.length; i++) {
- sql += ",?";
- }
- sql = sql + ")";
- PreparedStatement ps = DBUtil.getPs(conn, sql);
- //user.setUsername(rs.getString("username"));
- for (int i = 0; i < fs.length; i++) {
- String methodName = "get" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
- //假如有个实体user类,含有uname属性,则获取uname的方法默认会为getUname(),会将uname的首字母大写,其余不变
- //Character.toUpperCase就是将字符大写,然后将除首字母以外的截取出来,拼到一起,构成类似于getUname()的方法
- //user.setUsername(uForm.getUsername);
- //该处用get是因为要把对象保存进数据库里,用get获取属性
- Method m = clazz.getDeclaredMethod(methodName);
- ps.setObject(i,m.invoke(entity));
- //setObject用来给"?"赋值。invoke则是在不知道具体类的情况下利用字符串去调用方法
- //正常情况下是user.getUsername,m.invoke(entity)中m是一个方法,类似于getUsername(),entity相当于user.
- //invoke是从实体里边找方法,那句话的意思就是从实体里边调用方法
- }
- ps.executeUpdate();
- DBUtil.close(ps);
- DBUtil.close(conn);
- }
- @Override
- public void view(Entity entity) throws Exception {
- // TODO Auto-generated method stub
- }
- @Override
- public void update(Entity entity) throws Exception {
- Connection conn = DBUtil.getConn();
- String sql = "update " + clazz.getSimpleName() + "set";
- Field[] fs = clazz.getDeclaredFields();
- for (int i = 0; i < fs.length; i++) {
- sql += fs[i].getName() + " = ?,";
- }
- sql = sql.substring(0,sql.length()-1) + " where id = ?"; //减去最后的逗号
- PreparedStatement ps = DBUtil.getPs(conn, sql);
- for (int i = 0; i < fs.length; i++) {
- String methodName = "get" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
- Method m = clazz.getDeclaredMethod(methodName);
- ps.setObject(i, m.invoke(entity));
- }
- Method getId = clazz.getDeclaredMethod("getId");//更新需要知道id
- ps.setInt(fs.length, (Integer) getId.invoke(entity));//因为id在sql语句最后一个问号处,所以要用fs.length
- ps.executeUpdate();
- DBUtil.close(ps);
- DBUtil.close(conn);
- }
- @Override
- public void delete(int id) throws Exception {
- Connection conn = DBUtil.getConn();
- String sql = "delete from " + clazz.getSimpleName() + " where id = ?" + id;
- PreparedStatement ps = DBUtil.getPs(conn, sql);
- ps.executeUpdate();
- DBUtil.close(ps);
- DBUtil.close(conn);
- }
- @Override
- public Entity findById(int id) throws Exception {
- Connection conn = DBUtil.getConn();
- String sql = "select * from " + clazz.getSimpleName() + " where id= ? ";
- PreparedStatement ps = DBUtil.getPs(conn, sql);
- ps.setInt(1,id);
- ResultSet rs = ps.executeQuery();
- Entity entity = (Entity) clazz.newInstance();//利用无参构造函数新建实例
- Field[] fs = clazz.getDeclaredFields();
- if(rs.next()){
- for (int i = 0; i < fs.length; i++) {
- String methodName = "set" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
- Method m = clazz.getDeclaredMethod(methodName, fs[i].getType());
- m.invoke(entity, rs.getObject(fs[i].getName()));
- }
- }
- DBUtil.close(rs);
- DBUtil.close(ps);
- DBUtil.close(conn);
- return entity;
- }
- @Override
- public List<Entity> findAll() throws Exception {
- Connection conn = DBUtil.getConn();
- String sql = "select * from " + clazz.getSimpleName();
- PreparedStatement ps = DBUtil.getPs(conn, sql);
- ResultSet rs = ps.executeQuery();
- List<Entity> enList = new ArrayList<Entity>();
- while(rs.next()){
- Entity en = (Entity) clazz.newInstance();
- //user.setUsername(rs.getString("username"));
- Field[] fs = clazz.getDeclaredFields();
- for (int i = 0; i < fs.length; i++) {
- String methodName = "set" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
- Method m = clazz.getDeclaredMethod(methodName, fs[i].getType());
- m.invoke(en, rs.getObject(fs[i].getName()));
- }
- enList.add(en);
- }
- DBUtil.close(rs);
- DBUtil.close(ps);
- DBUtil.close(conn);
- return enList;
- }
- }
注意:String methodName在何处用get,何处用set
3.UserDao代码
- import java.util.List;
- import com.bjsxt.base.BaseDao;
- import com.bjsxt.entity.User;
- public interface UserDao extends BaseDao<User>{
- List<User> findByPageList(int currentPage, int pageSize) throws Exception;
- Long getTotal() throws Exception;
- }
4.UserDaoImpl代码
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- import sun.nio.cs.US_ASCII;
- import com.bjsxt.base.BaseDaoImpl;
- import com.bjsxt.dao.UserDao;
- import com.bjsxt.entity.User;
- import com.bjsxt.util.DBUtils;
- public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao{
- @Override
- public List<User> findByPageList(int currentPage, int pageSize)
- throws Exception {
- Connection conn = DBUtils.getConn();
- String sql = "select * from user limit " + (currentPage-1)*pageSize + "," +pageSize;
- PreparedStatement ps = DBUtils.getPs(conn, sql);
- ResultSet rs = ps.executeQuery();
- List<User> userlist =new ArrayList<User>();
- while(rs.next()){
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setUsername(rs.getString("username"));
- user.setPassword(rs.getString("password"));
- user.setAge(rs.getInt("age"));
- user.setSex(rs.getString("sex"));
- user.setBirthday(rs.getString("birthday"));
- user.setSalary(rs.getString("salary"));
- user.setDescription(rs.getString("description"));
- userlist.add(user);
- }
- DBUtils.close(rs);
- DBUtils.close(ps);
- DBUtils.close(conn);
- return userlist;
- }
- @Override
- public Long getTotal() throws Exception {
- Connection conn = DBUtils.getConn();
- String sql = "select count(*) from user";
- PreparedStatement ps = DBUtils.getPs(conn, sql);
- ResultSet rs =ps.executeQuery();
- if(rs.next()){
- return ((Number)rs.getInt(1)).longValue();
- }
- return ((Number)0).longValue();
- }
- }
5.User代码,下边的UserVO先和它一样,就不贴了。
- public class User {
- private int id ;
- private String username ;
- private String password ;
- private int age ;
- private String sex ;
- private String birthday ;
- private String salary ;
- private String description ;
- public User() {
- super();
- // TODO Auto-generated constructor stub
- }
- public User(int id, String username, String password, int age, String sex,
- String birthday, String salary, String description) {
- super();
- this.id = id;
- this.username = username;
- this.password = password;
- this.age = age;
- this.sex = sex;
- this.birthday = birthday;
- this.salary = salary;
- this.description = description;
- }
- public int getId() {
- return id;
- }
- public void setId(int 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 int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public String getBirthday() {
- return birthday;
- }
- public void setBirthday(String birthday) {
- this.birthday = birthday;
- }
- public String getSalary() {
- return salary;
- }
- public void setSalary(String salary) {
- this.salary = salary;
- }
- public String getDescription() {
- return description;
- }
- public void setDescription(String description) {
- this.description = description;
- }
- }
6.UserService代码,只提供接口,不实现任何方法,只让UserServiceImpl来实现
- import java.util.List;
- import com.bjsxt.util.DataGrid;
- import com.bjsxt.vo.UserVO;
- public interface UserService {
- void saveUser(UserVO userVO) throws Exception ;
- void deleteUser(int id) throws Exception ;
- void updateUser(UserVO userVO) throws Exception ;
- UserVO findById(int id) throws Exception ;
- List<UserVO> findAll() throws Exception ;
- DataGrid findByPage(int currentPage , int PageSize) throws Exception ;
- }
7.UserServiceImpl代码,方法还没完全实现,只完成一种。
- import java.nio.channels.DatagramChannel;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import com.bjsxt.dao.UserDao;
- import com.bjsxt.dao.impl.UserDaoImpl;
- import com.bjsxt.entity.User;
- import com.bjsxt.service.UserService;
- import com.bjsxt.util.DataGrid;
- import com.bjsxt.vo.UserVO;
- public class UserServiceImpl implements UserService {
- private UserDao userDao = new UserDaoImpl();
- @Override
- public void saveUser(UserVO userVO) throws Exception {
- }
- @Override
- public void deleteUser(int id) throws Exception {
- }
- @Override
- public void updateUser(UserVO userVO) throws Exception {
- }
- @Override
- public UserVO findById(int id) throws Exception {
- return null;
- }
- @Override
- public List<UserVO> findAll() throws Exception {
- return null;
- }
- @Override
- public DataGrid findByPage(int currentPage, int PageSize)
- throws Exception {
- List<UserVO> uservolist = new ArrayList<UserVO>();
- List<User> userList = this.userDao.findByPageList(currentPage ,PageSize);
- for (Iterator iterator = userList.iterator(); iterator.hasNext();) {
- User user = (User) iterator.next();
- UserVO uvo = new UserVO();
- uvo.setId(user.getId());
- uvo.setUsername(user.getUsername());
- uvo.setPassword(user.getPassword());
- uvo.setAge(user.getAge());
- uvo.setBirthday(user.getBirthday());
- uvo.setSalary(user.getSalary());
- uvo.setSex(user.getSex());
- uvo.setDescription(user.getDescription());
- uservolist.add(uvo);
- }
- Long total = this.userDao.getTotal();
- DataGrid datagrid = new DataGrid();
- datagrid.setRows(uservolist);
- datagrid.setTotal(total);
- return datagrid;
- }
- }
8.DataGrid代码
- import java.util.List;
- public class DataGrid {
- private Long total ; //总记录数
- private List rows ; //返回的数据条目
- public Long getTotal() {
- return total;
- }
- public void setTotal(Long total) {
- this.total = total;
- }
- public List getRows() {
- return rows;
- }
- public void setRows(List rows) {
- this.rows = rows;
- }
- }
9.DBUtil代码
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- /**
- * 链接数据库的
- * @author Administrator
- *
- */
- public class DBUtils {
- /**
- * 获得connection对象
- * @return
- */
- public static Connection getConn(){
- Connection conn = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- conn = DriverManager.getConnection("jdbc:mysql://localhost/ext_001", "root", "root");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return conn;
- }
- /**
- * 预编译sql
- * @param conn
- * @param sql
- * @return
- */
- public static PreparedStatement getPs(Connection conn , String sql){
- PreparedStatement ps = null;
- try {
- ps = conn.prepareStatement(sql);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return ps;
- }
- /**
- * 一系列关闭对象的close
- * @param conn
- */
- public static void close(Connection conn){
- if(conn != null){
- try {
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- public static void close(PreparedStatement ps){
- if(ps != null){
- try {
- ps.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- public static void close(ResultSet rs){
- if(rs != null){
- try {
- rs.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
最后粘一篇百度知道上的内容,关于service层和dao层的,供参考。
首先,service层会很大,方法很多。
第二,试想,所有DAO都有增删改查四个基本方法。假设在DAO层(如StudentDAO.java)里student.add(),student.delete().student.update(),student.query()。
而如果应用增加了service层(如ApplictionServiceImpl.java),需要在service层中加上
applicationService.addStudent(),deleteStudent(),updateStudent(),queryStudent()四个方法。
这时你需要更新service层的接口类ApplicationService.Java,加上这四个方法。然后再更新service层的实现类ApplicationServiceImpl,加上这四个方法,最后你发现这四个方法每个方法里都只有一句话(以addStudent()为例)
public int addStudent(Student student){
return student.add();
}
这样是不是太傻了点,还不如在action中直接调用StudentDAO中的student.add()。
以上是我的个人看法,请各位指点
这么来讲好了 按你所说 在action中直接调用StudentDAO中的student.add()。 现在有客户A 客户B
客户A的需求是 addStudent 这个和你所说的情况一致
客户B的需求是 addStudent 前去加一个动作 将学生父母的信息也插入数据库
这时如果按照只调用DAO的方法的话,你需要从新建立一个action
CustomerBAction
再重新写一个DAO 因为这个DAO里要有添加父母的方法 student.addStudentAndParentInfo()。
CustomerBAction 去调用 student.addStudentAndParentInfo()。
这样加大了很多工作量
如果中间有service层的话 action始终用一个action
而调用的也是service接口 只要对接口注入不同的实现就可以满足 不同客户的需求了
知识要活学活用,要按照自己项目以后的发展趋势来搭设环境,别人家说什么就用什么。其实有时候javabean+jsp 也很好用啊,因为jsp不用重启服务 开发速度很快。我做小项目就是这种模式,以后小项目的更改也会很少,所以不用搭建的过于复杂。
补充:
entity和vo的不同还可以通过下边这个例子说明。如有user.java和userVO.java
user的属性为
- private int id ;
- private String username ;
- private String password ;
而userVO的属性则可为:
- private int id ;
- private String username ;
- private String password1 ; //第一次输入密码
- private String password2 ; //确认密码
在表单验证时,password1和password2相同时才会被提交。这样不用改entity类,只需修改vo层即可。当然,这里的password1和password2也得写上get和set方法。
java web中分层MVC的意义的更多相关文章
- java web 中的MVC
M:相当于Bean V:jsp C:servlet 当客户端发来请求,servlet响应请求处理请求,并把要发送给客户端的数据封装到Bean中,然后通过转发,将这个封装好了数据Bean送给jsp,js ...
- JDBC在Java Web中的应用
JDBC在Java Web中的应用 制作人:全心全意 在Java Web开发中,JDBC的应用十分广泛.通常情况下,Web程序操作数据库都是通过JDBC实现,即使目前数据库方面的开源框架层出不穷,但其 ...
- Java Web中的mapper,service,controller,model
Java Web中的mapper,service,controller,model作用分别是:java web中mapper是对象持久化映射层,一般会继承ibatis或者mybatisservive是 ...
- 【中文乱码】深入分析 Java Web 中的中文编码问题
深入分析 Java Web 中的中文编码问题 1.几种常见的编码格式 1.1 为什么要编码 在计算机中存储信息的最小单元是 1 个字节,即 8 个 bit, 所以能表示的字符范围是 0 ~ 255 个 ...
- Java Web 中 过滤器与拦截器的区别
过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法u ...
- JAVA WEB 中的编码分析
JAVA WEB 中的编码分析 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {background-co ...
- Java web中常见编码乱码问题(一)
最近在看Java web中中文编码问题,特此记录下. 本文将会介绍常见编码方式和Java web中遇到中文乱码问题的常见解决方法: 一.常见编码方式: 1.ASCII 码 众所周知,这是最简单的编码. ...
- Java web中常见编码乱码问题(二)
根据上篇记录Java web中常见编码乱码问题(一), 接着记录乱码案例: 案例分析: 2.输出流写入内容或者输入流读取内容时乱码(内容中有中文) 原因分析: a. 如果是按字节写入或读取时乱码, ...
- 深入分析Java Web中的编码问题
编码问题一直困扰着我,每次遇到乱码或者编码问题,网上一查,问题解决了,但是实际的原理并没有搞懂,每次遇到,都是什么头疼. 决定彻彻底底的一次性解决编码问题. 1.为什么要编码 计算机的基本单元是字节, ...
随机推荐
- 三张图搞懂JavaScript的原型对象与原型链
对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__proto__混淆,二来它们之间的各种指向实在有些复杂,其实市面上已经有非常多的文章在尝试说清楚,有一张 ...
- IIC_slaver 仿真错误
integer 类型不能直接赋值. 改正之后的代码
- oracle 查询年月日连在一起
SELECT B.YEAR || replace(lpad(B.MONTH, 2), ' ', '0') || replace(lpad(B.WEEK, 2), ' ', '0') from TT_U ...
- python实现文件的复制
# 练习: # 1. 写程序,实现文件的复制,(注:只复制文件,不复制文件夹) # 要求: # 1) 要考虑文件关闭的问题 # 2) 要考虑超大文件无法一下加载到内存的问题 # 3) 要能复制二进 ...
- The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
好久没有冒泡了,最近在新环境上搭建应用时,启动报错: INFO: Illegal access: this web application instance has been stopped alre ...
- Ubuntu中的出现:主文件夹的内容跑在桌面显示解决方案。同时 vim编辑器的操作
在终端窗口进入中文件夹 输入命令:cd .config/ 然后找到user-dirs.dirs 输入命令:vim user-dirs.dirs 在vim中安 i 即可进行插入操作 把对应的中文件中的文 ...
- 2019-04-19-day036-协程与进程池
内容回顾 11:30 码云 :王老师检查作业+定期抽查 注册账号 考试的时间 threading.enumerate(),能够获取到当前正在运行的所有线程对象列表 守护线程 守护线程会等待所有的非守护 ...
- 洛谷P1966 【火柴排队】
题解 P1966 [火柴排队] 说明: 在数学中有个公式: (a1-b1)^2+(a2-b2)^2<(a2-b1)^2+(a1-b2)^2 (你可以自己试着证一下) 两列火柴对应的两根火柴在各列 ...
- js 防抖 debounce 与 节流 throttle
debounce(防抖) 与 throttle(节流) 主要是用于用户交互处理过程中的性能优化.都是为了避免在短时间内重复触发(比如scrollTop等导致的回流.http请求等)导致的资源浪费问题. ...
- L2-002 链表去重 (25 分)
L2-002 链表去重 (25 分) 给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉.即对每个键值 K,只有第一个绝对值等于 K 的结点被保留.同时,所有被删除的结点须被保存在 ...