Spring

1、Spring概述

①Spring是一个开源框架

②Spring为简化企业级开发而生,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。

③Spring是一个IOC(DI)和AOP容器框架。

④Spring的优良特性:

[1]非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
​
[2]控制反转:IOC——Inversion of Control,指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。
​
[3]依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用setXX方法去设置,而是通过配置赋值。
​
[4]面向切面编程:Aspect Oriented Programming——AOP
​
[5]容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
​
[6]组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
​
[7]一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)

IOC和AOP

IOC

控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上。

通常,我们实例化一个对象时,都是使用类的构造方法来new一个对象,这个过程是由我们自己来控制的,而控制反转就把new对象的工交给了Spring容器。

IOC的主要实现方式有两种:依赖查找、依赖注入。

依赖注入是一种更可取的方式。

那么依赖查找和依赖注入有什么区别呢?

依赖查找,主要是容器为组件提供一个回调接口和上下文环境。这样一来,组件就必须自己使用容器提供的API来查找资源和协作对象,控制反转仅体现在那些回调方法上,容器调用这些回调方法,从而应用代码获取到资源。

依赖注入,组件不做定位查询,只提供标准的Java方法让容器去决定依赖关系。容器全权负责组件的装配,把符合依赖关系的对象通过Java Bean属性或构造方法传递给需要的对象。

2.1 IOC容器 IoC容器:具有依赖注入功能的容器,可以创建对象的容器。IoC容器负责实例化、定位、配置应用程序中的对象并建立这些对象之间的依赖。

2.2 依赖注入 DI,英文全称,Dependency Injection,意为依赖注入。

依赖注入:由IoC容器动态地将某个对象所需要的外部资源(包括对象、资源、常量数据)注入到组件(Controller, Service等)之中。简单点说,就是IoC容器会把当前对象所需要的外部资源动态的注入给我们。

Spring依赖注入的方式主要有四个,基于注解注入方式、set注入方式、构造器注入方式、静态工厂注入方式。推荐使用基于注解注入方式,配置较少,比较方便。

基于注解注入方式

服务层代码

@Service
public class AdminService {
    //code
}

控制层代码

@Controller
@Scope("prototype")
public class AdminController {
​
@Autowired
private AdminService adminService;
​
//code
​
}

@Autowired与@Resource都可以用来装配Bean,都可以写在字段、setter方法上。他们的区别是:

@Autowired默认按类型进行自动装配(该注解属于Spring),默认情况下要求依赖对象必须存在,如果要允许为null,需设置required属性为false,例:@Autowired(required=false)。如果要使用名称进行装配,可以与@Qualifier注解一起使用。

@Autowired
@Qualifier("adminService")
private AdminService adminService;

@Resource默认按照名称进行装配(该注解属于J2EE),名称可以通过name属性来指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行装配;如果注解写在setter方法上,默认取属性名进行装配。当找不到与名称相匹配的Bean时,会按照类型进行装配。但是,name属性一旦指定,就只会按照名称进行装配。

@Resource(name = "adminService")
private AdminService adminService;

除此之外,对于一些复杂的装载Bean的时机,比如我们需要根据配置装载不同的Bean,以完成不同的操作,可以使用getBean(“beanID”)的方式来加载Bean。

通过BeanID加载Bean方法如下:

@Component
public class BeanUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
 
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
    if (BeanUtils.applicationContext == null) {
        BeanUtils.applicationContext = applicationContext;
    }
}
 
public static ApplicationContext getApplicationContext() {
    return applicationContext;
}
 
public static Object getBean(String id) throws Exception {
    try {
        return applicationContext.containsBean(id) ? applicationContext.getBean(id) : null;
    } catch (BeansException e) {
        e.printStackTrace();
        throw new Exception("not found bean id: " + id);
    }
}
}

我们在需要装载Bean的地方调用该方法即可

public class BaseController {
protected IService loadService(String id) throws Exception {
    IService iService = (IService) BeanUtils.getBean(id);
    if (iService != null) {
        return iService;
    } else {
        throw new Exception("加载Bean错误");
    }
}
}

AOP(面向切面编程)

面向切面编程(AOP)就是纵向的编程。比如业务A和业务B现在需要一个相同的操作,传统方法我们可能需要在A、B中都加入相关操作代码,而应用AOP就可以只写一遍代码,A、B共用这段代码。并且,当A、B需要增加新的操作时,可以在不改动原代码的情况下,灵活添加新的业务逻辑实现。

在实际开发中,比如商品查询、促销查询等业务,都需要记录日志、异常处理等操作,AOP把所有共用代码都剥离出来,单独放置到某个类中进行集中管理,在具体运行时,由容器进行动态织入这些公共代码。

AOP主要一般应用于签名验签、参数校验、日志记录、事务控制、权限控制、性能统计、异常处理等。

1 AOP涉及名词 切面(Aspect):共有功能的实现。如日志切面、权限切面、验签切面等。在实际开发中通常是一个存放共有功能实现的标准Java类。当Java类使用了@Aspect注解修饰时,就能被AOP容器识别为切面。

通知(Advice):切面的具体实现。就是要给目标对象织入的事情。以目标方法为参照点,根据放置的地方不同,可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。在实际开发中通常是切面类中的一个方法,具体属于哪类通知,通过方法上的注解区分。

连接点(JoinPoint):程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出等。Spring只支持方法级的连接点。一个类的所有方法前、后、抛出异常时等都是连接点。

切入点(Pointcut):用于定义通知应该切入到哪些连接点上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。

比如,在上面所说的连接点的基础上,来定义切入点。我们有一个类,类里有10个方法,那就产生了几十个连接点。但是我们并不想在所有方法上都织入通知,我们只想让其中的几个方法,在调用之前检验下入参是否合法,那么就用切点来定义这几个方法,让切点来筛选连接点,选中我们想要的方法。切入点就是来定义哪些类里面的哪些方法会得到通知。

目标对象(Target):那些即将切入切面的对象,也就是那些被通知的对象。这些对象专注业务本身的逻辑,所有的共有功能等待AOP容器的切入。

代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象的功能等于目标对象本身业务逻辑加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。目标对象被织入共有功能后产生的对象。

织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译时、类加载时、运行时。Spring是在运行时完成织入,运行时织入通过Java语言的反射机制与动态代理机制来动态实现。

事务

ACID原则

一、简介 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列。事务必须满足ACID原则——即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

二、原子性 原子性指事务是数据库工作的最小单位,一个事务中的所有操作要么全部成功提交,要么全部失败回滚。以经典的银行转账情境为例,假设A和B两个账户分别拥有100元,此时A向B转账100元。对于数据层面包含两个操作:

操作1:A账户余额减少100元,账户余额为0元; 操作2:B账户余额增加100元,账户余额为200元

显然这两个操作要么同时成功则转账成功,要么同时失败则转账失败。此时这两个操作应在同一个事务中。

三、一致性 一致性指事务操作不能破坏数据的一致性,数据库在一个事务的执行前后都应处于一致性状态。仍以上述转账情境为例:在转账事务前后数据库中的总钱数都应是200元。假设在修改数据的过程中数据库发生故障(例如宕机)则事务被迫中断,此时如果未完成的事务中的部分操作已经写入数据库则会破坏数据的一致性。

四、隔离性 隔离性指数据库并发情况下,并发的事务直接是隔离的,一个事务的执行不能被其他事务影响。隔离性比较复杂,在MySQL中存在四种隔离级别:Read Uncommitted、Read Committed、Repeatable Read和Serializable,不同的隔离级别采用不同的锁机制实现。

五、持久性 持久性指一旦事务提交,则其对数据的变更就是永久性的,即使数据库发生任何故障都不应该对数据造成任何影响。持久性很好理解,如果上述转账事务成功前数据库故障,重启后A和B账户仍应各有100元;反正如果在事务成功后故障,那么重启后A和B账户应分别拥有0元和200元。

事务产生的问题

场景:同一个事务内(同一个服务内)

名称数据的状态实际行为产生原因
脏读未提交打算提交但是数据回滚了,读取了提交的数据数据的读取
不可重复读已提交读取了修改前的数据数据的修改
幻读已提交读取了插入前的数据数据的插入

事务隔离级

名称结果脏读不可重复读幻读
Read UnCommitted(读未提交)什么都不解决
Read Committed(读提交)解决了脏读的问题
Repeatable Read(重复读)(mysql的默认级别)解决了不可重复读 )
Serializable(序列化)解决所有问题

READ UNCOMMITTED(读未提交数据):允许事务读取未被其他事务提交的变更数据,会出现脏读、不可重复读和幻读问题。 READ COMMITTED(读已提交数据):只允许事务读取已经被其他事务提交的变更数据,可避免脏读,仍会出现不可重复读和幻读问题。 REPEATABLE READ(可重复读):确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止其他事务对此字段的更新,可以避免脏读和不可重复读,仍会出现幻读问题。 SERIALIZABLE(序列化):确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,可避免所有并发问题,但性能非常低。

Spring隔离级别

int ISOLATION_DEFAULT = -1;   默认采用数据库的隔离级
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;   //0000 0001 -> 1 
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;       //0000 0010-> 2
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;     //0000 0100-> 4
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;          // 0000 1000-> 8

spring事务7种传播行为

一、

Propagation :key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用: PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。 PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。 PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。 PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

Spring常用注解

1.声明bean的注解

@Component组件,没有明确的角色

@Service 在业务逻辑层使用(service层)

@Repository 在数据访问层使用(dao层)

@Controller 在展现层使用,控制器的声明(C)

2.注入bean的注解

@Autowired:由Spring提供

@Inject:由JSR-330提供

@Resource:由JSR-250提供

都可以注解在set方法和属性上,推荐注解在属性上(一目了然,少写代码)。

3.java配置类相关注解

@Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)

@Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)

@Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上)

@ComponentScan 用于对Component进行扫描,相当于xml中的(类上)

@WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解

4.切面(AOP)相关注解

Spring支持AspectJ的注解式切面编程。

@Aspect 声明一个切面(类上) 使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。

*@After* 在方法执行之后执行(方法上) *@Before* 在方法执行之前执行(方法上) *@Around* 在方法执行之前与之后执行(方法上)

@PointCut 声明切点 在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)

5.@Bean的属性支持

*@Scope* 设置Spring容器如何新建Bean实例(方法上,得有@Bean) 其设置类型包括:

Singleton (单例,一个Spring容器中只有一个bean实例,默认模式), Protetype (每次调用新建一个bean), Request (web项目中,给每个http request新建一个bean), Session (web项目中,给每个http session新建一个bean), GlobalSession(给每一个 global http session新建一个Bean实例)

@StepScope 在Spring Batch中还有涉及

@PostConstruct 由JSR-250提供,在构造函数执行完之后执行,等价于xml配置文件中bean的initMethod

@PreDestory 由JSR-250提供,在Bean销毁之前执行,等价于xml配置文件中bean的destroyMethod

6.@Value注解

@Value 为属性注入值(属性上) 支持如下方式的注入: 》注入普通字符

@Value("Michael Jackson")
String name;

》注入操作系统属性

@Value("#{systemProperties['os.name']}")
String osName;

》注入表达式结果

@Value("#{ T(java.lang.Math).random() * 100 }") 
String randomNumber;

》注入其它bean属性

@Value("#{domeClass.name}")
String name;

》注入文件资源

@Value("classpath:com/hgs/hello/test.txt")
String Resource file;

》注入网站资源

@Value("http://www.cznovel.com")
Resource url;

》注入配置文件

@Value("${book.name}")
String bookName;

注入配置使用方法: ① 编写配置文件(test.properties)

	book.name=《三体》

② @PropertySource 加载配置文件(类上)

@PropertySource("classpath:com/hgs/hello/test/test.propertie")

③ 还需配置一个PropertySourcesPlaceholderConfigurer的bean。

7.环境切换

@Profile 通过设定Environment的ActiveProfiles来设定当前context需要使用的配置环境。(类或方法上)

@Conditional Spring4中可以使用此注解定义条件话的bean,通过实现Condition接口,并重写matches方法,从而决定该bean是否被实例化。(方法上)

8.异步相关

@EnableAsync 配置类中,通过此注解开启对异步任务的支持,叙事性AsyncConfigurer接口(类上)

@Async 在实际执行的bean方法使用该注解来申明其是一个异步任务(方法上或类上所有的方法都将异步,需要@EnableAsync开启异步任务)

9.定时任务相关

@EnableScheduling 在配置类上使用,开启计划任务的支持(类上)

@Scheduled 来申明这是一个任务,包括cron,fixDelay,fixRate等类型(方法上,需先开启计划任务的支持)

10.@Enable*注解说明

这些注解主要用来开启对xxx的支持。 @EnableAspectJAutoProxy 开启对AspectJ自动代理的支持

@EnableAsync 开启异步方法的支持

@EnableScheduling 开启计划任务的支持

@EnableWebMvc 开启Web MVC的配置支持

@EnableConfigurationProperties 开启对@ConfigurationProperties注解配置Bean的支持

@EnableJpaRepositories 开启对SpringData JPA Repository的支持

@EnableTransactionManagement 开启注解式事务的支持

@EnableTransactionManagement 开启注解式事务的支持

@EnableCaching 开启注解式的缓存支持

11.测试相关注解

@RunWith 运行器,Spring中通常用于对JUnit的支持

@ContextConfiguration 用来加载配置ApplicationContext,其中classes属性用来加载配置类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestConfig.class})
public class KjtTest {
 
    private static Logger logger = LoggerFactory.getLogger("KjtTest");
 
    @Autowired
    Service service;

 
    @Test
    public void test() {
        
    }
}
 

SpringMVC部分的注解

@EnableWebMvc 在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,若无此句,重写WebMvcConfigurerAdapter方法(用于对SpringMVC的配置)。

*@Controller* 声明该类为SpringMVC中的Controller

*@RequestMapping* 用于映射Web请求,包括访问路径和参数(类或方法上)

@ResponseBody 支持将返回值放在response内,而不是一个页面,通常用户返回json数据(返回值旁或方法上)

@RequestBody 允许request的参数在request体中,而不是在直接连接在地址后面。(放在参数前)

@PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。

@RestController 该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。

@ControllerAdvice 通过该注解,我们可以将对于控制器的全局配置放置在同一个位置,注解了@Controller的类的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上, 这对所有注解了 @RequestMapping的控制器内的方法有效。

@ExceptionHandler 用于全局处理控制器里的异常

@InitBinder 用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中。

@ModelAttribute 本来的作用是绑定键值对到Model里,在@ControllerAdvice中是让全局的@RequestMapping都能获得在此处设置的键值对。

SpringMVC

SpringMVC 概述 Spring 为展现层提供的基于 MVC 设计理念的优秀的 Web 框架,是目前最主流的 MVC 框架之一 Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架。 Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。 支持 REST 风格的 URL 请求。 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。 2. SpringMVC是什么 一种轻量级的、基于MVC的Web层应用框架。偏前端而不是基于业务逻辑层。Spring框架的一个后续产品。 Spring框架结构图(新版本):

3 SpringMVC能干什么 天生与Spring框架集成,如:(IOC,AOP) 支持Restful风格 进行更简洁的Web层开发 支持灵活的URL到页面控制器的映射 非常容易与其他视图技术集成,如:Velocity、FreeMarker等等 因为模型数据不存放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用) 非常灵活的数据验证、格式化和数据绑定机制、能使用任何对象进行数据绑定,不必实现特定框架的API 更加简单、强大的异常处理 对静态资源的支持 支持灵活的本地化、主题等解析 SpringMVC运行原理

如图所示:

流程说明:

(1)客户端(浏览器)发送请求,直接请求到DispatcherServlet。

(2)DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。

(3)解析到对应的Handler后,开始由HandlerAdapter适配器处理。

(4)HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。

(5)处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。

(6)ViewResolver会根据逻辑View查找实际的View。

(7)DispaterServlet把返回的Model传给View。

(8)通过View返回给请求者(浏览器)

三层架构和mvc区别

三层架构 三层架构是指:视图层view,服务层service,持久层Dao,通常也叫(表示层UI,业务逻辑层BLL,数据访问层DAL)它们的功能是: 1.view层: 用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面 2.service层:实现业务的主要逻辑,是系统架构中体现核心价值的部分。 3.Dao层:有时候也称为是持久层,其功能主要是负责数据库的访问。可以访问数据库、二进制文件、文本文件等。简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那么就会包括对象和数据表之间的mapping,以及对象实体的持久化。

三层架构的出现是为了降低耦合度,在这里,使用面向抽象编程,也就是上层对下层的调用,直接通过接口来完成,下层对上层的真正服务提供者,是下层实现的接口实现类,实现类是可以更换的,这就实现了层间的解耦合。

实际项目中的包命名结构,其实就是三层架构的体现:

xxx:代表公司名称 yyy:代表项目名称

com.xxx.yyy.dao      dao层接口 com.xxx.yyy.dao.impl    dao层实现 com.xxx.yyy.service    service层接口 com.xxx.yyy.service.impl  service层实现       com.xxx.yyy.web      web层 com.xxx.yyy.util      工具包 com.xxx.yyy.domain    javabean MVC MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式: 1.View: 视图,为用户提供使用界面,与用户进行交互。 2.Model: 模型承载数据,对用户提交请求进行计算的模块,分为两类:1.数据承载bean,2.业务承载bean,数据承载bean是指实体类专门承载业务数据的,比如Student,User,业务处理bean是指Service或者Dao对象,专门处理用户的请求的。 Controller:控制器,用来将用户请求转发给相应的Model进行处理,并且根据Model的计算结果向用户提供相应的响应。

MVC工作流程:

最典型的MVC就是我们最近学习的JSP + Servlet + javabean的模式。

三层架构与MVC的关系

三层架构与MVC毫无关系。之所以这样说,是因为它们二者使用范围不同:三层可以应用于任何语言、任何技术的应用程序;而MVC只是为了解决B-S应用程序视图层各部分的耦合关系。它们互不冲突,可以同时存在,也可根据情况使用其中一种。

之所以我们会混淆,是因为在进行web开发时两者会同时使用。

在三层架构设计中,表示层可由MVC设计模式中的视图和控制器来实现,而业务逻辑层和数据访问层则组成MVC设计模式中的模型的实现。因此,在实际的应用中,都是采用三层架构来搭建系统的框架,而表示层与业务逻辑层和数据访问层的交互则是通过MVC设计模式来实现。 SSM与三层架构的对应关系 SSM,即SpringMVC,Spring与Mybatis的统称。

1.SpringMVC:作为view的实现者,它的controller作为整个应用的控制器,完成用户请求的转发和对用户的响应。 2.Mybatis:作为Dao的实现者,完成数据库的增伤改查等功能。 3.Spring:是整个应用的大管家,整个应用中所有的bean的生命周期行为,都是由Spring来管理的,就是说整个应用中所有的对象的创建,初始化,销毁,以及对象之间关联的关系维护,都是由Spring来进行管理。

SpringMVC前台传值到后台的方法

使用request.getParameter("属性名“)取值

页面代码

<form action="${basePath }doLogin.htm" method="post" οnsubmit="check();">
			用户名:<input name="username" type="text" id="un"><br><br>
			密    码:<input name="password" type="password" id="pwd">
			<button type="submit">登陆</button>
</form>

后台代码

@RequestMapping("/doLogin.htm")
	public String doLogin(HttpServletRequest req){
		String u = req.getParameter("username");
		System.out.println(u);
		return "/user/welcome";
	}

二。使用注解方式传值

后台代码

	@RequestMapping("/doLogin.htm")
	public String doLogin(@RequestParam("username")String username){
		System.out.println(username);
		return "/user/welcome";
	}

三。参数传值

后台代码

	@RequestMapping("/doLogin.htm")
	public String doLogin(String username){
		System.out.println(username);
		return "/user/welcome";
	}

第二种比较适合用于form表单传值,第三种可以用于界面之间相互传值,也方便开发人员利用AJAX传值

Spring mvc 返回json数据的四种方式

一.返回ModelAndView,其中包含map集

/*
     * 返回ModelAndView类型的结果
     * 检查用户名的合法性,如果用户已经存在,返回false,否则返回true(返回json数据,格式为{"valid",true})
     */
    @RequestMapping(value = "/checkNameExistsMethod2", produces = "application/json;charset=UTF-8") //这里的produces值在不设置的情况下将根据返回结果自动决定
    public @ResponseBody
    ModelAndView checkNameValidMethod2(@RequestParam String name) {
        boolean result = true;
       //...
        Map<String, Boolean> map = new HashMap<>();
        map.put("valid", result);
        return new ModelAndView(new MappingJackson2JsonView(), map);
    }

二.返回String类型的json,这里有两种方式。

方式一:使用jackson-databind-x.x.x.jar包中的ObjectMapper将Map型数据改写为String并返回

  	/*
     * 返回String类型的结果
     * 检查用户名的合法性,如果用户已经存在,返回false,否则返回true(返回json数据,格式为{"valid",true})
     */
    @RequestMapping(value = "/checkNameExistsMethod1", produces = "application/json;charset=UTF-8")
    public @ResponseBody
    String checkNameValidMethod1(@RequestParam String name) {
        boolean result = true;
        //...
        Map<String, Boolean> map = new HashMap<>();
        map.put("valid", result);
        ObjectMapper mapper = new ObjectMapper();
        String resultString = "";
        try {
            resultString = mapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return resultString;
    }

方式二:

直接返回字符串,主要key/value值必须使用含有转义字符\的双引号,单引号无效

 	/*
     * 返回String类型的结果
     * 检查用户名的合法性,如果用户已经存在,返回false,否则返回true(返回json数据,格式为{"valid",true})
     */
    @RequestMapping(value = "/checkNameExistsMethod1", produces = "application/json;charset=UTF-8")
    public @ResponseBody
    String checkNameValidMethod1(@RequestParam String name) {
        boolean result = true;
     
        String resultString = "{\"result\":true}"; //注意一定是双引号 "{\"result\":\"success\"}"
      
        return resultString;
    }

三.返回任何预定义class类型的结果:

@RequestMapping(value = "/findEmployeebyName")
    public @ResponseBody
    Employee findEmployeebyName(String name) {
        List<Employee> lstEmployees = employeeService.getAllEmployees();
        for (Employee employee : lstEmployees) {
            if (employee.getName().equals(name))
                return employee;
        }
        return null;
    }

这里的Employ必须事先定义好。

四.使用HttpServletResponse对象的response.getWriter().write(xxx)方法

@RequestMapping(value="/forbiddenUser")
    public void forbiddenUser(int id,HttpServletRequest request,HttpServletResponse response) {
        String resultString="{\"result\":\"success\"}";//注意一定是双引号 "{\"result\":true}"    
        try {
            response.setContentType("application/json");
            response.getWriter().write(resultString);
        } catch (IOException e) {
            e.printStackTrace();
        }        
    }

1.拦截器

Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。

将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

拦截器和过滤器的区别:

2.自定义拦截器

自定义拦截器的三个步骤:

①创建拦截器类实现HandlerInterceptor接口 ②配置拦截器 ③测试拦截器的拦截效果

①创建拦截器类实现HandlerInterceptor接口

perHandler中的返回值

如果是true:代表放行

如果返回false,代表不放行,也就是后面的操作都不会执行。但是可以在噶方法里面通过response转发和重定向

package com.lsy.interceptor;
 
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class MyInterceptor1 implements HandlerInterceptor {
    //在目标方法执行之前 执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
        System.out.println("preHandle.....");
        return true;
    }
 
    //在目标方法执行之后 视图对象返回之前执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("postHandle...");
    }
 
    //在流程都执行完毕后 执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("afterCompletion....");
    }
}

②在spring-mvc中配置拦截器

<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--表示对那些资源进行拦截操作-->
            <!--/**表示对所有的资源都进行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.lsy.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

③测试拦截器的拦截效果

package com.lsy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class TargetController {
@RequestMapping("/target")
public ModelAndView show(){
    System.out.println("目标资源执行......");
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("name","itcast");
    modelAndView.setViewName("index");
    return modelAndView;
	
	}
}

3.多拦截器的应用

package com.lsy.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyInterceptor2 implements HandlerInterceptor {
    //在目标方法执行之前 执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
        System.out.println("preHandle22222.....");
        return true;
    }
//在目标方法执行之后 视图对象返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    System.out.println("postHandle2222...");
}
 
//在流程都执行完毕后 执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    System.out.println("afterCompletion2222....");
	}
}
<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--表示对那些资源进行拦截操作-->
            <!--/**表示对所有的资源都进行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.lsy.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--表示对那些资源进行拦截操作-->
            <!--/**表示对所有的资源都进行拦截操作-->
            <mvc:mapping path="/**"/>
            <bean class="com.lsy.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
 
    </mvc:interceptors>

mybatis

一、Mybatis简介 MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。 MyBatis 避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集。 MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 二、为什么要使用Mybatis? MyBatis是一个半自动化的持久化层框架。 JDBC:SQL夹在Java代码块里,耦合度高导致硬编码内伤。维护不易且实际开发需求中sql是有变化,频繁修改的情况多见 Hibernate和JPA:长难复杂SQL,对于Hibernate而言处理也不容易;内部自动生产的SQL,不容易做特殊优化;基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。导致数据库性能下降。 对开发人员而言,核心sql还是需要自己优化 sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据。

一、mybatis简单注解

注解说明
@Insert实现新增
@Delete实现删除
@Update实现更新
@Select实现查询
@Result实现结果集封装
@Results可以与@Result 一起使用,封装多个结果集
@ResultMap实现引用@Results 定义的封装
@One实现一对一结果集封装
@Many实现一对多结果集封装
@SelectProvider实现动态 SQL 映射
@CacheNamespace实现注解二级缓存的使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值