自己写一个简单的Struts框架(2)

接上一篇自己写一个简单的Struts框架(1)

基于配置文件的控制器

在上节所做的简单控制器的基础上,将其做成基于配置文件的控制器,通过读取解析xml文件中的标签配置,分发请求给特定的action处理类进行处理。

SimpleController工程

SimpleController工程目录:

工程新创建了工具类MyTools.java,重写了SimpleController.java

这里写图片描述

MyTools.java

MyTools中定义了readXml方法,代码没有用现有的几种解析xml文件的方式,而是自己实现了简单的读取和解析,参数为actionName和xml配置文件的路径,返回解析的相应action标签内容的Map数组。这种方式比较傻,后来知道有专门解析xml文件的方法后又重写了代码。

package sc.ustc.tool;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MyTools {

    public Map<String, String> readXml(String actionName, String path) throws FileNotFoundException {

        File fd = new File(path);
        BufferedReader br = new BufferedReader(new FileReader(fd));
        StringBuilder sb = new StringBuilder();
        String line = null;

        try {
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        String[] sl = sb.toString().split("</action>");
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < sl.length; i++) {
            String acName = sl[i].substring(sl[i].indexOf("name=\"") + 6);

            if (acName.startsWith(actionName + "\"")) {
                map.put("action", actionName);
                String classN = acName.substring(acName.indexOf("class=\"") + 7);
                map.put("class", classN.substring(0, classN.indexOf("\"")));
                String methodN = classN.substring(classN.indexOf("method=\"") + 8);
                map.put("method", methodN.substring(0, methodN.indexOf("\"")));

                String[] result = methodN.split("<result");
                for (int j = 1; j < result.length; j++) {
                    String resN = result[j].substring(result[j].indexOf("name=\"") + 6);
                    String resT = resN.substring(resN.indexOf("type=\"") + 6);
                    String resV = resT.substring(resT.indexOf("value=\"") + 7);
                    String res = resT.substring(0, resT.indexOf("\"")) + "-" + resV.substring(0, resV.indexOf("\""));
                    map.put("result" + resN.substring(0, resN.indexOf("\"")), res);
                }
            }

        }

        return map;
    }
}

SimpleController.java

SimpleController类拦截.sc请求,调用readXml获得相应的action标签项,通过java反射机制,调用相应class的method,根据返回值再做相应的分发。

package sc.ustc.controller;

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

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

import sc.ustc.tool.MyTools;

public class SimpleController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html,charset=utf-8");
        response.setCharacterEncoding("utf-8");
        request.setCharacterEncoding("utf-8");

        String actionName = request.getServletPath().toString();
        String[] actionUrl = actionName.split("/");
        actionName = actionUrl[actionUrl.length - 1];
        String path = this.getServletContext().getRealPath("WEB-INF/classes/controller.xml");
        MyTools mt = new MyTools();
        Map<String, String> actionMap = mt.readXml(actionName.substring(0, actionName.indexOf(".")), path);
        if (!actionMap.isEmpty()) {
            String classN = actionMap.get("class");
            String methodN = actionMap.get("method");

            try {
                Class cl = Class.forName(classN);
                Method m = cl.getDeclaredMethod(methodN, HttpServletRequest.class, HttpServletResponse.class);
                String result = (String) m.invoke(cl.newInstance(), request, response);

                String resN = actionMap.get("result" + result);
                String resT = resN.substring(0, resN.indexOf("-"));
                String resV = resN.substring(resN.indexOf("-") + 1);

                if (resT.equals("foward")) {
                    request.getRequestDispatcher(resV).forward(request, response);
                } else if (resT.equals("redirect")) {
                    response.sendRedirect(resV);
                }

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        } else {
            response.sendRedirect("/UseSC/jsp/Login.jsp");
        }
    }

}

UseSC工程

简单的web工程,用来测试上面写的框架

UseSC工程:

这里写图片描述

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <servlet>
        <servlet-name>sc</servlet-name>
        <servlet-class>sc.ustc.controller.SimpleController</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>sc</servlet-name>
        <url-pattern>*.sc</url-pattern>
    </servlet-mapping>


    <welcome-file-list>
        <welcome-file>/Login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

controller.xml

与Struts2框架类似,此即为框架要解析的配置文件,通过解析此文件来做拦截,转发等操作

<?xml version="1.0" encoding="UTF-8"?>
<sc-configuration>
    <controller>
        <action name="login" class="water.ustc.action.LoginAction"
            method="handleLogin">
            <result name="success" type="foward" value="Welcome.jsp"></result>
            <result name="failure" type="redirect" value="Login.jsp"></result>
        </action>
        <action name="regist" class="water.ustc.action.RegisterAction"
            method="handleRegist">
            <result name="success" type="foward" value="Welcome.jsp"></result>
            <result name="failure" type="redirect" value="Regist.jsp"></result>
        </action>
    </controller>
</sc-configuration>

测试

用户输入用户名密码,点击登录后,action提交表单至simpleController控制器处理,simpleController解析action后将调用LoginAction,LoginAction查询数据库,进行验证,并根据验证结果返回success或者failure,simpleController根据返回结果再进行页面转发或重定向。

这里写图片描述

UseSC工程其他代码

简单的登录注册界面以及登录注册的代码,用于测试框架

Login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>please login!</title>
    </head>

    <body>
        <div>
            <h3>请登录:</h3><br>
            <form action="login.sc" name="loginForm">
            <div>账&nbsp&nbsp号:<input type="text" name="id" /></div>
            <div>密&nbsp&nbsp码:<input type="password" name="password" /></div>
            <div><input type="submit" name="login" value="登录" /></div>
            </form>
            <div>
                <font color="red">${sessionScope.loginMessage }</font> 
            </div>
            <br>
            <div>
                如果您还不是我们的用户,请<a href="/UseSC/Regist.jsp">点击注册</a>
            </div>
            <%
                session.removeAttribute("loginMessage");
            %>
        </div>
    </body>
</html>

Welcome.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <body>
        <div>
            尊敬的${sessionScope.id },您好!
        </div>
        <div>
            <a href="/UseSC/Login.jsp">退出账户</a>
        </div>
    </body>
</html>

LoginAction.java

package water.ustc.action;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import water.ustc.dao.LoginDao;
import water.ustc.tools.Tools;

public class LoginAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public String handleLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String id = Tools.setUtf(request.getParameter("id"));
        String password = request.getParameter("password");
        LoginDao userDao = new LoginDao();
        HttpSession session = request.getSession();
        if (userDao.select(id, password) != null && !userDao.select(id, password).isEmpty()) {

            session.setAttribute("id", id);
            return "success";
        } else {
            session.setAttribute("loginMessage", "用户名或密码错误!");
            return "failure";
        }
    }
}

Regist.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
    <form action="regist.sc" name="loginForm" accept-charset="utf-8">
        <div>账&nbsp&nbsp号:<input type="text" name="id" /></div>
        <div>密&nbsp&nbsp码:<input type="text" name="password" /></div>
        <div><input type="submit" name="regist" value="注册" /></div>
    </form>
    <div>
        <font color="red">${sessionScope.registMessage }</font> 
    </div>
    <%
        session.removeAttribute("registMessage");
    %>
  </body>
</html>

RegistAction.java

package water.ustc.action;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import water.ustc.dao.LoginDao;
import water.ustc.tools.Tools;

public class RegisterAction extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public String handleRegist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String id = Tools.setUtf(request.getParameter("id"));
        String password = request.getParameter("password");
        LoginDao userDao = new LoginDao();
        HttpSession session = request.getSession();
        if (userDao.select(id, password) != null && !userDao.select(id, password).isEmpty()) {
            session.setAttribute("registMessage", "用户名已存在!");
            return "failure";
        } else {
            userDao.insert(id, password);
            session.setAttribute("id", id);
            return "success";
        }
    }
}

LoginDao.java

package water.ustc.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public class LoginDao {

    String driver = "com.mysql.jdbc.Driver";
    String dbName = "user";
    String passWord = "";
    String userName = "root";
    String url = "jdbc:mysql://localhost:3306/" + dbName;

    public List<List<String>> select(String id, String password) {

        String sql = "select * from useraccount where name = ? and password = ?";

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<List<String>> listlist = new ArrayList();
        List<String> list = new ArrayList();
        try {
            // 加载驱动
            Class.forName(driver);
            // 获得连接
            conn = DriverManager.getConnection(url, userName, passWord);
            // 创建prepareStatement
            ps = conn.prepareStatement(sql);
            ps.setString(1, id);
            ps.setString(2, password);
            // 执行操作
            rs = ps.executeQuery();
            while (rs.next()) {
                list.add(rs.getString(1));
                list.add(rs.getString(2));
                listlist.add(list);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return listlist;
    }

    public void insert(String id, String password) {

        String sql = "insert into useraccount(name,password) values(?,?)";

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            // 加载驱动
            Class.forName(driver);
            // 获得连接
            conn = DriverManager.getConnection(url, userName, passWord);
            // 创建prepareStatement
            ps = conn.prepareStatement(sql);
            ps.setString(1, id);
            ps.setString(2, password);
            // 执行操作
            ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

对Struts2控制器的理解

Struts2框架是MVC框架,Struts2控制器根据用户的请求决定调用哪个Action组件进行处理,决定执行后返回到哪个视图,将业务逻辑抽离出来,使得程序员仅仅需要关心业务逻辑的实现而无需处理视图的跳转,业务模型中也只有业务处理的代码,结构清晰。

基于配置的控制器和注解的控制器各自优缺点。

基于配置:
优点:集中式管理,与代码没有绑定,进一步降低了耦合,怎强可拓展性,使代码维护更加方便。
缺点:需要使用解析工具,开发时较麻烦,coding时无法验证准确性。
基于注解:
优点:提高开发效率,不需要使用解析工具,coding时可验证准确性。
缺点:与代码耦合高,项目庞大时代码维护,修改不方便。

下一篇自己写一个简单的Struts框架(3)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值