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(),
credits INT,
password VARCHAR(),
last_visit datetime,
last_ip VARCHAR()
)ENGINE=InnoDB;
创建一个登录日志表,字段分别是:日志ID,用户ID,ip和登录时间。同样设置为内联。
CREATE TABLE t_logon_log(
login_log_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
ip VARCHAR(),
login_datetime datetime
)ENGINE=InnoDB;
在用户名表内插入一段数据:用户名admin,密码123456。
INSERT INTO t_user(user_name,password) VALUES ("admin","");
自此数据库的搭建,进行完毕。我们开始写代码。
使用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
Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)的更多相关文章
- Spring AOP (Spring 3.x 企业应用开发实战读书笔记第六章)
从面相对象编程到面相切面编程,是一种代码组织方式的进化. 每一代的代码组织方式,其实是为了解决当时面对的问题.比如写编译器和写操作系统的时候的年代当然要pop,比如写界面的时候当然要oop,因为界面这 ...
- [Effective Java 读书笔记] 第二章 创建和销毁对象 第一条
第二章 创建和销毁对象 第一条 使用静态工厂方法替代构造器,原因: 静态工厂方法可以有不同的名字,也就是说,构造器只能通过参数的不同来区分不同的目的,静态工厂在名字上就能表达不同的目的 静态工厂方法 ...
- 《精通Spring+4.x++企业应用开发实战》读后感
引言 还记得大三时上培训班的是时候,当时的培训老师说自己是本地讲解spring最好的讲师,但是后来等我实习了看了<Spring 3.x 企业应用开发实战>以及后续版本<精通Sprin ...
- 学习《Spring 3.x 企业应用开发实战》Day-1
Day-1 记录自己学习spring的笔记 提要:根据<Spring 3.x 企业应用开发实战>开头一个用户登录的例子,按照上面敲的. 1.项目分层
- Spring实战读书笔记
Spring实战读书笔记 Spring-core Spring之旅 - DI 和 AOP 概念 spring 的Bean容器 spring 的 核心模块 Spring的核心策略 POJO 最小侵入式编 ...
- Spring 3.x企业实用开发实战(1)
有关Spring的介绍这里就不赘述了,主要是学习了陈雄华版的<Spring 3.x企业应用开发实战>并做了一点笔记,以助于后期的回顾和复习. 废话不多说,直接进入主题,以下所有代码基于&l ...
- 《精通Spring 4.X企业应用开发实战》读书笔记1-1(IoC容器和Bean)
很长一段时间关注在Java Web开发的方向上,提及到Jave Web开发就绕不开Spring全家桶系列,使用面向百度,谷歌的编程方法能够完成大部分的工作.但是这种不系统的了解总觉得自己的知识有所欠缺 ...
- 第一章 Andorid系统移植与驱动开发概述 - 读书笔记
Android驱动月考1 第一章 Andorid系统移植与驱动开发概述 - 读书笔记 1.Android系统的架构: (1)Linux内核,Android是基于Linux内核的操作系统,并且开源,所以 ...
- Spring MVC介绍和第一个例子
1.Spring mvc概述 spring mvc是spring提供给web应用框架设计,实际上MVC框架是一个设计理念.它不仅存在java世界中而且广泛在于各类语言和开发中,包括web的前端应用.对 ...
随机推荐
- c功能实战
1,linux C连接ftp实现简单的上传下载; libcurl/libftp/busybox; oracle查看用户信息 1. 查询oracle中所有用户信息 select * from dba_u ...
- work2
回答问题: 描述在这么多相似的需求面前, 你怎么维护你的设计 (父类/子类/基类, UML, 设计模式, 或者其它方法) 让整个程序的架构不至于崩溃的? 答:诚然,问题给出了很多选项如-a,-v,- ...
- hdu 5505 GT and numbers
GT and numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- 背景透明文字不透明的最佳方法兼容IE(以背景黑色透明度0.5为例)
以背景黑色,透明度0.5举例为大家详细介绍下关于背景透明,文字不透明的最佳方法同时兼容IE,具体实现如下,感兴趣的朋友可以参考下哈希望对大家有所帮助 以背景黑色,透明度0.5举例 非IE:backgr ...
- Android项目实战--手机卫士24--程序锁的实现以及逻辑
昨天我们已经把程序全部读取出来,显示到界面上了,那今天,我们就来讲一下那个程序锁的实现啦.其实也很简单啦,我们主要就是把用户要锁定的程序放到一个表里面,然后就监听手机里面的任务栈,如果发现任务栈里面出 ...
- Oracle- PL/SQL DEV的远程配置
首先装好Oracle企业版或者客户端精简版.之后要修改你的的tnsnames.ora文件,来增加数据库. 我的ORACLE实例是ORACLE1,放在D:\oracle\ 目录下.我的IP地址是 192 ...
- JavaScript 的原型对象 Prototype
在 JavaScript 中,每当定义一个对象(或函数)时候,对象中都会包含一些预定义的属性,其中一个属性就是原型对象 prototype. var myObject = function( name ...
- C#操作sql通用类 SQLHelper
Codeusing System; using System.Data; using System.Configuration; using System.Web; using System.Web. ...
- Oracle DataGuard数据备份方案详解
Oracle DataGuard是一种数据库级别的HA方案,最主要功能是冗灾.数据保护.故障恢复等. 在生产数据库的"事务一致性"时,使用生产库的物理全备份(或物理COPY)创建备 ...
- Android的横竖屏切换
android的横竖屏切换,也会发生不少问题. 1. 锁定屏幕方向,禁止切换: 在AndroidManifest.xml中的Activity参数中加上 android:screenOrientat ...