MVC结构的应用
什么是MVC结构
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
简单的来说就是我们要做到不同业务之间的分离
如何做到MVC结构
以用户管理功能的实现为例
图中的Servlet是与用户交互的,负责调用Service层,是控制程序的走向的一类,在MVC设计模式中充当Controller(控制器)。
图中的Service与Dao是逻辑业务层,主要负责通过查询数据库中的信息,为我们返回Servlet层需要的一些值。在MVC中充当Model(模型)。我们又将这里分为两层,一层为Service层,一层为Dao层。Dao层直接与实体类接触,通过SQL查询数据库中的一些信息,而Service层中会直接引入Dao层,从而通过Dao的对象对数据库进行操作,简单地说就是对Dao层的封装。
图中显示的返回JSP页面就是MVC中的View层,主要负责页面内容的显示。
那么怎么才能实现这写呢?
首先我们要清楚,我们是面向接口编程的,我们选择从底部往上写。那么我们要实现具体的操作就分为一下几个操作:
1:编写获取数据库连接方法、查询公共方法、增删改公共方法、释放连接方法
//获得数据库的连接
public static Connection getConnection(){
Connection connection = null;
try{
Class.forName(driver);
connection = DriverManager.getConnection(url,username,password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
//编写查询公共类
public static ResultSet execute(Connection connection,String sql,Object[] params,ResultSet resultSet,PreparedStatement preparedStatement) throws SQLException{
//预编译的sql,在后面直接执行就可以了
preparedStatement = connection.prepareStatement(sql);
for (int i = 0;i < params.length;i++){
//占位符从1开始,但是我们的数组从0开始
preparedStatement.setObject(i+1,params[i]);
}
resultSet = preparedStatement.executeQuery();
return resultSet;
}
//编写增删改公共方法
public static int execute(Connection connection,String sql,Object[] params,PreparedStatement preparedStatement) throws SQLException{
preparedStatement = connection.prepareStatement(sql);
for (int i = 0;i < params.length;i++){
preparedStatement.setObject(i+1,params[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
//释放资源
public static boolean closeResource(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){
boolean flag = true;
if(resultSet!=null){
try{
resultSet.close();
resultSet = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if(preparedStatement!=null){
try{
preparedStatement.close();
preparedStatement = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if(connection!=null){
try{
connection.close();
connection = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
2:创建Dao层的接口,接口中我们可以有一些对数据库操作的方法
在这里我列举一个登陆的例子:
public interface UserDao {
//得到登录的用户
public User getLoginUser(Connection connection, String userCode) throws SQLException;
}
3:实现Dao的接口,并完成其中对数据库操作的方法。
public class UserDaoImpl implements UserDao{
//得到要登录的用户
@Override
public User getLoginUser(Connection connection, String userCode) throws SQLException {
PreparedStatement pstm = null;
ResultSet rs = null;
User user = null;
if (connection!=null){
String sql = "select * from smbms_user where userCode=?";
Object[] params = {userCode};
rs = BaseDao.execute(connection,sql,params,rs,pstm);
if (rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResource(null,pstm,rs);
}
return user;
}
4:创建Service接口
public interface UserService {
//用户登录
public User login(String userCode,String password);
}
5:实现Service接口
public class UserServiceImpl implements UserService {
//业务层都会调用dao层,所以我们要引入Dao层;
private UserDao userDao;
public UserServiceImpl() {
userDao = new UserDaoImpl();
}
//用户登录
@Override
public User login(String userCode, String password) {
Connection connection = null;
User user = null;
try{
connection = BaseDao.getConnection();
user = userDao.getLoginUser(connection, userCode);
} catch (SQLException e){
e.printStackTrace();
}finally {
BaseDao.closeResource(connection,null,null);
}
return user;
}
}
6:编写Servlet
public class LoginServlet extends HttpServlet {
//Servlet:控制层,调用业务层代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
UserService userService = new UserServiceImpl();
User user = userService.login(userCode, userPassword);
if (user!=null){
//查有此人可以登录
req.getSession().setAttribute(Constants.USER_SESSION,user);
//跳转到内部
resp.sendRedirect("jsp/frame.jsp");
}else {
//查无此人,无法登录,转发到登录页面
req.setAttribute("error","用户名或者密码错误");
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7:在web.xml中注册Servlet
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.yyp.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
过滤器的应用
过滤器是干什么的
过滤器可以再请求和响应之前做一部分预处理,有效的过滤掉不需要的内容,而且过滤器可以被复用,节省了大量的复用代码,提高了java的代码执行效率
如何实现过滤器
简单的来说,就比如我们的系统,需要时刻保证我们的用户是存在的,这时我们就可以用过滤器来判断当前用户是否为空。
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
if (user==null){
response.sendRedirect("/smbms/error.jsp");
}else {
chain.doFilter(req,resp);
}
}
@Override
public void destroy() {
}
}
我们在登录之后直接给Session设置一个属性,其值为当前用户,在过滤器中,我们只需要判断Session中userSession中的user是否为null就可以了,如果为空,就跳转到错误页面,不为空的话,就继续程序进行。