Web应用项目开发

前言

  • 项目背景

本项目是采用前后端项目架构实现的“学生课程习题集”系统。主要聚焦系统后端实现,学生可从学习过程中学习系统架构、Spring Boot前后端分离开发、业务流程分析、各中技术的集成等相关知识。而且,由于使用的是前后端分离开发,所以学生也可以为后续项目扩展打好基础,进一步学习相关的技术完成知识储备

  • 开发基础:

能够自行配置集成开发环境;熟悉构建工具Maven;Web 应用打包部署,理解和掌握Spring Boot应用开发的流程;学会不同方式SpringBoot 项目的创建;学会数据持久化及业务层编码;理解和掌握控制器编码;能利用前端模板组织页面数据。

  • Web安全及性能

理解Web安全风险,能够自行实现一种安全机制,并掌握一种主流的Web安全框架;了解缓存的原理,学会SpringCache集成Redis提升Web性能;了解并使用消息中间件RabbitMQ

一、基础

在Spring Boot项目中,一旦引入了Web依赖启动器spring-boot-starter-web,那么Spring Boot整合Spring MVC框架默认实现的一些XxxAutoConfiguration自动配置类就会自动生效,几乎可以在无任何额外配置的情况下进行Web开发。

1.掌握Spring Boot中MVC功能的定制和拓展。

2.掌握Spring Boot整合Servlet三大组件的实现。

3.掌握Spring Boot项目的打包和部署。

4.掌握Spring Boot文件上传和下载的实现。

二、Spring MVC 功能拓展实现

步骤:

1、项目基础环境搭建

2、功能拓展实现

3、效果测试

三、异常处理

1、自定义错误响应页面

响应页面定义可以有几种方式

第1种:有模板引擎

  • 精确匹配error状态码,通过将错误页面命名为具体的错误状态码,例如:404.html放在引擎目录templates/error目录中,当发生对应状态码错误时,就可以响应对应的模板页。
  • 模糊匹配error状态码,通过定义4xx或5xx,匹配对应类型的所有错误。
  • 此种方式,精确匹配优先于模糊匹配。

第2种:没有模板引擎
此种方式,模板引擎无法找到对应的错误页面

  • 将至静态资源目录中的error目录中找相应页面

第3种:模板/静态目录种均无相应错误页面,直接响应SpringBoot默认错误页面

如果BasicErrorController的errorhtml方法没有找到对应的view对象,将前往error定义在
ErrorMvcAutoConfiguation的defaultErrorView中。

2、自定义错误页面
  • 在resources/templates中添加首页的index.html页面
  • 在源码文件夹Application类的同目录中添加web文件夹,并创建IndexController
  • 使用@Controller注解,完整名称org.springframework.stereotype.Controller

Annotation(注解)是Java的一种特殊注释机制,JVM可通过反射读取注解内容,从而根据
注解内容进行特定操作。
注解以@开头常见注解如@Override,给toString等方法注解表示重写,这类的注解仅用于开发者,编译器处理完就会被去掉该注解用于定义控制器类,在spring项目中由控制器负责将用户发来的请求转发到对应的服务接口(Service层)

  • 添加一个index方法,为index页面提供页面数据(此处无)
  • 为index方法添加@GetMapping("/")注解,该注解提供路由信息,负责URL到Controller中的
  • 具体方法的映射;也可以通过WebMvcConfigurer进行视图和控制器的映射实现页面映射
  • 在templates中创建error文件夹,并创建404.html和500.html两个页面
  • 运行测试,并在index方法中主动制造错误,测试500页面,访问不存在的url,测试404页面
packagecn.edu.lzzy.config;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.ViewControllerRegistry;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
springmvc自定义配置
*
/
@Configuration
publicclassMvcConfigureimplementsWebMvcConfigurer{
publicvoidaddViewControllers(ViewControllerRegistryregistry){
//这样就不需要为每一个页面编写Controller代码了,对于纯渲染的页面可以直接这样定义就可以
registry.addViewController("/home").setViewName("index");//forWard实现
}
}
<!--templates/index.html-->
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>主页</title>
</head>
<body>
<h1>
我是站点首页<br>
内容正在建设中,请耐心等待
</h1>
</body>
</html>
<!--templates/error/404.html-->
<!DOCTYPEhtml>
<htmllang="en"xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<divclass="container">
<divclass="starter-template">
<h1>404——找不到对象</h1>
<divth:inline="text">你好,'[[${#httpServletRequest.remoteUser}]]'你访问的页面不存在</div>
</div>
</div>
</body>
</html>

3、自定义错误处理

  • 在web同目录下添加handler文件夹。
  • 添加两个自定义异常类,NotFoundException和BusinessException,代表资源不存在和业务异常。
  • 添加一个统一的异常处理类PracticeExceptionHandler。
  • 使用@ControllerAdvice注解该类,该注解将所有Controller作为切面,利用切面技术Controller扩展功能。
  • 添加专用于业务异常处理的异常处理方法,并使用ExceptionHandler注解,参数为自定义的业务异常类。
  • 添加通用的异常处理方法,并使用ExceptionHandler注解,参数为Exception类。

另一个@RestControllerAdvice注解将所有的RestController作为切面,为RESTful
Api扩展功能。

除全局异常处理外,还提供全局数据绑定功能:
全局数据绑定:@ModelAttribute,可对所有Controller的Model添加全局属性,示例如下:

①全局控制器添加全局数据

@ControllerAdvice
publicclassGlobalController{
@ModelAttribute
publicvoidaddGlobalData(Modelmodel){
model.addAttribute("contact","lzzy@163.com");
model.addAttribute("homeUrl","https://www.baidu.com")
}
}

②在控制器类中无需绑定数据,如:

@Controller
publicclassHomeController{
@GetMapping("/")
publicStringindex(){
return
"
index"
}
}

③在index.html中使用Thymeleaf绑定全局数据

<!DOCTYPEhtml>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>
<spanth:text="'欢迎访问必应搜索引擎:'+${homeUrl}+'惊不惊喜,意不意
外'"></span><br>
<spanth:text="'联系偶们:'+${contact}"></span>
</h1>
</body>
</html>

四、项目实现

  • 认证业务接口实现

Spring Boot数据持久层技术有:
1.MyBatis
2.JdbcTemplate(SpringBoot自带)
3.SpringDataJpa规范

SpringBoot整合JdbcTemplate
原生JDBC进行数据操作,代码冗余度高。Spring针对此问题封装了JdbcTemplate,它可以通过
Spring注入功能将数据源注入JdbcTemplate中,Spring中的IOC容器可以将数据源当作Java
Bean进行管理,完成代码简化。

SpringBoot整合Mybatis
Mybatis持久层框架同样封装了jdbc操作细节,开发人员秩序关注sql语句,无需关注注册驱动、创
建链接等过程,使用ORM(ObjectRelationalMapping,即'对象/关系'数据库映射)思想实现对结
果集的封装。

SpringBoot整合Jpa

Jpa(JavaPersistenceAPI)是SUN公司提出的ORM规范,提供了一种对象/映射工具来管理Java应
用中的关系数据,使用XML或者注解的方式简化对数据库的操作。
它的出现是为了规范现有的ORM框架,采用Jpa开发时,我们仍将使用这些ORM框架,只是此时开发出
来的应用不在依赖于某个持久化提供商。应用可以在不修改代码的情况下载任何JPA环境下运行,真正做到低耦合,可扩展的程序设计。类似于JDBC,在JDBC出现以前,我们的程序针对特性的数据库API进行编程,但是现在我们只需要针对JDBCAPI编程,这样能够在不改变代码的情况下就能换成其他的数据库。
而Spring-Data-jpa是在Jpa规范下提供的Resporsity实现,JpaResporsity拥有常用的CURD方法
及分页、字段排序等,可以统一不同ORM框架对数据库操作的代码。

持久层框架选择
1. 从用户数量看,主流的选择是JPA和MyBatis,JPA使用Hibernate作为默认实现,因此就是
Hibernate和MyBatis的选择

2. 关注度:根据谷歌数据,JPA全球用户数量最多,但国内MyBatis用户数更多
3. Hibernate特点

  • 全自动的技术框架,无需维护SQL
  • 偏向于对象操作,从对象的角度更容易开发维护
  • 因SQL生成是自动的,所以在切换不同数据库时更容易,数据库移植性更好
  • 缓存机制优于MyBatis

4. MyBatis特点

  • 需要维护SQL,算是半自动化技术框架,但因此也可以更自由的进行SQL定制
  • 在学习SQL较为精通时,更容易掌握
  • 切换数据库有较大的维护工作量,因不同的数据库SQL写法存在区别

5. 如何选择

  • SQL基础不好,或者习惯了其他的等无需SQL维护的ORM框架如EF时,选择JPA
  • SQL熟练掌握则可选择MyBatis,毕竟国内使用者众多

6. MyBatis流程示例

  • pom.xml添加依赖
  • 添加创建数据库架构的sql文件,并在其中写createtable这样的语句
  • yml文件中配置数据连接,配置spring.datasource.schema指向上一步的架构sql文件
  • 创建实体类,如User
  • 添加mapper接口,接口方法实现有两种方式

可在接口方法上通过如@Select|@Update|@Delete注解写sql语句

@Select("select*fromuserwhereid=#{id}")
UserfindById(@Param("id")intid);

或者使用mapper配置文件

<mapper namespace="net.lzzy.learn.practice.mapper.UserMapper">
<resultMapid="user"type="User">
<idcolumn="id"property="id"javaType="int"></id>
<resultcolumn="name"property="name"javaType="String">
</result>
<resultcolumn="age"property="age"javaType="int"></result>
<resultcolumn="pwd"property="pwd"javaType="String">
</result>
</resultMap>
<selectid="findById"parameterType="int"resultMap="user"
resultType="User">
select*fromuser
<trimsuffixOverrides="and"prefixOverrides="and">
<where>
<iftest="userid!=null">
andid=#{id}
</if>
</where>
</trim>
</select>
</mapper>

在业务层或者Controller中直接使用mapper的接口对象进行crud操作

DOM数据持久层

按照SpringData规范,查询方法以find|read|get开头,涉及条件查询时,条件的属性
用条件关键字连接,要注意的是:条件属性以首字母大写。
在接口中只需要声明符合规范的方法,即拥有对应的功能,如下表所示为方法中支持的关键字

1、添加repositories文件夹
2. 添加UserRepository接口

  • 继承JpaRepository接口,两个类型参数分别时User类和主键类型UUID
  • 继承的上述接口包含了CRUD方法,一般的数据访问即可直接使用
  • 声明一个findUserByUserNameAndPassword方法,返回User对象
  • 声明一个countByUserName方法,返回该用户名在数据库中的记录数
packagecn.edu.lzzy.repositories;
importcn.edu.lzzy.entities.User;
importorg.springframework.data.jpa.repository.JpaRepository;
importorg.springframework.data.jpa.repository.Query;
importorg.springframework.data.repository.query.Param;
importjava.util.List;
importjava.util.UUID;
/**
*
用户数据持久层(Dao层接口)
*
/
publicinterfaceUserRepositoryextendsJpaRepository<User,UUID>{
UserfindUserByUserNameAndPassword(StringuserName,Stringpassword);//根
据用户名/密码查找用户
IntegercountByUserName(StringuserName);//用户在db中的记录数
IntegercountAllBy();
List<User>findAllByOrderByUpdateTimeDesc();//获取用户并根据更新时间降序输出
List<User>findUserByApplyTeacherOrderByUpdateTimeDesc(boolean
applying);//查找教师数据
/**
*
查询字段:用户账号、昵称、Email、联系电话
*
/
@Query("selectufromUseruwhereu.userNamelikeCONCAT('%',:kw,'%')
oru.nickName"+
"
likeCONCAT('%',:kw,'%')oru.emaillikeCONCAT('%',:kw,'%')or
u.phonelikeCONCAT('%',:kw,'%')")
List<User>findByQuery(@Param("kw")Stringkw);//根据关键字(keyword)查找用
户
List<UserProjection>findUserByUserName(Stringuser);
}

3. 添加UserProjection接口,使用投影选取特定的User字段

  • 添加一个getSalt方法,返回用户注册时的随机salt
  • 在UserRepository中添加一个findUsersByUserName方法,返回用户数据的salt投影,用于用户登录时salt验证
packagecn.edu.lzzy.repositories;
/**
*
获取用户salt
*
用于用户登录时salt验证
*
/
publicinterfaceUserProjection{
StringgetSalt();
}

五、Web开发心得体会

  在过去的几个月里,我深入地参与了Web开发的学习与实践。这个过程不仅让我掌握了丰富的技术知识,更让我对团队协作、项目管理等方面有了深刻的理解。
首先,我认识到Web开发是一个综合性的工作,它要求我们具备多种技能。从前端设计到后端编程,从数据库管理到系统架构,每一个环节都需要我们精心打磨。尤其在前端开发中,我深入学习了HTML、CSS和JavaScript,如何实现页面的美观与交互性,同时保持代码的简洁与高效,是一项需要持续学习和探索的任务。
  其次,团队合作是Web开发的另一个重要方面。在项目中,我们经常需要与设计师、后端工程师等多方进行密切的合作。这让我意识到,良好的沟通与协作能力是完成任务的关键。我们不仅需要理解各自的工作内容和流程,更需要懂得如何高效地协同工作,以达到项目的整体目标。
此外,项目管理也是我在这个过程中学到的宝贵经验。一个项目的成功,不仅取决于技术实现的难度,更在于项目的管理和执行。从需求分析、计划制定到进度控制,每一个环节都需要精细的管理。我开始了解到,仅仅埋头写代码是不够的,如何更好地进行项目规划和流程控制,同样非常重要。
  回想这次的学习经历,我深感收获颇丰。Web开发不仅让我掌握了实用的技术知识,更让我明白了作为一个工程师的责任与担当。在未来的工作中,我将继续努力,不断提升自己的技术能力和项目管理水平,为团队和公司创造更多的价值。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值