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.为什么要编码 计算机的基本单元是字节, ...
随机推荐
- [server]利用python构建的服务器地址问题
http://0.0.0.0:8000/ 利用github开源项目搭建AI上色师时,遇到了建立server却无法访问的问题,ip如上. 其实很简单,0.0.0.0并不是有效的ip地址,用localho ...
- 最全面的Redis命令行查阅手册(收藏查看)
Redis是用C语言实现的,一般来说C语言实现的程序“距离”操作系统更近,执行速度相对会更快. Redis使用了单线程架构,预防了多线程可能产生的竞争问题. 作者对于Redis源代码可以说是精打细磨, ...
- WScript与CScript的区别
WSH有两种形式:一为WScript是一个窗口化的版本:一为CScript是一个命令行的版本.两种版本都可以运行任何脚本.二者之间的区别是,窗口化版本(WScript)使用一个弹出对话框来显示文本输出 ...
- 2017年5月11日17:43:06 rabbitmq 消费者队列
从昨天开始发现个问题,一个接口在本地调用时大部分正常,一旦在生成者打一个断点调试,并且在promotion也打断点的时候会出现没有返回channel的异常,然后消费者就再也消费不了了 16:57:45 ...
- 北大poj- 1007
DNA排序 逆序数可以用来描述一个序列混乱程度的量.例如,“DAABEC”的逆序数为5,其中D大于他右边的4个数,E大于他右边的1个数,4+1=5:又如,“ZWQM”的逆序数为3+2+1+0=6. 现 ...
- php:数组与json数据相互转换
1.数组转json $json=json_encode(数组名) 数组转json字符串 2,json转数组 $arr=json_decode(json字符串,[true]) 不加true第一次转直接转 ...
- Delphi编程之爬取贴吧帖子图片
大家如果经常在逛贴吧的时候,会看到很多帖子里有很多好看的图片,都想下载下来留存的话,常规的方法只能一张一张点击右键,然后图片另存为,这样的方法对于图片少的来说没什么,要是图片超过100张,200张,那 ...
- Tomcat配置SSL后使用HTTP后跳转到HTTPS
Tomcat配置好SSL后将HTTP请求自动转到HTTPS需要在TOMCAT/conf/web.xml的未尾加入以下配置: <login-config> <!-- Authoriza ...
- if ,while ,for 的掌握
a)python的缩进和冒号 对于Python而言代码缩进是一种语法,Python没有像其他语言一样采用{}或者begin...end分隔代码块,而是采用代码缩进和冒号来区分代码之间的层次. 缩进的空 ...
- 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contai
之前一直使用的mysql5,突然换成8之后,有许多地方不一样,今天就碰到一个. 在使用sql语句创建表时,报错: 1055 - Expression #1 of ORDER BY clause is ...