我的java web架构方案

//业务逻辑代码片段
private String word;
    private String area;
    private String type;
    private Integer year;
    private String order;
    private Integer page;

@NotNull
@Min(0)
private Integer id;

public void list(HttpServletRequest req, HttpServletResponse res) throws ... {
//获得请求参数处理工具类实例,这里直接从上下文读取,你也可以使用spring或者自行实现依赖注入
        RequestParameterUtil paramUtil = (RequestParameterUtil) req.getServletContext().getAttribute("requestParameterUtil");
//获得消息对象
        Messages messages = (Messages) req.getAttribute("messages");
        String[] paramNames = {"word", "area", "type", "year", "order", "page"};
//请求参数工具类根据paramNames指定的参数数组利用反射依照命名约定绑定到this对象,本例为查询操作。当然,对于insert操作,绑定到javaBean对象更快捷方便。
//然后工具类自动执行java标准的基于注解的数据合法性验证validate
//bind()方法返回布尔值,标示是否存在绑定或者验证错误,messages为消息对象,保存所有分级别的消息
        paramUtil.bind(req, this, paramNames, messages);


...
        try (Connection conn = HdgangDataSource.getConnection(HostFactory.getHost())) {
            URL url = new URL("/cult/list.do");//url工具类,构造方法参数为请求路径,可在视图里覆盖,复杂项目不建议这样直接设定,可从控制器获取
            Tool.bind(url, this, paramNames);//绑定有效的请求参数至url对象
            Pagination pagination = new Pagination();//创建一个查询分页工具类实例
            pagination.setRowCnt(24);//设置每页24条记录
            pagination.setPageParamName("page");//设置url的分页的请求参数名
            pagination.setCurrentPage(page);//设置当前页码
            pagination.setUrl(url);//设置url
            pagination.setEncode(res.getCharacterEncoding());//设置URL参数的默认编码

//DAO方法
            List<Movie> movieList = MovieDAO.getList(conn, word, order, pagination);
//可以换成依赖注入。pagination 为分页对象,视图可直接配合模板一行代码渲染分页模块
            req.setAttribute("movieList", movieList);
            req.setAttribute("pagination", pagination);
        }
//可以返回字符串消息,交由控制器处理跳转
        req.getRequestDispatcher("/cult/list.jsp").forward(req, res);
    }


//get set 方法省略


//DAO方法

public static List<Movie> getList(Connection conn, String word, String order, Pagination pagination)
            throws ... {

//通过map绑定命名参数(类似于 :xxx),也支持通过javaBean绑定
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fulltext", fulltext);

//依据查询条件拼接复杂sql,myBatis实现的话比较别扭。这里定义MovieSql接口,具体实现可以跨数据库。这里直接new,实际应用应该依赖注射或者根据配置文件装载和实例化。
        MovieSql movieSql = new MovieSqlMysqlImpl();

        String scalarSql= movieSql.getSelectScalarSql(word);
//DAO为数据库工具类,getScalar获取符合条件的记录条数
        long rowTotalCnt = DAO.getScalar(conn, scalarSql, paramMap);
        List<Movie> movieList = null;
        if (rowTotalCnt > 0) {
//将查询得到的总记录条数set到pagination
            pagination.setRowTotalCnt(rowTotalCnt);
            String sql = movieSql.getSelectListSql(word,order, pagination.getOffset(),pagination.getRowCnt());
//getBeanList 获得查询得到的分页记录,getBeanList方法重载支持通过javaBean和Map绑定命名参数
            movieList = DAO.getBeanList(conn, sql, paramMap, Movie.class);
        }
        return movieList;
    }




//获取SQL语句的接口
public interface MovieSql{
     public String getSelectScalarSql(String word);
     public String getSelectListSql(String word,String order, int offset, int rowCnt);

     ...
}


//实现MovieSql接口,动态拼接sql语句。
public class MovieSqlMysqlImpl implements MovieSql{
     private final String select = "select `id`,`imdbid`,`name`,`year`,`duration`,`aliases`,`directors`,`actors`,`tags`,`intro`"
                + ",`areas`,`types`,`score`,`date`,`update`,`state` from `movie` ";
       private final String selectCnt = "select count(*) from `movie` ";

     private String getConditionsSqlFragment(String word){
        String conditions = "";
        String fulltext = "";
        if (word != null && !word.trim().isEmpty()) {
            word = word.trim();
            fulltext = Tool.encode(word, true, "+");
            conditions = " where match(`fulltext`) against(:fulltext IN BOOLEAN MODE) ";
        }
        return conditions;
     }

     private String getOrdersSqlFragment(String order){
        String orders;
        switch (order) {
            case "score":
                orders = " order by `score` desc ";
                break;
            case "sdate":
                orders = " order by `date` desc ";
                break;
            default:
                orders = " order by `update` desc,`date` desc ";
                break;
        }
        return orders;
     }

     @Override
     public String getSelectScalarSql(String word){
        return selectCnt +" "+ getConditionsSqlFragment(word) + ";";
     }

     @Override
     public String getSelectListSql(String word,String order, int offset, int rowCnt){
        return select +" "+ getConditionsSqlFragment(word) +" "+ getOrdersSqlFragment(order) + " limit " + offset + "," + rowCnt + ";";
     }

     ...
}



更多细节可参考 http://afadgaeg.iteye.com/blog/2155226

架构原则
1、轻量级组件优于重量级框架。实现完全解耦
2、约定优于配置。实现零配置
3、不要为了所谓的优雅而做不优雅的事,如过度封装和过度配置

相关阅读
php轻量化架构与编码约定 http://afadgaeg.iteye.com/blog/2395077

深圳求职(如有违规,请版主告知,我一定配合删除):
本人现在在深圳,找寻java方向工作,如有适合岗位招聘,可联系我的邮箱: [email protected] 或者手机: 13874372370

猜你喜欢

转载自afadgaeg.iteye.com/blog/2395132