SpringMVC的Bean装配及返回值
SpringMVC也是通过Servlet来工作,具体是Spring框架的DispatcherServlet.SpringBoot默认的配置,该Servlet的路径为/**
SpringMVC:Spring Framework项目中一个框架,提供web请求处理的功能
@Controller
当前类型注册实例到容器中,并指定为web请求的处理
@RequestMapping()
可以定义请求相关的配置,如路径,请求方法等等
存在同一个类型,多个实例对象时:默认查找bean的名称为变量名的bean
如果变量名和bean名称不一致,需要手动指定:
(1)@Autowired+@Qualifier ( "bean的名称”)
(2)@Resource (name=“bean的名称”)
SpringBoot注意事项:
(1、启动类,必须在某一个包下
(2)、默认扫描启动类所在的包下
@Autowired装配Bean
@Autowired
用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean
的类型进行装配。
@Resource
其作用与 Autowired 一样。其区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照
Bean 实例名称进行装配。
两者区别:
@Autowired:属于Spring框架
@Resource:JDK提供的注解,表示资源。JDK只提供了规范,没有提供实现 JDBC和Serlet都是jdk提供规范,第三方提供具体实现
通过路径访问
装配名称
创建一个User类
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class User {
private String username;
private String password;
}
进行装配
import frank.springbootstudy.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
@Configuration
public class AppConfig {
@Bean
public User user() {
User user = new User();
user.setUsername("hhh");
user.setPassword("123456");
return user;
}
@Bean
public User user1() {
User user = new User();
user.setUsername("jjj");
user.setPassword("456789");
return user;
}
}
装配时的名称问题
装配Bean
只使用 @Autowired
变量名和Bean的名称要一致否则会报错
使用@Autowired搭配@Qulifier指定Bean名称
变量名和Bean的名称不一致
@Autowired
@Qualifier(“user1”)
private User user1246;
import frank.springbootstudy.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
@Controller//当前类型注册实例到容器中,并指定为web请求的处理
@RequestMapping("/user")//可以定义请求相关的配置,如路径,请求方法等等
public class UserController {
//装配Bean
@Autowired
private Map<Integer,String> test1;
@Autowired
private User user;//变量名和Bean的名称要一致否则会报错
//变量名和Bean的名称不一致使用@Autowired搭配@Qulifier指定Bean名称
@Autowired
@Qualifier("user1")
private User user1246;
@RequestMapping(value = "/login",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Object logon(){
/* Map<String ,String> map = new HashMap<>();
map.put("man","jjj");
map.put("rea","hkhk");
return map;*/
return user;
}
}
@Resource装配Bean
@Resource是按照类型进行装配
按照之前代码,@Resourse是按照类型匹配,因为User有两个对象装配,会匹配失败。
所以在@Resourse中添加名称可以识别到
返回方式
1、返回资源
返回资源类型为String,返回值为资源的路径(静态资源和服务器资源都可以)
转发写法: “返回forward资源路径”
重定向写法: “返回redirect资源路径”
资源路径是否带/,和相对位置有关,带/,就是以当前项目路径为相对位置,不带/。是当前请求路径为相对位置
2、返回json数据
@ResponBody: 返回application/json的数据类型,返回值会序列化为json字符串
url为rest风格的请求
Controller中,请求数据的方式
(1)路径变量: url中定义(变量名)作为占位符,使用@PathVariable对应变量
(2)@RequestPath:
可以处理url中的请求数据
请求数据类型为x-www-from-urlencoded和form-data时,可以获取请求体中的数据
可以省略注释或者注解值,就以变量名匹配请求数据
可以匹配url中的参数
@RequestParam定义的类型,可以是基础数据类型,包装类型,自定义类型,都可以有多个参数。自定义类型是通过请求数据的key映射到类型的字段中
返回的两个特殊值
(3)直接使用Servlet的request和response对象
Http请求是基于Servlet的,Spring已经生成了request和response对象,可以直接在参数中使用,spring自动将对象注入到参数
(4)RequestBody
请求数据类型为application/json时,解析请求体中的json字符串,为java对象
注意事项:
(1)@ResponseBody使用时,注意返回值为null和字符串的情况
(2)请求的数据类型(定义了请求体的格式),Controller要使用对应的注解
(3)请求数据是放在哪。url中,还是请求体
web开发存在需求
1、统一处理异常
设置异常抛出
2、统一返回数据格式
设置返回的数据样式
package frank.springbootstudy.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class ResponseResult {
private boolean success;
protected Object data;//success=true需要的业务数据
private String code;//success=false需要的错误码及错误信息
private String message;
}
package frank.springbootstudy.config;
import frank.springbootstudy.model.ResponseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
//指定身份:拦截controller中web请求的类
@ControllerAdvice
public class AppControllerAdvice implements ResponseBodyAdvice<Object> {
//指定请求方法中抛出的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public Object handle(Exception e){
e.printStackTrace();
return null;
}
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
//执行Controller中的veb请求方法结束,返回数据到前端的时候,是否要重写响应体
return true;//如果为true进行下面的方法
}
@Override
public ResponseResult beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
ResponseResult r = new ResponseResult();
r.setSuccess(true);
r.setData(body);
return r;
}
}
3、统一会话管理(登陆的敏感资源权限控制)
package frank.springbootstudy.config.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import frank.springbootstudy.model.ResponseResult;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;
/*
定义拦截器
只有配置的拦截路径匹配请求路径时,才会执行拦截器中的方法
*/
public class Logininterceptor implements HandlerInterceptor {
private ObjectMapper objectMapper;
public Logininterceptor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
/*
controller中请求方法执行前就调用preHandle,返回值决定是否继续执行Controller中的方法
return true 继续执行 controller中方法
return false 不执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
//登陆允许访问
if(session != null && session.getAttribute("user") != null){
return true;
}
//没有登录,可以通过response对象,返回json数据,或者重定向到某个页面
response.setCharacterEncoding("UTF-8");
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
ResponseResult r = new ResponseResult();
r.setCode("ERR401");
r.setMessage("用户未登录不允许访问");
String json = objectMapper.writeValueAsString(r);//将java对象序列化json字符串
PrintWriter pw = response.getWriter();
pw.println(json);
pw.flush();
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
package frank.springbootstudy.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class ResponseResult {
private boolean success;
protected Object data;//success=true需要的业务数据
private String code;//success=false需要的错误码及错误信息
private String message;
}