梳理开发流程:
WEB项目主要解决得是浏览器与服务器的交互问题。
浏览器与服务器是由一次又一次的请求来交互得,任何功能都可以拆解成若干次请求
重要的是每一次请求的执行过程。。。按照步骤去开发每次请求。
具体的请求执行过程:
1、请求会提交给服务器端的视图层,视图层主要有controller层和模板层构成。。。
2、而controller在处理请求的过程当中需要访问业务Serveice层,让Service层的业务组件来处理具体的业务。
3、业务组件在处理业务的过程中,会访问到数据库。就需要调用DAO数据业务组件。
显然:Controller依赖于Service,而Service依赖于DAO,而DAO又依赖于数据库。
正常的开发顺序是按照依赖关系,先开发底层:
(一)、先设计好数据库、
建表的DDL语句可以了解这个表包含那些字段以及含义
User_id 字段可以关联User表。。。
(二)、再开发相关业务的DAO接口
(三)、继续开发相关业务的Service
(四)、开发Controller层
DAO层的开发
1、用于封装数据表中数据的实体类
2、数据访问组件Mapper接口
出现问题的解决办法:
1.对于mapper接口中,传入的参数有多个时必须使用@param
进行标识,查看了一下自己的代码,每个参数我都用@Param
注解标识了,可还是报这个错,
2.那有可能是MySQL中你传入的参数跟你使用的值不一致,仔细检查了一遍sql语句,发现没啥毛病,见下图:传入的参数分别是#{postId},#{page},#{number},引用的时候也分别是这三个字段
第一种情况:mapper层方法缺少@Param注解
第二种情况:传2个参数都是对象的时候,而不是简单地string、int等等
出错原因:对象具体的xx属性没加对象名
出错代码:
正确代码:
Service服务层的开发
业务层(Service)中为什么一定要用接口,不用行不行?回答:不是必须要使用接口,但强烈建议使用接口。
情景1: 在开源框架中有很多这种情况,就是某个功能支持用户自定义扩展.说白了,它提供了一个接口,我们只需要实现这个接口,把我们自己的实现逻辑补上,就可以让框架按照我们的逻辑来执行.问题来了,框架的作者并不知道我们的实现类是什么,如果不定义一个接口,那么要如何在框架中调用我们的实现类呢?
情景2: 我和同事分别做项目的2个不同功能模块,但是同事的功能中却需要调用我这头实现的部分逻辑.为了让他有一个"占位符"可用,我是不是应该快速的写个接口扔给他呢?
情景3: 一个适配器功能,或是说一个简单的工厂类,如果没有定义接口,那么面对众多实现类,要如何统一操作呢?
情景4: 想让项目的代码符合某种"规范",但是又不可能看着别人写代码吧,那好办,先出一套接口,然后你们就看着办~
情景5: java中没有多继承,但是可以多实现接口,那么就有一件很有趣的事情了,一个实现类可以实现多个接口,然后此时接口可以有选择的暴露实现类的部分方法,做到"窄化"实现类功能的目的。
当然例子还有很多,这些情况其实可以说是接口好处的体现,所以java有面向接口编程的建议,但是说回Service层一定要有接口吗?那到未必,因为说到底,多一个接口仅仅是扩展性和某些情况下有优势,但是是否会用到接口的便利性,不确定的情况下我们未必一定要为"可能"买单,只是多写那几行代码,付出一点就可能避免"未来"的大"麻烦",何乐而不为!?
下面简单列出Spring Boot中业务层(Service)的创建步骤及应用
1) 接口及实现类命名方式,接口XXXService,实现类:XXXServiceImpl。
2) 实现类XXXServiceImpl需添加注解@Service,并指明名称,如@Service("companyService");
3) 在实现类中,通过注解@Autowired,注入数据仓库层Repository接口;
当实现的接口涉及数据库数据的删除或修改时,方法上一定要添加注解@Transactional,否则会执行不成功。
Controller视图层的开发
视图层的一些用得到但不常见注解:
@RequsetMapping
@RequestMapping
是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径;用于方法上,表示在类的父路径下追加方法上注解中的地址将会访问到该方法。例如,
// 用于类上,可以没有
@RequestMapping(value = "/controllerDemo")
public class ControllerDemo {
// 用于方法上,必须有
@RequestMapping(value = "/methodDemo")
public String methodDemo() {
return "helloWorld";
}
}
其对应的相对请求路径就是controllerDemo/methodDemo
,访问该路径就会跳转到helloWorld
页面。
@Responsebody
@ResponseBody这个注解通常使用在控制层(controller)的方法上。当方法上面没有写ResponseBody,底层会将方法的返回值封装为ModelAndView对象。
- 作用:将该方法的返回的结果直接写入 HTTP 响应正文中,一般在异步获取数据时使用,进而将数据返回给客户端;
- 在使用
@RequestMapping
后,返回值通常解析为跳转路径,加上@Responsebody
后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。例如,异步获取json
数据,加上@Responsebody
注解后,就会直接返回json
数据。例如,
-
@RequestMapping(value = "person/login") @ResponseBody // 将请求中的数据写入 Person 对象中 public Person login(@RequestBody Person person) { // 不会被解析为跳转路径,而是直接写入 HTTP 响应正文中 return person; }
接收参数相关的三个注解@PathVariable、@RequestParam、@RequestBody
三个注解都是在我们进行请求时对服务端参数进行封装的,那么具体三个注解的使用,什么情况下,什么条件下使用呢?
@RequestParam
@RequestParam注解用于从请求的URL或表单中获取参数的值。它通常用于处理GET请求中的请求参数,并将参数的值绑定到方法的参数上。
简单来说,当我们需要获取URL中的参数或表单中的参数时,就可以使用@RequestParam注解。 使用@RequestParam:要指明前端传过来的参数名并与其对应。
例如:
http://localhost:8080/test/?name=”xxx”
@GetMapping("/test")
String test(@RequestParam("name") String name);
@RequestBody
当我们需要从请求体中获取数据并封装成对象时,@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);请求的Content-Type必须为application/json或application/xml,以确保请求体的数据能够正确地被解析和绑定到对应的Java对象上。
@PostMapping("/test2")
String test2(@RequestBody Product product);
@RequestParam可以使用多个,@RequestBody只能使用一个
@PathVarible
接收请求路径中占位符的值
一般也是用于Get请求,URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中.
@GetMapping("id/{id}")
public ObjectfindById(@PathVariable("id") long id) {
return studentService.findById(id);
}
Controller层的Model和ModelAndView的解析:
- Model是每次请求中都存在的默认参数,可以自动创建,利用其addAttribute()方法即可将服务器的值传递到前端的页面中去。
- ModelAndView,使用时需要自己实例化(new)
- Model只是用来传输数据的,并不会进行业务的寻址。ModelAndView 却是可以进行业务寻址的
ModelAndView的使用
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class AnnotationController {
@RequestMapping("/ahello")
public ModelAndView hello() {
ModelAndView mv = new ModelAndView();
List<user> list = UserService.select();
mv.addObject("msg",list);
mv.setViewName("hello");
return mv;
}
}
Model的使用
package demo01.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class AnnotationController {
@RequestMapping("/ahello")
public String hello(Model m) {
List<DiscussPost> list = discussPostService.findDistcussPosts(0,0,10);
m.addAttribute("amsg",list);
return "hello";
}
}