spring3.x第二章 快速入门

第二章 快速入门
2.1 实例功能概述
2.1.1比HelloWorld更适用的实例

  论坛的登陆模块

2.1.2实例功能简介

  登陆页面提供输入账号密码的输入表单。填写并提交表单,服务端检查是否匹配,不匹配返回登陆页面,匹配就成功登陆并重定向到欢迎页面。

2.2 环境准备

  使用MySQL5.X

2.2.1 创建库表

  创建用户表,创建用户登录表。并插入初始化的一个数据

//新建数据库
DROP DATABASE IF EXISTS sampledb;
CREATE DATABASE sampledb DEFAULT CHARACTER SET utf8;
USE sampledb;
//新建用户表
CREATE TABLE t_user(
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    user_name VARCHAR(30),
    credit INT,
    password VARCHAR(32),
    last_visit datetime,
    last_ip VARCHAR(23)
)ENGINE=InnoDB;
//新建登陆日志表
CREATE TABLE t_login_log(
    login_long_id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    ip VARCHAR(23),
    login_datetime datetime
)ENGINE=InnoDB;
//初始化数据
INSERT INTO t_user(user_name, password)VALUES('admin','123456');
2.2.2 建立工程

  使用MyEclipse

2.2.3 类包及Spring配置文件规划

  2.2.3_2017-01-25_11-50-45.png
  Spring可以将所有的配置信息统一到一个文件中,也可以放置到多个文件中。即applicationContext.xml配置文件。

2.3 持久层
2.3.1 建立领域对象

  领域对象(Domain Object)也称为实体类。
  用户领域对象

package com.liwenguang.baobaotao.domain;
import java.util.Date;
public class User implements Serializable{
    private int userId;
    private String userName;
    private String password;
    private int credits;
    //省略Get、Set方法
}
package com.liwenguang.baobaotao.domain;
import java.util.Date;
public class LoginLog implements Serializable{
    private int loginLogId;
    private int userId;
    private String ip;
    private Date loginDate;
    //省略Get、Set方法
}
2.3.2 UserDao和LoginLogDao

  访问实体类的DAO。

package com.liwenguang.baobaotao.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
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 com.liwenguang.baobaotao.domain.User;
@Repository //通过注解定义一个DAO
public class UserDao {

    /**
     * 根据用户名和密码获取匹配的用户数
     */
    @Autowired //自动注入JdbcTemplate的Bean
    private JdbcTemplate jdbcTemplate;

    public int getMatchCount(String userName, String password){
        String sqlString = "SELECT count(*) FROM t_user"+
                "WHERE user_name = ? and password = ?";
        return jdbcTemplate.queryForInt(sqlString, new Object[]{userName, password});
    }

    /**
     * 根据用户名获取用户对象
     * @param userName
     * @return
     */
    public User findUserByUserName(final String userName){
        String sqlString = "SELECT user_id, user_name, credits FROM t_user"
                +" WHERE user_name = ?";
        final User user = new User();
        jdbcTemplate.query(sqlString, new Object[]{userName},
                new RowCallbackHandler() {

                    @Override
                    public void processRow(ResultSet rs) throws SQLException {
                        // 对数据指针进行回调
                        user.setUserId(rs.getInt("user_id"));
                        user.setUserName(userName);
                        user.setCredits(rs.getInt("credits"));
                    }
                });
        return user;
    }

    /**
     * 更新用户积分,最后登陆IP,最后登陆时间
     * @param user
     */
    public void updateLoginInfo(User user){
        String sqlString = "UPDATE t_user SET last_visit = ?, last_ip = ?, credits = ?"+
                " WHERE user_id = ?";
        jdbcTemplate.update(sqlString, new Object[]{user.getLastVisit(), user.getLastIp(), user.getCredits()});

    }
}
package com.liwenguang.baobaotao.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.liwenguang.baobaotao.domain.LoginLog;

@Repository
public class LoginLogDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void insertLoginLog(LoginLog loginLog){
        String sqlString = "INSERT INTO t_login_log(user_id, ip, login_datetime)"
                +"VALUES(?,?,?)";
        Object[] argsObjects = {loginLog.getUserId(), loginLog.getIp(), loginLog.getLoginDate()};
    }
}
2.3.4 在Spring中装配DAO

  在以上两个DAO实现类中都没有打开/释放Connection的代码,DAO类究竟如何访问数据库呢?所以我们首先声明一个数据源即数据库,然后定义一个JdbcTemplate Bean,通过Spring的容器上下文进行Bean的注入。即applicationContext.xml的Spring配置文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 引用Spring的多个Schema空间的格式定义文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入,这样@Repository以及@Autowires才会起作用  -->
    <context:component-scan base-package="com.liwenguang.baobaotao.dao"/>
    <!-- 定义一个使用DBCP实现的数据源 -->
    <bean
        id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/sampledb"
        p:username="root"
        p:password=""/>

    <!-- 定义Jdbc模版Bean -->
    <bean
        id="jdbcTemplate"
        class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource"/>
</beans>
2.4 业务层
2.4.1 UserService
package com.liwenguang.baobaotao.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.liwenguang.baobaotao.dao.LoginLogDao;
import com.liwenguang.baobaotao.dao.UserDao;
import com.liwenguang.baobaotao.domain.LoginLog;
import com.liwenguang.baobaotao.domain.User;
@Service //将UserService标注为一个服务层的Bean
public class UserService {
    @Autowired //注入DAO层的Bean
    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());e
        loginLog.setIp(user.getLastIp());
        loginLog.setLoginDate(user.getLastVisit());
        userDao.updateLoginInfo(user);
        loginLogDao.insertLoginLog(loginLog);
    }
}
2.4.2 在Spring中装配Service
<!-- 配置事务管理器 -->
    <bean
        id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource"/>
    <!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法 拥有事务-->
    <aop:config
        proxy-target-class="true">
        <aop:pointcut
            id="serviceMethod"
            expression=" execution(* com.liwenguang.baobaotao.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>
2.4.3 单元测试
package com.liwenguang.baobaotao.service;
import static org.junit.Assert.*;
import java.util.Date;
import javax.swing.Spring;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.liwenguang.baobaotao.domain.User;
@RunWith(SpringJUnit4ClassRunner.class) //基于JUnit4的Spring测试框架
@ContextConfiguration(locations={"/applicationContext.xml"}) //启动Spring容器
public class TestUserService {
    @Autowired //注入Spring容器中的Bean
    private UserService userService;
    @Test
    public void testHasMatchUser() {
        boolean b1 = userService.hasMatchUser("admin", "123456");
        boolean b2 = userService.hasMatchUser("admin", "1111");
        assertTrue(b1);
        assertTrue(!b2);
    }
    @Test
    public void testFindUserByUserName(){
        User user = userService.findUserByUserName("admin");
        assertEquals(user.getUserName(), "admin");
    }
    @Test
    public void testAddLoginLog(){
        User user = userService.findUserByUserName("admin");
        user.setUserId(1);
        user.setUserName("admin");
        user.setLastIp("192.168.12.7");
        user.setLastVisit(new Date());
        userService.loginSuccess(user);
    }
}
2.5 展现层
2.5.1 配置Spring MVC框架

对web.xml文件进行配置,以便Web容器启动时能够自动启动Spring容器

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    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_3_0.xsd">
    <!-- 从类路径下记载Spring配置文件,classpath关键字特指类路径下加载 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 负责启动Spring容器的监听器,它将引用上下文参数获得Spring配置文件参数 -->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
        <servlet-name>baobaotao</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>baobaotao</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
</web-app>
2.5.2 处理登陆请求

  POJO控制器类

package com.liwenguang.baobaotao.web;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
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 com.liwenguang.baobaotao.domain.User;
import com.liwenguang.baobaotao.service.UserService;
@Controller //标注为SpringMVC的控制器,处理HTTP的请求,首先会是一个Bean,所以可以使用@Autowired进行Bean的注入
public class LoginController {
    @Autowired
    private UserService userService;
    //负责处理/index.html的请求
    @RequestMapping(value = "/index.html")
    public String loginPage(){
        return "login";
    }
    //负责处理/loginCheck.html的请求
    @RequestMapping(value = "/loginCheck.html")
    public ModelAndView loginCheck(HttpServletRequest request, LoginCommand loginCommand){
        boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(), loginCommand.getPassword());
        if (!isValidUser) {
            return new ModelAndView("login", "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");
        }
    }
}
package com.liwenguang.baobaotao.web;
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;
    }
}

  Spring MVC配置文件:编写完控制器后,需要在baobaotao-servlet中声明该控制器,扫描Web路径,指定Spring MVC的仕途解析器。

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <!-- 扫描web包,应用Spring的注解 -->
    <context:component-scan base-package="com.liwenguang.baobaotao.web"/>
    <!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:viewClass="org.springframework.web.servlet.view.JstlView" 
        p:prefix="/WEB-INF/jsp/"
        p:suffix=".jsp" />
</beans>
2.5.3 JSP视图页面
2.6 运行Web应用
2.7 小结

  复杂的代码实现简单的功能,但是如果新增功能非常方便

2.8 学习中的问题:

  aopalliance-1.0.jar、aspectjweaver-1.7.0.jar、spring-aspects-4.0.2.RELEASE.jar三个包是用于支持applicationContext.xml中声明的AOP所依赖的三个包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值