前言
Spring是MVC模式的,大大降低了耦合度,提高了开发效率,便于代码管理,
Model,View,Controller 三部分协调工作,MVC思想和观察者模式很相似,但又不同,View是观察者,Model层一旦发生变化,View层即被通知更新。
MVC要实现的目标是将软件用户界面和业务逻辑分离以使代码可扩展性、可复用性、可维护性、灵活性加强。
这篇博客写的不错
View层是界面,Model层是业务逻辑,Controller层用来调度View层和Model层,将用户界面和业务逻辑合理的组织在一起,起粘合剂的效果。所以Controller中的内容能少则少,这样才能提供最大的灵活性。
而SpringMVC就是MVC模式的一个实现,用户看到的界面叫View层,Service层是对数据库操作的一个封装,比如按id查找就会封装成findById函数,然后再去调用Dao层也就是数据库层的相关操作去操作数据库,Service可以完全不知道Dao层的操作,这就实现了分离,@Controller层则是调节Service层和View之间的关系以及联系的,一个View可以有多个不同的Controller,是策略者模式,具体我也不是很清楚策略者模式,简单来说应该就是View可以有不同的策略来从数据库中拿到数据去渲染吧。
1、常用注解
- @RequestMapping用于将url传递给函数,来执行指定Url的指定函数
value={"/one","/tow"} 可以指定多个url同时访问一个函数
@RequestMapping(value = {"/index","/jb"}
method={POST,GET}指定访问方式
2.@RequestParam 用于请求参数,如表单提交上来的参数,还有拼接在URL中的/nb?name=nb&age=16 都可以绑定到函数的参数中
3.@PathVariable 获得URL动态参数 ,默认不指定名字则是以参数名为绑定对象,
@RequestMapping("/body{userid}/")
@ResponseBody
public User Body(@PathVariable("userid") Integer id,@ModelAttribute User user)
4.@RequestHeader获取请求头信息
5.@CookieValue获取Cookie信息,required=false 代表不是必要的 ,defalut="null"可以指定默认值如果没有的话
6.@SessionAttribute 获取session值
7.@SessionAttributes 将Model中的属性加入到sessioon中,一般需要指定,可以根据类型或者在Model中的键来指定多个
value={“user”,},types={User.class}
@SessionAttributes(value = {"nb"}) //value={"user",},types={User.class}
public class C3 {
@ModelAttribute(value = "nb")
public String before1(ServletRequest request, HttpSession session)
{
session.setAttribute("s1","S1");
//request.setAttribute("username","name-pb");
return "NB";
}
}
这样在session中就是储存model中的nb值
8.@ModelAttribute
加了这个注解的,在一个Controller中会先执行,每次有请求来到这个Controller中都会先执行,以便将数据初始化到Model中,其他函数可以在Model中取
主要分三种情况
1、标记着返回具体类的方法中,返回值就是Model中的值
@ModelAttribute(value = "nb") "nb"就是Model中的键
public String before1(ServletRequest request, HttpSession session)
{
session.setAttribute("s1","S1");
//request.setAttribute("username","name-pb");
return "NB";
}
2、注释在方法参数中
@RequestMapping(value = "/url")
public String process(@ModelAttribute(value = "name") String name){
return "success";
}
上述代码中,处理url请求时,会创建String对象,值为url请求中的参数“name”的值,并将该对象添加到Model中,
3、注释在无返回值的函数中,则需要自己创建Model来往Model中添加数据
@ModelAttribute
public void user(
@RequestParam("username") String username,
@RequestParam("pwd") String pwd,Model model) {
model.addAttribute("username", username);
model.addAttribute("pwd", pwd);
}
注意:如果原来的Model中已经有了同名的,则会从Model中拿,如果没有,比如下面注释掉的代码,那么如果从Form表单或者URL参数中获取属性参数值,放到对应类型的参数中,注意:此时表单中的组件名和参数属性名称一致,如User对象有两个属性,分别为username,password,则表单中input的名称必须为username,password,才能实现属性值注入。
// @ModelAttribute("nb")
// public String Add()
// {
// return "NB";
// }
@RequestMapping(value = {"/index","/jb"})
public String Index(@ModelAttribute("nb") String nb,HttpServletRequest request, Model model,Map<String,String> map)
{
System.out.println(nb);
System.out.println("========================="+request.getAttribute("filter01"));
System.out.println(request.getAttribute("interceptor"));
model.addAttribute("index","首页");
request.setAttribute("index","首页");
// System.out.println(map.get("nb"));
return "index";
}
9.@ResponseBody返回JSON类型,SpringBoot会自动解析
10.@ControllerAdvice 全局注解 ,主要用于全局异常处理
@ControllerAdvice
public class AllDataController {
@ModelAttribute("name")
public String Name()
{
return "panbin";
}
这时,每个Controller都可以拿到Model中的值
//异常处理 可以捕获所有Controller中的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public String Bad()
{
return "Bad";
}
}
11.@Resource和@Autowired
都是自动注入注解
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
public class TestServiceImpl {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
12.@Repository
dao层注解
2、SpringMVC异常处理
- @ ExceptionHandler
进行异常处理的方法必须与出错的方法在同一个Controller里面
不能全局控制异常。每个类都要写一遍。
@Controller
2 public class GlobalController {
3
4
8 @ExceptionHandler({MyException.class}) //这里面放的是捕获哪个异常的类 下面就是异常处理函数
9 public String exception(MyException e) {
10 System.out.println(e.getMessage());
11 e.printStackTrace();
12 return "exception";
13 }
14
15 @RequestMapping("test")
16 public void test() {
17 throw new MyException("出错了!");
18 }
19 }
2.实现 HandlerExceptionResolver 接口
可以捕获全局异常,返回视图
@Component
2 public class ExceptionTest implements HandlerExceptionResolver{
3
4 /**
5 * TODO 简单描述该方法的实现功能(可选).
6 * @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
7 */
8 public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
9 Exception ex) {
10 System.out.println("This is exception handler method!");
11 return null;
12 }
13 }
3.使用 @ControllerAdvice+ @ ExceptionHandler 注解
@ControllerAdvice(backPackges="com.xx.xx") //backPackges用于定义扫描哪些包
public class AllDataController {
@ModelAttribute("name")
public String Name()
{
return "panbin";
}
//异常处理
@ExceptionHandler(Exception.class)
@ResponseBody
public String Bad()
{
return "Bad";
}
}
这里截了大佬的一段代码*大佬博客
``
/**
6 * 400 - Bad Request
7 */
8 @ResponseStatus(HttpStatus.BAD_REQUEST)
9 @ExceptionHandler(HttpMessageNotReadableException.class)
10 public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
11 logger.error("参数解析失败", e);
12 return ServiceResponseHandle.failed("could_not_read_json");
13 }
14
15 /**
16 * 405 - Method Not Allowed
17 */
18 @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
19 @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
20 public ServiceResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
21 logger.error("不支持当前请求方法", e);
22 return ServiceResponseHandle.failed("request_method_not_supported");
23 }
24
25 /**
26 * 415 - Unsupported Media Type
27 */
28 @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
29 @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
30 public ServiceResponse handleHttpMediaTypeNotSupportedException(Exception e) {
31 logger.error("不支持当前媒体类型", e);
32 return ServiceResponseHandle.failed("content_type_not_supported");
33 }
34
35 /**
36 * 500 - Internal Server Error
37 */
38 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
39 @ExceptionHandler(Exception.class)
40 public ServiceResponse handleException(Exception e) {
41 if (e instanceof BusinessException){
42 return ServiceResponseHandle.failed("BUSINESS_ERROR", e.getMessage());
43 }
44
45 logger.error("服务运行异常", e);
46 e.printStackTrace();
47 return ServiceResponseHandle.failed("server_error");
48 }
49 }
注意:如果需要自定义错误页,则需要在static目录下定义一个error目录,下面放错误页的html文件,并且按错误代码命名,如404.html,500.html等
3、JSR303数据校验
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
1、各种注解,@NULL @NotNULL 标注在JAVA Bean字段上
2、然后在需要验证的地方加@Validator 同时更上Errors 对象
@RequestMapping("/login")
public String testValid(@Valid User user, BindingResult result){
if (result.hasErrors()){
List<ObjectError> errorList = result.getAllErrors();
for(ObjectError error : errorList){
System.out.println(error.getDefaultMessage());
}
}
return "test";
}
4、文件上传
构造路径,然后把路径存在数据库里就行
@RequestMapping("/upload")
@ResponseBody
public String Upload(HttpServletRequest request,
@RequestParam("file")MultipartFile file)
throws IOException {
String path = "D:/1";
String filename = file.getOriginalFilename();
File file1 = new File(path+"/"+filename);
System.out.println("-----------------"+file1.getPath()+"--------------");
file.transferTo(file1);
return "SUCCESS";
}
5、拦截器-------》这篇不错
使用场景
1、日志记录 :记录请求信息的日志
2、权限检查,如登录检查
3、性能检测:检测方法的执行时间
6、启动系统任务 ----->来自这篇
SpringBoot对于系统启动时执行的任务,例如配置文件加载,数据库初始化等操作提供了两种解决方案:CommandLineRunner和ApplicationRunner,两者差别主要在于参数。
SpringBoot项目启动时会遍历所有的CommandLineRunner和ApplicationRunner的实现类并调用其中的run方法@Order注解可对于这些实现类调用顺序进行排序
args会被赋值为main的入参
@Component
@Order(2)
public class MyApplicationRunner1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> nonOptionArgs = args.getNonOptionArgs();
System.out.println(nonOptionArgs);
System.out.println("================");
}
}
@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
@Override //可变参数String...args
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(args));
System.out.println("------------------");
}
}
7、SpringBoot定时器
假设我们已经搭建好了一个基于Spring Boot项目,首先我们要在Application中设置启用定时任务功能@EnableScheduling。
其中 @EnableScheduling 注解的作用是发现注解@Scheduled的任务并后台执行。
@Component
public class MyScheduler {
@Scheduled(fixedRate = 2000) //每隔两秒启动
public void Test1()
{
System.out.println("任务启动");
}
}