zoukankan      html  css  js  c++  java
  • Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下。

    这个例子取自于《Spring 3.x 企业应用开发实战》一书中的第二章,IDE是Intellij,数据库为mySql。在Spring Web中,一般把系统划分为3个部分:

      1.持久层----数据库的操作

      2.业务层----主要的业务逻辑判断

      3.展现层----展示给用户的操作界面

    这是一种大而化之的分类方式,比如展现层可能是html,也可能是移动端的App。持久层可能操作的数据库也能是静态文件。分开的好处是思路可能清楚点,也方便后面的自动化测试。

      开发代码,业务现行,我们要开发一个简单的登录功能,上个时序图先:

    这个时序图里,已经做完了简单设计,两个界面:login.jsp和main.jsp在表现层,两个数据库操作的类UserDAO和LoinLogDAO

    在持久层。其余的都在业务层。我们从持久层,从下往上推进。

    持久层

    首先在mysql中创建数据库叫demo

    DROP DATABASE IF EXISTS demo;
    CREATE DATABASE demo DEFAULT   CHARACTER SET utf8;
    use demo

    设置用户远程连接的用户名admin和密码something

    grant all privileges on *.* to admin@localhost identified by 'something' with grant option;

    创建一个用户表,字段分别是:用户ID,用户名,积分,密码,最后登录时间,最后登录IP。设置为内联。

    CREATE TABLE t_user(
        user_id INT AUTO_INCREMENT PRIMARY KEY,
        user_name VARCHAR(30),
        credits INT,
        password VARCHAR(30),
        last_visit datetime,
        last_ip VARCHAR(23)
    )ENGINE=InnoDB;

    创建一个登录日志表,字段分别是:日志ID,用户ID,ip和登录时间。同样设置为内联。

    CREATE TABLE t_logon_log(
        login_log_id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT,
        ip VARCHAR(23),
        login_datetime datetime
    )ENGINE=InnoDB;

    在用户名表内插入一段数据:用户名admin,密码123456。

    INSERT INTO t_user(user_name,password) VALUES ("admin","123456");

    自此数据库的搭建,进行完毕。我们开始写代码。

    使用Intellij搭建项目。

    第一步创建一个Spring MVC的项目

    2.删除示例代码,把我们的代码加进去:

    我们主要需要修改两个部分1.main文件夹下面的代码。main文件夹下我们创建4个包:dao,domain,service,web。dao负责持久层的代码,domain主要负责一些bean文件,service主要负责业务逻辑,web主要负责Controller层的代码。2.web文件夹下面的配置文件和jsp文件。其中负责maven的pom.xml,负责最初配置的web.xml等。

    1.增加domain里面的bean类,主要用于和数据库里面的表对应。

    User.java

    public class User implements Serializable
    {
        private int userId;
        private String userName;
        private String password;
        private int credits;
        private String lastIp;
        private Date lastVisit;
    }
    

    LoginLog.java

    public class LoginLog implements Serializable {
        private int loginLogId;
        private int userId;
        private String ip;
        private Date loginDate;
    }

    在Intellij 中我们可以通过快捷键Alt+Ins来天剑set和get方法,简单实用。

    2.在DAO里面添加对数据库操作的代码

    第一步在web.xml里面添加applicationContext的Bean配置文件的位置。

    然后我们在applicationContext.xml文件中配置我们的一些关于数据库的工具。Spring基础是搭建在IOC和AOP之上的,即控制反转和切片。因为我们是刚开始学习,也不要深究这是什么意思,大略的意思是类里面不再使用new来创建对象,而是依靠注解来注入。这次我们要注入的是数据库操作的工具类org.springframework.jdbc.core.JdbcTemplate。

    applicationContext.xml

    好了,开始写代码:

    package com.test.dao;
    
    import com.test.domain.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowCallbackHandler;
    import org.springframework.stereotype.Repository;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * Created by 13051041 on 2016/5/3.
     */
    @Repository
    public class UserDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
        public int getMatchCount(String userName,String password) {
            String sqlStr = " SELECT count(*) FROM t_user WHERE user_name =? and password=? ";
            return jdbcTemplate.queryForInt(sqlStr, new Object[]{userName, password});
        }
    
        public User findUserByUserName(final String userName){
            String sqlStr = " SELECT user_id,user_name,credits FROM t_user WHERE user_name=? ";
            final User user = new User();
            jdbcTemplate.query(sqlStr, new Object[]{userName}, new RowCallbackHandler() {
                @Override
                public void processRow(ResultSet resultSet) throws SQLException {
                    user.setUserId(resultSet.getInt("user_id"));
                    user.setUserName(userName);
                    user.setCredits(resultSet.getInt("credits"));
                }
            });
            return user;
        }
    
        public void updateLoginInfo(User user){
            String sqlStr = " UPDATE t_user SET last_visit=?,last_ip=?,credits=? WHERE user_id=? ";
            jdbcTemplate.update(sqlStr,new Object[]{user.getLastVisit(),user.getLastIp(),user.getCredits(),user.getUserId()});
        }
    }
    LoginLogDao.java
    package com.test.dao;
    
    import com.test.domain.LoginLog;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Repository;
    
    /**
     * Created by 13051041 on 2016/5/4.
     */
    @Repository
    public class LoginLogDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        public void insertLoginLog(LoginLog loginLog){
            String sqlStr = " INSERT INTO t_logon_log(user_id,ip,login_datetime) VALUES(?,?,?) ";
            Object[] args = {loginLog.getUserId(),loginLog.getIp(),loginLog.getLoginDate()};
            jdbcTemplate.update(sqlStr,args);
        }
    }

    这里用到了两个注解:@Repository 的类都将被注册为 Spring Bean。@Autowire默认按照类型装配。

    到此,持久层的代码已经编码完毕,开始业务层的编码。我们先提供一个Service,把数据库操作抽象成正常的方法调用:

    package com.test.service;
    
    import com.test.dao.LoginLogDao;
    import com.test.dao.UserDao;
    import com.test.domain.LoginLog;
    import com.test.domain.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * Created by 13051041 on 2016/5/4.
     */
    @Service
    public class UserService {
        @Autowired
        private UserDao userDao;
        @Autowired
        private LoginLogDao loginLogDao;
    
        public boolean hasMatchUser(String userName,String password){
            int matchCount = userDao.getMatchCount(userName,password);
            return matchCount > 0;
        }
    
        public User findUserByUserName(String userName){
            return userDao.findUserByUserName(userName);
        }
    
        public void loginSuccess(User user){
            user.setCredits(5 + user.getCredits());
            LoginLog loginLog = new LoginLog();
            loginLog.setUserId(user.getUserId());
            loginLog.setIp(user.getLastIp());
            loginLog.setLoginDate(user.getLastVisit());
            userDao.updateLoginInfo(user);
            loginLogDao.insertLoginLog(loginLog);
        }
    }
    

      一个新的注解:@Service用于标注业务层组件。

    在String mvc中需要一个Servlet,只要在web文件夹下新建一个*-servlet.xml的文件,并且在web.xml中注册就可以了。我们现在需要一个叫dispatcher的Servlet,首先配置web.xml.

    
    

     然后新建dispatcher-servlet.xml,并在里面配置需要的bean。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ss="http://www.springframework.org/schema/security"
           xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jee="http://www.springframework.org/schema/jee"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/websocket"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       	http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
       	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       	http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
       	http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd 
       	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd 
       	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
    
           <!-- Only needed because we install custom converters to support the examples
               in the org.springframewok.samples.mvc.convert package -->
           <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
           <!-- 默认的注解映射的支持 -->
           <mvc:annotation-driven conversion-service="conversionService" />
    
            <context:component-scan base-package="com.test.dao" />
            <context:component-scan base-package="com.test.domain" />
            <context:component-scan base-package="com.test.service" />
            <context:component-scan base-package="com.test.web" />
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        </bean>
    
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource">
                <ref bean="dataSource"></ref>
            </property>
        </bean>
    
        <aop:config proxy-target-class="true">
            <aop:pointcut id="serviceMethod" expression="execution(* com.test.service..*(..))"/>
            <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>
        </aop:config>
    
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
    
    </beans>
    

      里面增加了业务切片的功能,就是大名鼎鼎的aop。但是所学尚欠,后面再慢慢消化吧。

    开始重头戏Controller的编写,主要负责url的配置和连接。

    package com.test.web;
    
    import com.test.domain.User;
    import com.test.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.Date;
    
    /**
     * Created by 13051041 on 2016/5/5.
     */
    @Controller
    public class LogonController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping(value = "/index.html")
         public String loginPage(){
            return "login";
        }
    
        @RequestMapping(value = "/loginCheck.html")
        public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){
            boolean isVaildUser = userService.hasMatchUser(loginCommand.getUserName(),loginCommand.getPassword());
    
            if(!isVaildUser){
                return new ModelAndView("login","error","your password is error!");
            }else{
                User user = userService.findUserByUserName(loginCommand.getUserName());
                user.setLastIp(request.getRemoteAddr());
                user.setLastVisit(new Date());
                userService.loginSuccess(user);
                request.getSession().setAttribute("user",user);
                return new ModelAndView("main");
            }
        }
    }
    

      

    public class LoginCommand {
        private String userName;
        private String password;
    
        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;
        }
    }
    

      代码中,controller将index.html转到了index.jsp。将main.html转到了main.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <html>
    <head>
        <title>Demo的</title>
    </head>
    <body>
      <c:if test="${!empty error}">
          <font color="red"> <c:out value="${error}"/> </font>>
        </c:if>>
    
      <form action="<c:url value="/loginCheck.html"/>" method="post">
          用户名:<input type="text" name="userName"><br>
          密码:<input type="password" name="password"><br>
          <br>
          <input type="submit" value="登录" />
          <input type="reset" value="重置" />
      </form>
    
    
    </body>
    </html>
    

      

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <html>
    <head>
        <title></title>
    </head>
    <body>
        ${user.userName},欢迎!你的积分是:${user.credits}.
    </body>
    </html>
    

      有jsp基础的同学,这些细节也没有好说的。

    例子下载:http://files.cnblogs.com/files/chenjie0949/TestBean.zip

  • 相关阅读:
    关于hexo-abbrlink链接undefined
    如何修改layer-layui中的confirm
    cmder的segmentation fault错误修复
    论好的代码习惯的养成/做一个优雅的coder
    50行代码写的一个插件,破解一个H5小游戏
    慎用array_filter函数
    python:if 语句的使用方法
    python:for语句的使用方法
    关于python3 发送邮件
    zookpeer的安装与配置
  • 原文地址:https://www.cnblogs.com/chenjie0949/p/5465747.html
Copyright © 2011-2022 走看看