springMVC学习笔记

一、关键技术

AOP(Aspect Oriented Program,面向切面编程)
在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。
AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。

IoC(Inversion of Control,控制反转)

由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

DI(Dependency Injection,依赖注入)

相对 IoC 而言,“依赖注入”的确更加准确的描述了这种古老而又时兴的设计理念。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
依赖注入机制减轻了组件之间的依赖关系,同时也大大提高了组件的可移植性,这意味着,组件得到重用的机会将会更多。

JDBC(Java Data Base Connectivity,java数据库连接)

JDBC是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。

bean

java在1996年发布,当年12月即发布了java bean1.00-A,可通过统一的规范可以设置对象的值(get,set方法)。bean是描述Java的软件组件模型,有点类似于Microsoft的COM组件概念。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生成新的应用程序。对于程序员来说,最好的一点就是JavaBean可以实现代码的重复利用,另外对于程序的易维护性等等也有很重大的意义。
作用为:1、所有属性为private;2、提供默认构造方法;3、提供getter和setter;4、实现serializable接口。

PO

PO:持久对象 (persistent object),po(persistent object)就是在Object/Relation Mapping框架中的Entity,po的每个属性基本上都对应数据库表里面的某个字段。完全是一个符合Java Bean规范的纯Java对象,没有增加别的属性和方法。持久对象是由insert数据库创建,由数据库delete删除的。基本上持久对象生命周期和数据库密切相关。

O/R mapping

O/R mapping技术是为了解决关系型数据库和面向对象的程序设计之间不匹配的矛盾而产生的。Hibernate/mybatis是目前最为流行的O/R mapping框架,它在关系型数据库和Java对象之间做了一个自动映射,使得程序员可以以非常简单的方式实现对数据库的操作。

二、DAO层用法

DAO,data access model,数据访问对象,主要是用来访问数据库的。它属于web开发的数据访问层,他可以给程序员提过统一的访问接口,来实现数据库的增删改查操作。Spring Data提供了一整套数据访问层(DAO)的解决方案,致力于减少数据访问层(DAO)的开发量。它使用一个叫作Repository的接口类为基础,它被定义为访问底层数据模型的超级接口。而对于某种具体的数据访问操作,则在其子接口中定义。
Repository(资源库):通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调。这个叫法就类似于我们通常所说的DAO,在这里,我们就按照这一习惯把数据访问层叫Repository 。
JpaRepository: 继承PagingAndSortingRepository,实现一组JPA规范相关的方法。
参考网址:spring mvc 的jpa JpaRepository数据层 访问方式汇总

CURD,是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD。作用是用于处理数据的基本原子操作。代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。
hibernate,是o/r mapping技术,对象到关系型数据库的映射技术,他通过使用一些配置文件,能够自动完成java对象到数据库表的映射,通过使用这项技术,我们在代码中可以像操作对象一样操作数据库。
在实现DAO接口的时候,在函数的实现体内,可以采用hibernate技术来完成数据库的操作,当然也可以自己通过jdbc驱动,自己来编写sql语句来完成。

三、各层关系

分层的目的:高内聚,低耦合。

controller:

也可以成为action层,业务模块流程。我经常喜欢用控制视图的跳转来简单形容,但是这个是不全面的,因为他除了控制视图的转换之外,还控制了业务的逻辑,但是,这里的控制业务逻辑不是业务逻辑的实现,而仅仅是一个大的模块,你看到之后,知道它实现了这个业务逻辑,但是怎么实现的,不需要关心,仅仅需要调用service层里的一个方法即可,这样使controller层看起来更加清晰。

service:

业务逻辑层。接着controller层中,可以想到,service层是业务逻辑(商务逻辑)的具体实现。它向上层的controller层提供接口,并且使用dao层提供的接口。存在的必要性:有时候,我认为更多的时刻,service层中仅仅是调用dao层中的一个方法,那么它是否有必要存在呢?答案是肯定的。因为,假如将来客户的业务有一定的变动,那么这样一来,你只需要在service层中进行一些变动即可。记住,你写程序不应该仅仅为实现功能考虑,更多的还是应该为将来的维护考虑,因为大部分的时间还是在维护上的。

dao:

数据访问对象。他只负责对数据进行访问,而不管其他的什么业务逻辑,其实就是只干活,而不管为什么干。在dao层里面要完成的是数据访问逻辑以及对数据的访问。数据访问,大部分情况下就是对数据进行操作。dao层为上层的service层提供接口。dao层在操作完成后,如果是查询,则返回对象,如果是增删改,则仅仅需要返回一个boolean值表示成功失败即可。

综上,controller调用service,service的实现在serviceImpl里,serviceImpl调用Dao,Dao继承自JpaRepository接口。

四、理解难点

model里的一对多和多对一等实体关系映射

@OneToMany和@ManyToMany
参考网址:JPA总结——实体关系映射(一对多@OneToMany)
在本项目中,如一个用户(user)对应多个位置(user_location),通过用户可以获得该用户的多个位置信息。用户和位置是一对多的关系,两个表之间通过user_location表中的外键user_id联系,并且客户与地址是单向关联的关系。
映射策略
外键关联:两个表的关系定义在一个表中;
表关联:两个表的关系单独定义一个表中通过一个中间表来关联。
本项目中一对多的关系采用外键关联,多对多的关系采用表关联。
数据库结构

    @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "userId"),
            inverseJoinColumns = @JoinColumn(name = "roleId"))
    private List<Role> roles = new ArrayList<Role>();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinTable(name = "user_location",joinColumns = @JoinColumn(name = "idUser"),
            inverseJoinColumns =@JoinColumn(name = "id"))
    private List<UserLocation> userLocations = new ArrayList<UserLocation>();

自定义接口的参数

自定义接口如userDao继承的Repository接口泛型里的第一个参数是要操作的对象,即User;第二个参数是主键的类型,即Integer。
方法即为根据工地找id等,这些接口是不用写实现类的,因为spring data底层会根据一些规则来进行相应的操作。
所以方法的名字是不能随便写的,不然就无法执行想要的操作。

public interface UserDao extends JpaRepository<User, Integer> {

    User save(User user);
    User findByIdnumber(String idnumber);
    List<User> findByIdConstruction(int idConstruction);

int与integer的区别
参考网址:java int与integer的区别
int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象。
Java 中的数据类型分为基本数据类型和复杂数据类型。int 是前者而integer 是后者(也就是一个类);因此在类进行初始化时int类的变量初始为0.而Integer的变量则初始化为null.
两者关系如下:1.int是基本的数据类型;2.Integer是int的封装类;3.int和Integer都可以表示某一个数值;4.int和Integer不能够互用,因为他们两种不同的数据类型。
List的使用

public interface UserService {


    User save(User user);

    User findByIdnumber(String idnumber);

    List<User> findByConstruction_plant_id(int construction_plant_id);

    User findById(Integer id);

    void delete(User user);
}

如代码中所示,findByIdnumber返回了一个User对象,而findByConstruction_plant_id返回了一个List,因为从功能上一个用户(User)只有一个Idnumber,却有多个Construction,因此通过工地查找的时候可能会返回多个用户。

五、细节注意

编程技巧:
IDEA全局搜索快捷键:shift+shift或ctrl+shift+F
文件夹重命名快捷键:shift+F6

编程时先写Dao,继承JpaRepository接口里的findByXXX,save等函数:

Vehicles findByVehicleId(int vehicleId);

注意函数的参数名称要和model里定义的变量名称相对应,在model中定义如下:

private Integer vehicleId;

然后写ServiceImpl,定义findByXXX,save等函数,在函数的实现里返回Dao层定义的函数,注意要先定义一个private的Dao对象,函数是对象的函数(即注意vehiclesDao的大小写的不同含义和区别,大写的是一个class类,小写的是class类的实体对象):

public class VehiclesServiceImpl implements VehiclesService{
    @Autowired
    private VehiclesDao vehiclesDao;
    public Vehicles save(Vehicles vehicles) {
        return vehiclesDao.save(vehicles);
    }
    public Vehicles findByVehicleId(int vehicleId){
        return vehiclesDao.findByVehicleId(vehicleId);

然后写Service,直接声明函数即可:

public interface VehiclesService {
    Vehicles findByVehicleId(int vehicleId);
    Vehicles save(Vehicles vehicles);

最后写controller。

public Result getUser(
            @RequestParam(value = "id") Integer vehicleId) {
        Result result = Result.okResult();
        Vehicles vehicles = vehiclesService.findByVehicleId(vehicleId);
        if (vehicles == null) {
            result.setOk(false);
            result.setErrorMessage("没有此车辆");
            return result;
        }
        result.setData(vehicles);
        return result;
    }

在本项目中,controller里的方法的返回值类型为Result类,使用RequestParam而不用@ResponseBody可以避免用页面中创建表单。其中setData由lombok定义好了,不用自己定义。result对象定义如下:

@Data
public class Result {
    private boolean ok;
    private Object data;
    private int errorCode;
    private String errorMessage;
    public static Result okResult(){
        Result result=new Result();
        result.setOk(true);
        return  result;
    }
    public static Result badResult() {
        Result result = new Result();
        result.setOk(false);
        return result;
    }
}

六、报错解决

Error:Repeated column in mapping for collection
重复映射是因为join_table的name里两个表里的字段一样:

@JoinTable(name = "vehicle_location",joinColumns = @JoinColumn(name = "vehicle_id"),
            inverseJoinColumns =@JoinColumn(name = "vehicle_id"))

解决办法为不设置name的值,则在默认情况下,name的取值遵循以下规则:
name=关联表的名称+“_”+ 关联表主键的字段名
默认根据id去找,因此你不需要自己去指定vehicle_id,他就会找对的。
(但总感觉这个方法治标不治本,一说修改为@Column(insertable=false,updatable=false)也可,但没试过。)

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值