学习笔记--Spring框架

//概述

轻量级,一站式,开发框架

IoC,Inversion of Control,控制反转

DI,Dependency Injection,依赖注入

AOP,Aspect-Oriented Programming,面向切面编程:业务逻辑与非业务逻辑分离,如日志、安全...

IoC容器:

对象创建、装配

对象生命周期管理

上下文环境

//IoC容器

IoC = ApplicationContext  (org.springframework.context,  spring-context)

初始化

ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

ApplicationContext context = new FileSystemXmlApplicationContext("/home/user/conf/application-context.xml");

或在web.xml中

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:application-context.xml</param-value>

</context-param>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

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:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

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">

<bean id="screwDriver" class="com.netease.course.ScrewDriver"></bean>

</beans>

Bean使用

//初始化容器

ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

//获取对象

ScrewDriver screwDriver = context.getBean("screwDriver", ScrewDriver.class);

//使用对象

screwDriver.use();

Bean作用域

singleton,单例

<bean id="screwDriver" class="com.netease.course.ScrewDriver" scope="singleton"></bean>

默认为单例

prototype,每次引用创建一个实例

<bean id="screwDriver" class="com.netease.course.ScrewDriver" scope="prototype"></bean>

request scope, requestBean

session scope, sessionBean

application scope, appBean

global scope

Bean生命周期回调

创建,申请资源

可以通过实现接口

public interface InitializingBean {

void afterPropertiesSet() throws Exception;

}

或者直接在application-context.xml中配置

<bean id="screwDriver" class="com.netease.course.ScrewDriver" init-method="init"></bean>

对应代码

public class ScrewDriver {

public void init() {

System.out.println("Init screwDriver");

}

}

销毁

可以通过实现接口

public interface DisposableBean {

void destroy() throws Exception;

}

或者直接在application-context.xml中配置

<bean id="screwDriver" class="com.netease.course.ScrewDriver" destroy-method="cleanup"></bean>

对应代码

public class ScrewDriver {

public void cleanup() {

System.out.println("Cleanup screwDriver");

}

}

关闭Bean

((ConfigurableApplicationContext) context).close();

依赖注入

构造函数,强依赖

Setter函数,可选依赖

配置bean的类的构造函数的参数

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg value="red"></constructor-arg>

<constructor-arg value="15"></constructor-arg>

</bean>

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg index="0" value="red"></constructor-arg>

<constructor-arg index="1" value="15"></constructor-arg>

</bean>

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg type="java.lang.String" value="red"></constructor-arg>

<constructor-arg type="int" value="15"></constructor-arg>

</bean>

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg name="color" value="red"></constructor-arg>

<constructor-arg name="size" value="15"></constructor-arg>

</bean>

需要传递集合类型的构造函数参数(如map)时

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg>

<map>

<entry key="color" value="red"></entry>

<entry key="size" value="15"></entry>

</map>

</constructor-arg>

<constructor-arg name="size" value="15"></constructor-arg>

</bean>

传入list时

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg>

<list>

<value>red</value>

<value>15</value>

</list>

</constructor-arg>

<constructor-arg name="size" value="15"></constructor-arg>

</bean>

传入Properties时

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg>

<props>

<prop key="color">red</prop>

<prop key="size">15</prop>

</props>

</constructor-arg>

<constructor-arg name="size" value="15"></constructor-arg>

</bean>

从外部倒入配置时

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<constructor-arg name="color" value="${color}"></constructor-arg>

<constructor-arg name="size" value="${size}"></constructor-arg>

</bean>

<bean id="headerProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="location" value="classpath:header.properties" />

</bean>

在一个bean中添加所依赖的bean

<bean id="screwDriver" class="com.netease.course.ScrewDriver">

<constructor-arg>

<ref bean="straightHeader" />

</constructor-arg>

</bean>

通过Setter方法注入依赖

<bean id="straightHeader" class="com.netease.course.StraightHeader">

<property name="color" value="${color}"></property>

<property name="size" value="${size}"></property>

</bean>

自动装配

constructor是按byType方式注入

<bean id="screwDriver" class="com.netease.course.ScrewDriver" autowire="constructor">

</bean>

<bean id="screwDriver" class="com.netease.course.ScrewDriver" autowire="byName">

</bean>

<bean id="screwDriver" class="com.netease.course.ScrewDriver" autowire="byType">

</bean>

Annotation

@Component:定义Bean,或@Component("name")

@Value:properties注入

@Autowired & @Resource:自动装配依赖

@PostConstruct & @PreDestroy:生命周期回调

在xml中加入

<context:component-scan base-package="com.netease.course" />

//AOP技术

AOP术语

Aspect:日志、安全等功能

Join point:函数执行或者属性访问

Advice:在某个函数执行点上要执行的切面功能

Pointcut:匹配横切目标函数的表达式

Advice类型

Before:函数执行之前

After returning:函数正常返回之后

After throwing:函数抛出异常之后

After finally:函数返回之后

Around:函数执行前后

Spring AOP

非完整AOP实现

整合AOP和与IoC

XML schema-based AOP

@AspectJ annotation-based AOP

@AspecsJ annotation-based AOP

aspectjweaver.jar

<?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:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<aop:aspectj-autoproxy />

</beans>

定义Aspect

<bean id="loggingAspect" class="com.netease.course.LoggingAspect">

<!-- configure properties of aspect here as normal -->

</bean>

相应代码中类名前加入@Aspect

定义Pointcut

@Pointcut("execution(* com.netease.course.Calculator.*(..))")

private void arithmetic() {}

Pointcut表达式

designator(modifiers? return-type declaring-type? name(param) throws?)

designator: execution, within

modifiers: public, private

return-type: 返回类型,*

declaring-type: 包名,类名

name: 函数名,*

param: 参数列表,()无参,(..)任意参数

throws: 异常类型

可以组合

定义Advice

@Before("com.netease.course.LoggingAspect.arithmetic()")

public void doLog() {

//

}

@Before("execution(* com.netease.course.Calculator.*(..))")

public void doLog() {

//

}

@AfterReturning("com.netease.course.LoggingAspect.arithmetic()")

public void doLog() {

//

}

@AfterThrowing("com.netease.course.LoggingAspect.arithmetic()")

public void doLog() {

//

}

@After("com.netease.course.LoggingAspect.arithmetic()")

public void doLog() {

//

}

Advice参数

函数上下文信息

@Before("com.netease.course.LoggingAspect.arithmetic()")

public void doLog(JoinPoint jp) {

System.out.println(jp.getSignature() + ", " + jp.getArgs());

}

@Around("com.netease.course.LoggingAspect.arithmetic()")

public void doLog(ProceedingJoinPoint pjp) {

System.out.println("start method: " + pjp.toString());

Object retVal = pjp.proceed();

System.out.println("stop method: " + pjp.toString());

}

返回值

@AfterReturning(pointcut="com.netease.course.LoggingAspect.arithmetic()"),

returning="retVal")

public void doLog(Object retVal) {

//

}

异常

@AfterThrowing(pointcut="com.netease.course.LoggingAspect.arithmetic()"),

throwing="ex")

public void doLog(IllegalArgumentException ex) {

//

}

目标函数参数

@Before("com.netease.course.LoggingAspect.arithmetic() && args(a, ..)")

public void doLog(JoinPoint jp, int a) {

//

}

XML schema-based AOP

定义Aspect和PointCut

<aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:pointcut id="arithmetic" expression="execution(* com.netease.course.Calculator.*(..))" />

</aop:aspect>

</aop:config>

定义Advice

<aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:before pointcut-ref="arithmetic" method="doLog" />

</aop:aspect>

</aop:config>

<aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:before pointcut="execution(* com.netease.course.Calculator.*(..))" method="doLog" />

</aop:aspect>

</aop:config>

<aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:after-returning pointcut-ref="arithmetic" returning="retVal" method="doLog" />

</aop:aspect>

</aop:config>

<aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:after-throwing pointcut-ref="arithmetic" throwing="ex" method="doLog" />

</aop:aspect>

</aop:config>

<aop:aspect id="loggingAspect" ref="loggingBean">

<aop:around pointcut-ref="arithmetic" method="doLog" />

</aop:aspect>

//数据访问

DAO,Data Access Object

数据访问相关接口

ORM,Object Relation Mapping

对象关系映射

DataSource (javax.sql)

DriverManagerDataSource (org.springframework.jdbc.datasource)

BasicDataSource (org.apache.commons.dbcp)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<property name="driverClassName" value="${jdbc.driverClassName}" />

<property name="url" value="${jdbc.url}" />

<property name="username" value="${jdbc.username}" />

<property name="password" value="${jdbc.password}" />

</bean>

<context:property-placeholder location="db.properties" />

JdbcTemplate (org.springframework.jdbc.core)

设置JdbcTemplate的数据库配置信息

private JdbcTemplate jdbcTemplate;

@Autowired

public void setDataSource(DataSource dataSource) {

this.jdbcTemplate = new JdbcTemplate(dataSource);

}

查询操作

int rowCount = this.jdbcTemplate.queryForObject("select count(*) from user", Integer.class);

int countOfNamedJoe = this.jdbcTemplate.queryForObject("select count(*) from user where first_name = ?", Integer.class, "Joe");

String lastName = this.jdbcTemplate.queryForObject("select last_name from user where id = ?", new Object[]{1212L}, String.class);

更改操作

this.jdbcTemplate.update("insert into user (first_name, last_name) values (?, ?)", "Meimei", "Han");


this.jdbcTemplate.execute("create table user (id integer, first_name varchar(100), last_name varchar(100))");


对象匹配

        User user = this.jdbcTemplate.queryForObject("select last_name from user where id = ?",

new Object[]{1212L},

new RowMapper<User>() {

public User mapRow(ResultSet rs, int rowNum) throws SQLException {

User user = new User();

user.setFirstName(rs.getString("first_name"));

user.setLastName(rs.getString("last_name"));

return user;

}

});

List<User> users = this.jdbcTemplate.query("select last_name from user where id = ?",

new Object[]{1212L},

new RowMapper<User>() {

public User mapRow(ResultSet rs, int rowNum) throws SQLException {

User user = new User();

user.setFirstName(rs.getString("first_name"));

user.setLastName(rs.getString("last_name"));

return user;

}

});

定义JdbcTemplate

public class JdbcExampleDao implements ExampleDao {

private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {

this.jdbcTemplate = new JdbcTemplate(dataSource);

}

//...DAO接口实现

}

可以在xml中配置相应的bean

也可以用annotation的方法,如下:

@Repository

public class JdbcExampleDao implements ExampleDao {

private JdbcTemplate jdbcTemplate;

@Autowired

public void setDataSource(DataSource dataSource) {

this.jdbcTemplate = new JdbcTemplate(dataSource);

}

//...DAO接口实现

}

NamedParameterJdbcTemplate (org.springframework.jdbc.core)

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

@Autowired

public void setDataSource(DataSource dataSource) {

this.namedParameterJdbcTemplate= new NamedParameterJdbcTemplate (dataSource);

}

public int countOfUserByFirstName(String firstName) {

String sql = "select count(*) from usertest where first_name = :first_name";

Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);

return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);

}

其他api接口

queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)

queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)

SqlParameterSource: MapSqlParameterSource, BeanPropertySqlParameterSource (org.springframework.jdbc.core.namedparam)

如:

public int countOfUserByFirstName(User user) {

String sql = "select count(*) from usertest where first_name = :first_name";

SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(user);

return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);

}

异常处理

DataAccessException, "unchecked", 是一个基类 (org.springframework.dao)

//事务管理

spring事务管理

统一的事务编程模型,编程式事务及声明式事务(AOP)

public interface PlatformTransactionManager {

TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

void commit(TransactionStatus status) throws TransactionException;

void rollback(TransactionStatus status) throws TransactionException;

}

事务管理器

PlatformTransactionManager (org.springframework.transaction):

DataSourceTransactionManager (org.springframework.jdbc.datasource), JDBC

HibernateTransactionManager (org.springframework.orm.hibernate), Hibernate

TransactionDefinition

getName:事务名称

getIsolationLevel:隔离级别

getPropagationBehavior:传播行为

getTimeout:超时时间

isReadOnly:是否只读

TransactionStatus

isNewTransaction:是否是新事务

hasSavePoint:是否有savepoint(诊断,NESTED)

isCompleted:是否完成

isRollbackOnly:事务结果是否是rollback-only
setRollbackOnly:设置事务为rollback-only

隔离级别

ISOLATION_READ_UNCOMMITTED:读未提交

ISOLATION_READ_COMMITTED:读提交

ISOLATION_REPEATABLE_READ:重复读

ISOLATION_SERIALIZABLE:串行化

ISOLATION_DEFAULT:默认

传播行为

PROPAGATION_MANDATORY:必须在一个事务中运行,不存在则抛异常

PROPAGATION_NEVER:不应该在事务中运行,存在则抛异常

PROPAGATION_NOT_SUPPORTED:不应该在事务中运行,存在则挂起

PROPAGATION_SUPPORTS:不需要事务,有则在事务中执行

PROPAGATION_REQUIRED:必须在事务中执行,如果不存在,则启动新事务(内部事务会影响外部事务)

PROPAGATION_NESTED:必须在事务中执行,如果不存在,则启动新事务(事务之间互不影响)

PROPAGATION_REQUIRES_NEW:必须在新事务中执行,挂起当前事务(独立physical事务)

声明式事务

添加schema

<?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: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-2.0.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-2.0.xsd">

定义事务管理器

<bean id="txManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource" />

</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

destroy-method="close">

<property name="driverClassName" value="${jdbc.driverClassName}" />

<property name="url" value="${jdbc.url}" />

<property name="username" value="${jdbc.username}" />

<property name="password" value="${jdbc.password}" />

</bean>

<context:property-placeholder location="db.properties" />

定义事务Advice

<tx:advice id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<tx:method name="get*" read-only="true" />

<tx:method name="*" />

</tx:attributes>

</tx:advice>

定义Pointcut

<aop:config>

<aop:pointcut id="daoOperation"

expression="execution(* com.netease.course.AccountDao.*(..))" />

<aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperation" />

</aop:config>

配置<tx:method />

name: 匹配的函数名称,支持*匹配

propagation:事务传播行为

isolation:事务隔离级别

timeout:超时

read-only:是否只读事务

rollback-for:触发回滚的异常,用逗号分隔

no-rollback-for:不触发回滚的异常

采用annotation方法

@Transactional

xml中添加

<tx:annotation-driven transaction-manager="txManager" />

相应代码

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)

public boolean deleteClusterByClusterId(Sring clusterId) {

// do work

}

@transactional

value:使用的TransactionManager

propagation:事务传播行为

isolation:事务隔离级别

timeout:超时

readOnly:是否只读

rollbackFor:触发回滚的异常类对象数组

rollbackForClassName:触发回滚的异常类名称数组

noRollbackFor:不触发回滚的异常类对象数组

noRollbackForClassName:不触发回滚的异常类名称数组

编程式事务

定义TransactionTemplate

public class SimpleService implements Service {

private final TransactionTemplate transactionTemplate;

public SimpleService(PlatformTransactionManager transactionManager) {

this.transactionTemplate = new TransactionTemplate(transactionManager);

this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

this.transactionTemplate.setTimeout(30);

}

}

使用TransactionTemplate

public Object someMethod() {

return transactionTemplate.execute(new TransactionCallback() {

public Object doInTransaction(TransactionStatus status) {

updateOperation1();

return resultOfUpdateOperation2();

}

});

}

或(不返回结果)

public Object someMethodWithoutResult() {

return transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {

updateOperation1();

updateOperation2();

}

});

}

或(设置为遇到异常时只能回滚)

public Object someMethodWithoutResult() {

return transactionTemplate

.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(

TransactionStatus status) {

try {

updateOperation1();

updateOperation2();

} catch (SomeBusinessException e) {

status.setRollbackOnly();

}

}

});

}

PlatformTransactionManager的实现

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setName("TxName");

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);

try {

//do something

} catch (MyException ex) {

txManager.rollback(status);

throw ex;

}

txManager.commit(status);

整合MyBatis

SqlSessionFactory

添加mybatis-spring依赖

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis-spring</artifactId>

<version>1.2.3</version>

</dependency>

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.3.0</version>

</dependency>

定义SqlSessionFactoryBean

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="configLocation" value="classpath:sqlMapConfig.xml" />

<property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />

</bean>

定义Mapper

public interface UserMapper {

@Select("SELECT * FROM users WHERE id = #{userId}")

User getUser(@Param("userId") String userId);

}

配置结果映射

@Results({

@Result(property="id", column="id"),

@Result(property="firstName", column="first_name"),

@Result(property="lastName", column="last_name")

})

或者采用xml的方法,见Mybatis部分

定义Mapper Bean

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">

<property name="mapperInterface" value="com.netease.course.UserMapper" />

<property name="sqlSessionFactory" ref="sqlSessionFactory" />

</bean>

或采用自动发现的机制

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://mybatis.org/schema/mybatis-spring

http://mybatis.org/schema/mybatis-spring.xsd">

<mybatis:scan base-package="com.netease.course" />

</beans>

当需要指定SqlSessionFactory时

<mybatis:scan base-package="com.netease.course" factory-ref="sqlSessionFactory" />

或者

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

<property name="basePackage" value="com.netease.course" />

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

</bean>

使用Mapper

public class SomeService {

@Autowired

private UserMapper userMapper;

public User getUser(String userId) {

return userMapper.getUser(userId);

}

}

定义SqlSessionTemplate使用

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">

<constructor-arg index="0" ref="sqlSessionFactory" />

</bean>

SqlSessionTemplate使用

public class UserDao {

@Autowired

private SqlSession sqlSession;

public User getUser(String userId) {

return (User) sqlSession.selectOne("com.netease.course.UserMapper.getUser", userId);

}

}

//Web框架

DispatcherServlet

[servlet-name]-servlet.xml

HandlerMapping

Controllers

View解析相关

WebApplicationContext

ContextLoaderListener

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/applicationContext*.xml</param-value>

</context-param>

Servlet WebApplicationContext (containing controllers, view resolvers, and other web-related beans)

Root WebAppliacationContext (containing middler-tier services, datasources, etc.)

实现Controller

@Controller

@RequestMapping(value = "/hello")

public class HelloController {

@RequestMapping(value = "/spring")

public void spring(HttpServletResponse response) throws IOException {

response.getWriter().write("Hello, Spring Web!!");

}

}

定义Controller

自动发现

<context:component-scan base-package="com.netease.course" />

@RequestMapping

name: 名称

value & path: 路径,如"/hello"

method: 请求方法,如"GET"

params: 请求参数

headers: 请求头

consumes: 请求的媒体类型,"Content-Type"

produces: 响应的媒体类型,"ACCEPT"

注入路径中的变量

@RequestMapping(value="/users/{userId}")

public String webMethod(@PathVariable String userId) {

//do work

}

@RequestMapping(value="/users/{userId:[a-z]+}")

public String webMethod(@PathVariable String userId) {

//do work

}

函数参数

HttpServletRequest / HttpServletResponse, HttpSession (Servlet API)

Reader / Writer

@PathVariable

@RequestParam

@RequestHeader

HttpEntity

@RequestBody

Map / Model / ModelMap

函数返回值

void

String: view名称,@ResponseBody

HttpEntity

View

Map

Model

ModelAndView

函数实现

@RequestMapping(value="/spring/{user}")

public void helloSpring(

@PathVariable("user") String user,

@RequestParam("msg") String msg,

@RequestHeader("host") String host,

HttpServletRequest request,

Writer writer) throws IOException {

writer.write("URI: " + request.getRequestURI());

writer.write("Hello, " + user + ": " + msg + ", host=" + host);

}

@RequestMapping(value="/spring/login")

public void login(@ModelAttribute User user, Writer writer) {

//do work

}

@RequestMapping(value="/users/login")

public String login(@RequestParam("name") String name, @RequestParam("password") String password, ModelMap map) {

map.addAttribute("name", name);

map.addAttribute("password", "******");

return "user";

}

ModelMap 
ModelMap的实例是由bboss mvc框架自动创建并作为控制器方法参数传入,用户无需自己创建。

Java代码  

  1. public String xxxxmethod(String someparam,ModelMap model)
  2. {
  3. //省略方法处理逻辑若干
  4. //将数据放置到ModelMap对象model中,第二个参数可以是任何java类型
  5. model.addAttribute("key",someparam);
  6. ......
  7. //返回跳转地址
  8. return "path:handleok";
  9. }

ModelAndView 
ModelAndView的实例是由用户手动创建的,这也是和ModelMap的一个区别。

Java代码  

  1. public ModelAndView xxxxmethod(String someparam)
  2. {
  3. //省略方法处理逻辑若干
  4. //构建ModelAndView实例,并设置跳转地址
  5. ModelAndView view = new ModelAndView("path:handleok");
  6. //将数据放置到ModelAndView对象view中,第二个参数可以是任何java类型
  7. view.addObject("key",someparam);
  8. ......
  9. //返回ModelAndView对象view
  10. return view;
  11. }

上传文件

定义bean

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<property name="maxUploadSize" value="100000" />

</bean>

相应代码

@RequestMapping(value="/form", method=RequestMethod.POST)

public String handleFormUpload(@RequestParam("file") MultipartFile file) {

// save the file

}

相应依赖

<dependency>  <groupId>commons-fileupload</groupId>  <artifactId>commons-fileupload</artifactId>  <version>1.3.1</version></dependency>

HttpEntity

@RequestMapping(value="/something")

public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) {

String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader");

byte[] requestBody = requestEntity.getBody();

// do something with requestHeader and requestBody

HttpHeaders responseHeaders = new HttpHeaders();

responseHeaders.set("MyResponseHeader", "MyValue");

return new ResponseEntity<String>("hello spring", responseHeaders, HttpStatus.CREATED);

}

@RequestBody & @ResponseBody

@RequestMapping(value="/spring")

@ResponseBody

public String spring(@RequestBody String body) throws IOException {

return "hello" + body;

}

MessageConverter,返回Java对象的转化

RequestBody ---> Object: 参数

ResponseBody <--- Object: 返回值

xml文件配置

<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"

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/mvc

http://www.springframework.org/schema/mvc/spring-mvc.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.netease.course" />

<mvc:annotation-driven />

</beans>

添加相应依赖,如JSON相关依赖

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-core</artifactId>

<version>2.6.4</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.6.4</version>

</dependency>

View解析

String      名称

View

ModelAndView

Map

Model

ViewResolver (org.springframework.web.servlet):

InternalResourceViewResolver (org.springframework.web.servlet.view)

FreeMarkerViewResolver (org.springframework.web.servlet.view.freemarker)

ContentNegotiatingViewResolver (org.springframework.web.servlet.view)

InternalResourceViewResovler

Servlet, JSP

bean定义

<bean id="viewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix" value="/WEB-INF/jsp/" />

<property name="suffix" value=".jsp" />

</bean>

resultView -------> /WEB-INF/jsp/resultView.jsp

FreeMarkerViewResolver

FreeMarker

bean定义

<bean id="freemarkerConfig"

class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />

</bean>

<bean id="viewResolver"

class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

<property name="cache" value="true" />

<property name="prefix" value="" />

<property name="suffix" value=".ftl" />

<property name="contentType" value="text/html; charset=utf-8" />

</bean>

ContentNegotiatingViewResolver

ViewResovler的组合

扩展名:user.json, user.xml, user.pdf

Accept头(media types):application / json, application / xml

bean定义

<bean

class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">

<property name="viewResolvers">

<list>

<bean id="viewResolver"

class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

<property name="cache" value="true" />

<property name="prefix" value="" />

<property name="suffix" value=".ftl" />

</bean>

</list>

</property>

<property name="defaultViews">

<list>

<bean

class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />

</list>

</property>

</bean>

DefaultRequestToViewNameTranslator

example/admin/index.html ---------> admin/index

example/display.html -------> display

ContentNegotiatingViewResolver 根据路径后缀,选择不同视图

方法一:使用扩展名

http://localhost:8080/learn/user.xml 获取xml类型数据

http://localhost:8080/learn/user.json  获取json类型数据

http://localhost:8080/learn/user  使用默认view呈现,如jsp

方法二:使用http 请求头的Accept

GET /user HTTP/1.1

Accept:application/xml

GET /user HTTP/1.1

Accept:application/json

方法三:使用参数

http://localhost:8080/learn/user?format=xml

http://localhost:8080/learn/user?format=json

  1. <!-- 同一资源,多种表述 -->
  2. <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
  3. <!-- 是否启用扩展名支持,默认为true -->
  4. <property name="favorPathExtenion" value="true" />
  5. <!-- 是否启用参数支持,默认为true -->
  6. <property name="favorParameter" value="false" />
  7. <!-- 是否忽略掉accept header,默认为false -->
  8. <property name="ignoreAcceptHeader" value="true" />
  9. <!-- 扩展名到mimeType的映射 -->
  10. <property name="mediaTypes">
  11. <map>
  12. <!-- 例如:/user.json 中的 .json 会映射到 application/json -->
  13. <entry key="json" value="application/json" />
  14. <entry key="xml" value="application/xml" />
  15. </map>
  16. </property>
  17. <!-- 如果所有mediaType都没匹配上,就使用defaultContentType -->
  18. <property name="defaultContentType" value="text/html"/>
  19. </bean>
  20. <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
  21. <!-- 解析器的执行顺序 -->
  22. <property name="order" value="1" />
  23. <property name="contentNegotiationManager" ref="contentNegotiationManager" />
  24. <property name="defaultViews">
  25. <list>
  26. <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean>
  27. <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
  28. <constructor-arg>
  29. <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  30. <property name="classesToBeBound">
  31. <list>
  32. <value>com.learn.model.User</value>
  33. </list>
  34. </property>
  35. </bean>
  36. </constructor-arg>
  37. </bean>
  38. </list>
  39. </property>
  40. </bean>
  41. <!-- 上面没匹配到则会使用这个视图解析器 ,解析为jsp  -->
  42. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  43. <property name="order" value="2" />
  44. <property name="prefix" value="/" />
  45. <property name="suffix" value=".jsp"/>
  46. </bean>  

    来源: http://blog.csdn.net/littleskey/article/details/53392283

Controller中可以用RequestMapping匹配多个路径后缀

@RequestMapping(value = {"/users", "/users.html", "/users.json"})

public String getUsersInfo(ModelMap map) {

List<User> users = userServiceImp.getUsers();

map.addAttribute("users", users);

return "users";

}

FreeMarker

模板引擎

数据模型

对象:hashes

基本类型:scalars

注释

<#-- 这是注释 -->

插值:表达式

${animal.name}

直接指定值:

字符串,如“Zoo”, ‘Zoo‘

数字,如123.45

布尔值,如true,false

序列,如["zoo", "bar", 123]

值域,如0..9,0..<10

哈希表,如{"name":"green mouse", "price":150}

检索变量:

顶层变量:user

哈希表数据:user.name, user["name"]

列表数据:products[5]

连接操作:

users + "guest"

passwords + "joe":"secret123"

算术操作

逻辑操作

比较操作

FTL标签:指令

开始标签:<#directivename parameters>

结束标签:</#directivename>

if指令

<#if user=="Big Joe">, our beloved leader</#if>

list指令

<#list animals as animal>

<tr><td>${animal.name}<td>${animal.price} Euros

</#list>

include指令

<#include "/copyright_footer.html">

使用

创建配置

Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);

cfg.setDirectoryForTemplateLoading(new File("/where/you/store/templates"));

cfg.setDefaultEncoding("UTF-8");

cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

定义模板

定义数据模型

Map<String, Object> root = new HashMap<>();

root.put("user", "Big Joe");

Map<String, Object> latestProduct = new HashMap<>();

root.put("latestProduct", latestProduct);

latestProduct.put("url", "products/greenmouse.html");

latestProduct.put("name", "greenmouse");

添加依赖

<dependency>

<groupId>org.freemarker</groupId>

<artifactId>freemarker</artifactId>

<version>2.3.23</version>

</dependency>

输出结果

Template ftl = cfg.getTemplate("user.ftl");

Writer outWriter = new OutputStreamWriter(System.out);

ftl.process(root, outWriter);

工程模板

一般java目录

com.netease.course.dao

com.netease.course.meta

com.netease.course.service

com.netease.course.service.impl

com.netease.course.utils

com.netease.course.web.controller

com.netease.course.web.filter

时间: 2024-08-11 03:36:27

学习笔记--Spring框架的相关文章

Java学习笔记:Spring框架

1.什么是Spring? 1.1 spring 是一个开源框架 1.2 spirng 为简化企业级应用开发而生,使用 spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能 1.3 spring 是一个 IOC(DI) 和 AOP 容器框架 2.Spring入门示例   2.1 HelloWorld.java package com.oneline.spring.day01; public class HelloWorld { private String name;

Spring学习笔记--Spring IOC

沿着我们上一篇的学习笔记,我们继续通过代码学习IOC这一设计思想. 6.Hello类 第一步:首先创建一个类Hello package cn.sxt.bean; public class Hello { private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello,"+name); } } 第二步:创建配置

SpringMVC学习指南-Spring框架

Spring框架主要使用依赖注入.实际上,很多牛叉的框架如Google的Guice都是使用依赖注入. ------------------------------------------------------依赖注入和IOC容器-------------------------------------------------------- 1.依赖注入 有两个组件A和B,其中A中的一个方法使用到了B中的方法: public classs A{ public void MethodA{ B b=

Spring学习笔记--Spring简介

1.spring:给软件行业带来了春天; 2.spring的理念:spring框架的初衷是使的现有的更加实用,spring不是创造轮子(技术或框架),而是使现有的轮子更好的运转;spring本身是一个大杂烩,整合现有的框架技术: 3.Spring优点: 轻量级框架:不具备侵入性(使用某个框架,我们不需要实现它的某个接口,方便框架的替换,原有的代码不需要替换); Ioc容器:控制反转; Aop:面向切面编程; 对事务的支持: 对矿建的支持; ................... 4.主要内容:

[学习笔记]spring mvc 与struts2比较

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(二) 在上一篇文章中我详细的介绍了如何搭建maven环境以及生成一个maven骨架的web项目,那么这章中我将讲述Spring MVC的流程结构,Spring MVC与Struts2的区别,以及例子中的一些配置文件的分析. 一.Spring MVC 3.0介绍 Spring MVC是一个典型的MVC框架,是Spring内置的Web框架,可以作为应用项目的展示层,继Spring 2.0对Spring

学习笔记——Spring+SpringMVC+MyBatis框架整合

一.Maven创建项目 1. 在Eclipse中选择New -> Project -> Maven -> Maven Project 2. 选择默认workspace之后建立maven-webapp 3. 填写Group Id和Artifact Id(项目名称) 4. 建立工程后发现目录结构报错 5. 为了避免乱码,右键点击工程选择Properties -> Resource,选择编码方式为UTF-8 6. 在Properties中选择Java Build Path -> J

[学习笔记]Spring注解实现Bean

12.3  注解实现Bean定义 12.3.1  概述 前边介绍的Bean定义全是基于XML方式定义配置元数据,且在[12.2注解实现Bean依赖注入]一节中介绍了通过注解来减少配置数量,但并没有完全消除在XML配置文件中的Bean定义,因此有没有方式完全消除XML配置Bean定义呢? Spring提供通过扫描类路径中的特殊注解类来自动注册Bean定义.同注解驱动事务一样需要开启自动扫描并注册Bean定义支持,使用方式如下(resources/chapter12/ componentDefini

Spring学习笔记——Spring中lazy-init与abstract具体解释

Spring的懒载入的作用是为了避免无谓的性能开销,就是当真正须要数据的时候才去运行数据的载入操作.不只在Spring中.我们在实际的编码过程中也应该借鉴这种思想,来提高我们程序的效率. 首先我们看一段配置文件: <beans> <bean> <bean id="creditService" type="com.jader.service.CreditServiceImpl" lazy-init="true"/>

HTML学习笔记21——框架集(品字形布局)

框架:<frameset rows="200px,*">                      //rows表示行分块(cols表示列分块),*表示除了200px之外的大小,都赋给第二行 <frame src="xx.html" ></frame> <frame src="xx.html" ></frame>  </frameset> 不需要<body><