#|Servlet 架构思路(MVC)

#|Servlet 架构思路(MVC)
文章图片

这几天在做一个前后端分离的一个项目,采用的是 MVC 模式,对于 MVC 网上的教程杂乱无章,也没有写的较详细的,所以写了此文,本文作为一个分享文,分享本人在学习中遇到的问题以及一些自个认为好用的小技巧。

目录
目录下的结构
配置文件
Dao 层
Service 层
Control 层
Model 层
lib 导包
web.xml 配置

目录下的结构

config jdbc.properties src com.xxx user(一般与项目名挂钩) control UserServlet.java dao impl UserDao.java IUserDao.java model User.java service impl UserService.java IUserService.java util JdbcUtil.java web web-inf web.xml lib xxx.jar xxx.jsp

#|Servlet 架构思路(MVC)
文章图片

配置文件 jdbc.properties : 开发中获得连接的4个参数(驱动、URL、用户名、密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可。
oracle 版
username=itxzw password=123456 driver=oracle.jdbc.OracleDriver url=jdbc:oracle:thin:@localhost:1521:orcl

mysql 版
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/db1?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8&useSSL=false或 url=jdbc:mysql://localhost/db1?useSSL=false&CharacterEncoding=UTF-8&server=TUC user=root password=123456

JdbcUtil.java
里面存放的是对连接 DB 的一些配置文件,可以减少代码量
public class JdbcUtil { public static String username; public static String password; public static String driver; public static String url; static { // -1.读取配置文件 InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties pro = new Properties(); try { pro.load(is); username = pro.getProperty("username"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); url = pro.getProperty("url"); // 0.加载驱动 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } }public static Connection getConnection(){ // 1.连接数据库 Connection conn = null; try { conn = DriverManager.getConnection(url, username, password); } catch (SQLException throwables) { throwables.printStackTrace(); } return conn; }public static void close(ResultSet rs, Statement stmt,Connection conn){ // 5.关闭连接 try { if(rs!=null){ rs.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { try { if (stmt!=null){ stmt.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally {try { if (conn!=null){ conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } } }}

Dao 层 dao 里面存放的是对 DB 进行操作的一些代码
IUserDao.java 里面存放的是对 DB 进行操作的一些代码的接口
public interface IUserDao {// 添加用户 public boolean add(User user); // 查询 public User query(User user); // 根据名字查询 public User queryUserByName(String name); // 根据ID_NUMBER查 public User queryUserByNumber(String number); }

UserDao.java 里面的就是实现 IUserDao.java 的代码,对 DB 进行操作
public class UserDao implements IUserDao { @Override public boolean add(User user) {………… return user; }@Override public User query(User user) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; User loginuser = null; try { // 1.连接数据库 conn = JdbcUtil.getConnection(); // 2.获取Statement对象:将sql语句传给数据库服务器执行 String sql = "select * from T_USER where USERNAME = ? and PASSWORD = ?"; stmt = conn.prepareStatement(sql); // 2.5.注入参数 stmt.setString(1,user.getUsername()); stmt.setString(2,user.getPassword()); // 3.执行sql,获取返回结果 rs = stmt.executeQuery(); // 4.处理结果集if(rs.next()){ Integer id = rs.getBigDecimal("id")==null?null:rs.getBigDecimal("id").intValue(); String un = rs.getString("username"); String password = rs.getString("password"); Integer sex = rs.getString("sex")==null?null:rs.getBigDecimal("sex").intValue(); String idNumber = rs.getString("ID_NUMBER"); String tel = rs.getString("tel"); String addr = rs.getString("addr"); Integer type = rs.getString("type")==null?null:rs.getBigDecimal("type").intValue(); loginuser = new User(id,un,password,sex,idNumber,tel,addr,type); } } catch (Exception e) { e.printStackTrace(); }finally { JdbcUtil.close(rs,stmt,conn); } return loginuser; }@Override public User queryUserByName(String name) {………… return user; }@Override public User queryUserByNumber(String number) {………… return user; } }

里面就是对 DB 进行增删改查等操作
Service 层 IUserService.java 里面存放的是实现 UserService.java 里面的接口
public interface IUserService {// 添加用户 public boolean register(User user); // 登录 public User login(User user); // 根据名字查询 public User queryUserByName(String name); // 根据ID_NUMBER查 public User queryUserByNumber(String number); }

UserService.java 里面存放的是实现 IUserService.java 接口里面的方法,申明一个 Dao 的成员,然后使用该 Dao 成员调用 Dao 里面的方法。
public class UserService implements IUserService {private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public UserDao getUserDao() { return userDao; }@Override public boolean register(User user) { User user1 = userDao.queryUserByName(user.getUsername()); if (user1!=null) return false; User user2 = userDao.queryUserByNumber(user.getIdNumber()); if (user2!=null) return false; return userDao.add(user); }@Override public User login(User user) { return userDao.query(user); }@Override public User queryUserByName(String name) { return userDao.queryUserByName(name); }@Override public User queryUserByNumber(String number) { return userDao.queryUserByNumber(number); } }

Control 层 control 里面存放的是 Servlet,与界面(view)、service进行交互。
public class UserServlet extends HttpServlet { private UserService userService; @Override public void init() throws ServletException { userService = new UserService(); UserDao userDao = new UserDao(); userService.setUserDao(userDao); }@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(req,resp); }@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String action = request.getParameter("action"); if("LOGIN".equalsIgnoreCase(action)){ login(request,response); }else if ("REGISTER".equalsIgnoreCase(action)){ register(request,response); }else{ response.sendRedirect("/a1/day02/fade.jsp"); } }public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{ String username = request.getParameter("username"); String password = request.getParameter("password"); User u = new User(); u.setUsername(username); u.setPassword(password); User loginuser = userService.login(u); if(loginuser!=null){ response.sendRedirect("/a1/day02/success.jsp"); }else{ response.sendRedirect("/a1/day02/login.jsp"); }}public void register(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{String[] hobbys = request.getParameterValues("hobby"); String un = request.getParameter("username"); String password = request.getParameter("password"); String usersex = request.getParameter("sex"); Integer sex = usersex==null?null:Integer.parseInt(usersex); String idNumber = request.getParameter("id_number"); String tel = request.getParameter("tel"); String addr = request.getParameter("addr"); String usertype = request.getParameter("type"); Integer type = usertype==null?null:Integer.parseInt(usertype); response.setContentType("text/html; charset=UTF-8"); response.getWriter().println("哈哈"); }}

Servlet生命周期 init 只会执行一次,申明 Service 层的对象一般只申明一次,以后项目上云了,如果有成千上万的人来访问你的网页,执行一次就创建一个 Service ,非常的浪费,所以为了减少内存的使用就把 Service 放入到 init 里面。
Model 层 里面存放的是实体类,对成员的 getter 与 setter 方法,有参无参的构造函数,重写toString等方法。
public class User {private int id; private String username; private String password; private int sex; private String id_number; private String tel; private String addr; private int type; public User() { }public User(int id, String username, String password, int sex, String id_number, String tel, String addr, int type) { this.id = id; this.username = username; this.password = password; this.sex = sex; this.id_number = id_number; this.tel = tel; this.addr = addr; this.type = type; }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 getSex() { return sex; }public void setSex(int sex) { this.sex = sex; }public String getId_number() { return id_number; }public void setId_number(String id_number) { this.id_number = id_number; }public String getTel() { return tel; }public void setTel(String tel) { this.tel = tel; }public String getAddr() { return addr; }public void setAddr(String addr) { this.addr = addr; }public int getType() { return type; }public void setType(int type) { this.type = type; }@Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", sex=" + sex + ", id_number='" + id_number + '\'' + ", tel='" + tel + '\'' + ", addr='" + addr + '\'' + ", type=" + type + '}'; } }

或者用 lombok.jar 就可以不用写getter 与 setter 方法,有参无参的构造函数,重写toString等方法。
@Data @AllArgsConstructor @NoArgsConstructor @ToString public class User {private Integer id; private String username; private String password; private Integer sex; private String idNumber; private String tel; private String addr; private Integer type; }

lib 导包 lib 里面存放的是导入的一些 .jar 包。
xxx.jsp
这个不用多讲,有一点需要注意的是,from 的 action 的位置与你的 web.xml 文件对应的。
web.xml 配置 web.xml文件是用来初始化配置信息:比如Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。 每个xml文件都有定义它书写规则的Schema文件,也就是说javaEE的定义web.xml所对应的xml Schema文件中定义了多少种标签元素,web.xml中就可以出现它所定义的标签元素,也就具备哪些特定的功能。
UserServlet com.itxzw.user.control.UserServletUserServlet /userServlet

#|Servlet 架构思路(MVC)
文章图片

servlet-mapping
servlet映射 端口映射过程就如同:你家在一个小区里B栋2410室,你朋友来找你,找到小区门口,不知道你住哪层哪号?就问守门的保安,保安很客气的告诉了他你家详细门牌,所以你朋友很轻松的找到了你家。
url-pattern
其实 url-pattern 就是说的 url 模式,就是容器在查找时根据这个模式来找到具体的servlet来执行。
servlet-name
Servlet程序起一个别名,一般是类名,作用是告诉服务器,当前配置的地址给哪个Servlet程序使用
servlet-class
java web开发中请求转发的类,就是你的类在你包下的地址。

不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!


【#|Servlet 架构思路(MVC)】

    推荐阅读