2015-12-25:
类加载路径classpath: classpath:/ 是等价的。都是相对于类的根路径。
classpath*:加载所有相同的classpath下的资源。
例如自己的项目路径和引入的jar包的路径重叠,
那么:
classpath:只扫描第一个加载的包。
classpath*: 加载所有的包
2015-12-14:
下面的classpath路径问题,其实有一个非常方便的方法解决!
就是查看项目中的build目录下的class目录。
这下面的是项目编译过后产生的,路径一目了然
注意:
2015-12-10:发现一个极其奇怪的问题,即classpath
本示例完美运行,然而之后本人新建立一个项目,结构一致,然而
当我配置log的时候,
classpath*:log/log4j.properties 提示无法找到
classpath*:spring/spring.xml这个却找到了
换成
classpath:log/log4j.properties则日志OK
classpath:spring/spring.xml 也OK
classpath*:spring/spring.xml 也OK
classpath*:common/jdbc.properties 也OK
不明就里
最后全部统一
classpath:log/log4j.properties
classpath:spring/spring.xml
目录
- 概述
- 建立项目
- 配置Spring.xml文件
- 编写完整流程代码
- 总结
No.1 概述
Spring框架在此不多介绍。本文是作为一名初学者的角度,来一步步建立起一个完整的Spring web项目并且调试通过。整个项目尽量做到简单,使用最新的jar。
环境:eclipse,mysql
No.2 建立项目
第一步:建立一个动态web工程,取名MySpring,点击next,next,选择生成web.xml
第二步:在WEB-INF的lib目录下引入jar包,基本的jar以及依赖的jar
其中包括连接mysql以及httpclient的jar
第三步:建立工程目录,本例取名com.csdn.myspring,以及简单的目录结构
- resource存放资源文件(properties,xml等)
- test存放测试用例
结构如图所示:(为了简单,并没有考虑代码的’优雅’)
No.3 配置spring xml文件
1.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>MySpring</display-name>
<!--之前这个地方加了个contex:param-name,contextConfigLocation以及相应的listener,后来发现每次bean都被创建了两次,貌似这种是针对放到WEB-INF下的Application.xml,我们手动指定了目录,则不要这个-->
<!--添加对日志的监听-->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!--添加springmvc的servlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--容器启动的时候加载指定目录的配置文件-->
<!--classpath*:resouce/spring/spring.xml如果resource和src是平级的,那么不加resource-->
<param-value>classpath*:spring/spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--设置过滤模式,此处是全接收-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--设置编码,但是目前看来没什么用-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
2.加入相应的配置文件
(此处为了结构清晰,易于扩展,spring.xml仅仅是一个导入的功能,具体的bean或者数据库的配置在其他的xml来配置)
目录如下:
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--每一个url都对应了需要使用的东西-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath*:spring/spring-view.xml"/>
<import resource="classpath*:spring/spring-database.xml"/>
<import resource="classpath*:spring/spring-bean.xml"/>
</beans>
spring-bean.xml
ps:一般的类bean不写成这种,直接在类上加上注解,而后通过context:component-scan扫描进来,spring则会把被它所管理的类创建
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 (controller/service/resposity注解的作用就是声明,可以被scan发现)-->
<context:component-scan base-package="com.csdn.myspring" />
<bean id="test" class="com.csdn.myspring.controller.TestBean" scope="singleton">
</bean>
</beans>
spring-database.xml
ps:使用的是c3p0数据源,以及spring JdbcTemplate
<?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"
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.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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- jdbc配置文件 -->
<context:property-placeholder location="classpath*:database/jdbc.properties"/>
<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--连接池中保留的最小连接数。 -->
<property name="minPoolSize">
<value>5</value>
</property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize">
<value>30</value>
</property>
<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize">
<value>10</value>
</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime">
<value>60</value>
</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">
<value>3</value>
</property>
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements">
<value>0</value>
</property>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts">
<value>30</value>
</property>
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
</bean>
<!-- 配置事务管理器
<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.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>
spring-view.xml
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 添加注解驱动(还没太理解,貌似和扫描类一个道理) -->
<mvc:annotation-driven />
<!-- 定义跳转的文件的前后缀 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
<!--网上有些使用&后跟上utf-8,多次实验证明&会使后面的utf-8编码失效,如果你发现中文插入数据库乱码,那么检查下jdbc这里的配置是不是用了&-->
jdbc.url=jdbc:mysql://localhost:3306/springwebtest?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
log4j.properties
ps:现在还没使用
log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [\u65E5\u5FD7\u4FE1\u606F] %m%n
No.4 逻辑流程代码
代码目录如图所示:
UserController.java
package com.csdn.myspring.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import com.csdn.myspring.dao.UserDao;
import com.csdn.myspring.entity.UserEntity;
/**
* 用户控制
* @author Ming
*
*/
@Controller // 标注为controller,便于spring管理
@RequestMapping(value = "/user")
public class UserController {
@Autowired // 它的实现userDaoImpl因被spring创建了,所以无需初始化
private UserDao userDao; // 注入的是一个接口。能够自动找到它的实现,便于更改实现
@RequestMapping(value = "/userInfoJSP")
public String userInfo() {
// return "success"; //跳转到success页面
return "user";
}
/**
* 查看
* @param json
* @return
*/
@RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
@ResponseBody
public String getUserInfo(String json) {
String result = null; //返回值
System.out.println("这是一个测试");
return result;
}
/**
* 保存
* @param json
* @return
*/
@RequestMapping(value = "/saveUserInfo", method = RequestMethod.POST)
@ResponseBody
public String saveUserInfo(@RequestBody String json) {
String result = null; //返回值
UserEntity user = JSONObject.parseObject(json,UserEntity.class); //将传来的json转换为对象
System.out.println("这是一个测试");
userDao.save(user);
return result;
}
}
UserDaoImpl .java
package com.csdn.myspring.dao.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.csdn.myspring.dao.UserDao;
import com.csdn.myspring.entity.UserEntity;
@Repository // 注解表明被spring管理,当被扫描到则被创建
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void save(UserEntity user) {
// 与表结构一一对应
String sql = "insert into user(u_name,password,credits) values(?,?,?)";
jdbcTemplate.update(sql, new Object[]{user.getuName(),user.getPassword(),user.getCredits()});
}
@Override
public void update(UserEntity user) {
// TODO Auto-generated method stub
}
@Override
public UserEntity getPerson(int id) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<UserEntity> getUsers() {
// TODO Auto-generated method stub
return null;
}
@Override
public void delete(int personid) {
// TODO Auto-generated method stub
}
}
UserEntity .java
package com.csdn.myspring.entity;
/**
* User实体
* @author ming
*
*/
public class UserEntity {
private int uId; //id
private String uName; //名字
private int credits;
private String password;
public int getuId() {
return uId;
}
public void setuId(int uId) {
this.uId = uId;
}
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public int getCredits() {
return credits;
}
public void setCredits(int credits) {
this.credits = credits;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
至此,全部项目代码以及配置完成。可以进行测试了。
先开启mysql服务,而后创建数据库表。
项目加入tomcat,并启动。
用postman插件输入如下:
点击send.完成后没报错。
之后查看数据库:
已经正确的插入,并且无乱码。至此一个简单的springmvc项目算是完成了!
(未涉及前端)
No.5 总结
1.最初resource目录放在src中,所以写的是
classpath*:resource/spring/spring-view.xml
这种带有resource的。之后resource目录放在与src平级的根目录,导致没有加载xml文件,将resource/去掉,
classpath*:spring/spring-view.xml
OK!成功了
2.项目乱码,web.xml设置了后,debug模式发现收到的是乱码。
在客户端需要设置application/json;charset=UTF-8(注意是分号),客户端收到了中文,但是数据库还是乱码,数据库的编码已经设置过,而后查看发现需要设置jdbc.properties:
jdbc.url=jdbc:mysql://localhost:3306/springwebtest?useUnicode=true&characterEncoding=UTF-8
OK!乱码问题解决
3.两种创建bean的方式
// 第一种
<bean id="test" class="com.csdn.myspring.controller.TestBean" scope="singleton">
</bean>
// 第二种
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入
(controller/service/resposity注解的作用就是声明,可以被scan发现)-->
<context:component-scan base-package="com.csdn.myspring" />
除了spring本身的一些bean需要些bean标签。其他的项目本身的代码类都通过注解后扫描的方式来实现。方便而又快捷明了
4.这一章的主要目的是搭建整个项目框架,以及学习spring的ioc(控制反转),spring aop的知识在下一章在进行探索研究。
——2015-12-9下午14:30添加:
之前web.xml中说道filter感觉没用,是因为没有配置filter-mapping,完整的过滤如下:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
从这个例子可以看出来,web.xml里面的都是一个东西对应一个mapping,如果没有mapping,相当于是摆设,并没使用它。加上这个filter mapping后,则postman客户端无需再设置编码utf-8。