美文网首页
Spring Web MVC -- 视图层

Spring Web MVC -- 视图层

作者: saoraozhe3hao | 来源:发表于2018-08-25 23:05 被阅读0次

官网:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html

术语
JSRs: Java Specification Requests,Java 规范提案
JSR 303:JSR第303号提案,即Bean Validation规范
Hibernate Validator:JSR 303的参考实现,和 Hibernate ORM 没有关系
Spring Web Flux:与Spring Web MVC对等,采用函数式(异步非阻塞)编程,能提高吞吐量,运行在Reactive容器,最终实现与Spring MVC一样的web服务
DispatcherServlet:Spring MVC提供的Servlet,不处理具体业务,负责调度
Controller:被DispatcherServlet调度,处理具体业务

IDEA 配置 Spring MVC

1、配置Maven依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>    <!-- 包含ContextLoaderListener和DispatcherServlet -->
  <version>5.0.8.RELEASE</version>
</dependency>
<dependency>   
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>    <!-- servlet支持 -->
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>   <!-- 用于对象转json -->
    <version>2.7.4</version>
</dependency>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>     <!-- 用于校验 -->
    <version>6.0.12.Final</version>
</dependency>

2、给IDE配置 Tomcat服务器:Settings -> Application Servers -> 添加 Tomcat Server(即servlet-api.jar 和 jsp-api.jar)
3、给项目配置tomcat:右上角 -> Edit Configurations -> 添加 Tomcat Server -> 添加Deployment
-- 点击绿色三角,就可以自动部署和运行了
-- debug模式运行,就可以打断点了
-- 可以查看tomcat日志了
-- 可以在Server -> Output窗口查看System.out的输出了

Spring MVC 应用组成

1、Servlet容器,项目应用配置 web.xml

<web-app>
  <context-param> <!-- 指定Spring 配置文件 -->
    <param-name>contextConfigLocation </param-name>
    <param-value>classpath:applicationContext.xml</param-value> <!-- classpath是指resources目录 -->
  </context-param>
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- Spring MVC封装的Servlet -->
  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>   <!-- 指定Spring MVC配置文件,默认为./dispatcher-servlet.xml -->
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
      </init-param>
      <load-on-startup>2</load-on-startup>
  </servlet>
<!-- Servlet要处理的url路径 -->
  <servlet-mapping>
      <servlet-name>dispatcher</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

2、Spring配置文件 applicationContext.xml
3、DispatcherServlet 默认读取的配置文件 /WEB-INFO/dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <mvc:annotation-driven />    <!-- 使用注解驱动,来扫描@Controller -->
    <context:component-scan base-package="com.hogen.controller"/>    <!-- 要扫描的包 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>   <!-- 视图方案,指定寻找jsp的路径和后缀 -->
    <mvc:interceptors>     <!-- 拦截器配置 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.hogen.interceptor.RoleInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

4、控制器 Controller

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller ("myController")    // 注解本类为Controller
@RequestMapping ("/my")       // 注解 /my 下的请求都由本类处理
public class MyController {
    @Autowired
    private CityService cityService;   // 注入Mybatis的Service

    @RequestMapping ("/index")    // 注解本方法处理 /my/index 请求
    public ModelAndView index (HttpSession session, HttpRequest request, HttpCookie cookie) { // 可传入这些Servlet原生参数
        ModelAndView mv = new ModelAndView();
        mv.setViewName("dir/index");   // 指定 jsp 路径
        mv.addObject ("role", role) ;   // 添加数据到session,给jsp用
        return mv ;     // 返回一个jsp页面
    }
    @RequestMapping(value="/index2", method=RequestMethod.POST)  // 指定请求方法
    public ModelAndView index (@RequestParam("id") Long id, @SessionAttribute("userName") String userName) { 
        // 获取url参数 和 session中的数据,@RequestParam("id") Long id 可以简写为@RequestParam Long id
    }
    @RequestMapping(value="/index/{id}")
    public ModelAndView index (@PathVariable("id") Long id, @RequestParam("file") MultipartFile file, , @RequestParam("files") MultipartFile[] files) {
        // 从url路径中获取参数;上传单个文件;上传多个文件
    }
    @RequestMapping(value="/index3")
    public ModelAndView index (@RequestBody RoleParams roleParams) {   // 从请求提中获取数据
        // 得先定义一个RoleParams类,拥有的成员就是这个请求有的参数       
    }
    @RequestMapping ("deleteRoles"}
    public ModelAndView deleteRoles(@RequestBody List<Long>idList) {  // 接收一个列表
    }
    @RequestMapping ("index5"}
    public ModelAndView index5(String param1, String param2) {  // 序列化后的参数,即表单数据
        ModelAndView mv = new ModelAndView();
        mv.addObject ("role","ddddd");
        mv.setView(new MappingJackson2JsonView());   // 返回json
        return mv;
    }
    @RequestMapping ("index6"}
    public ModelAndView index6(ModelAndView mv) {
        mv.addObject ("id", 1111);     // 传递参数
        mv.setViewName ("redirect: ./index5");   // 服务器端重定向
    }
    @RequestMapping ("index7"}
    public ModelAndView index7(RedirectAttributes ra) {
        ra.addFlashAttribute("role", role) ;     // 用对象来传递参数,临时保存到session, 跳转后清除
        mv.setViewName ("redirect: ./index5");   // 服务器端重定向
    }
    @RequestMapping ("index8"}
    public ModelAndView index8(@RequestHeader("User-Agent") String userAgent, 
                                                   @CookieValue("JSESSIONID") String sessionId) {
        // 从Cookie 和 请求头中获取信息
    }
}

5、拦截器 Interceptor

public class RoleInterceptor extends HandlerInterceptorAdapter {
   // 生命周期 preHandle -> servlet处理 -> postHandle -> 处理jsp -> afterCompletion
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;    // 返回 false 则直接结束
    }
    // 多个拦截器时,preHandle按配置顺序执行,postHandle逆序执行,afterCompletion逆序执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response , Object handler ,ModelAndView modelAndView) throws Exception {

    }
     // 多个拦截器时,一个preHandle返回false,则除了preHandle已经返回true的拦截器会执行它的afterCompletion,其他都不执行
    public void afterCompletion(HttpServletRequest request,HttpServletResponse response ,Object handler , Exception ex ) throws Exception {

    }
}

校验

1、用来包装请求体的 POJO

public class City {
    @NotNull(groups={First.class})    // 不能为空;分组,First为一个interface
    @Min(1)      // 最小值
    @Max(100)  // 最大值
    private Long id;

    @DecimalMin(value="1.1")  // 最小值
    @DecimalMax("500000.00")  // 最大值
    private Double price ;

   @Size(min=0,max=256)   // 长度范围
   @Pattern(regexp="^[a-z]+$", message="格式不对")  // 正则匹配,给出错误信息
    private String cityName;

    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")  // 指导json数据转换
    @DateTimeFormat(pattern="yyyy-MM-dd")   // 日期格式
    @Future    // 得是将来的日期
    private Date date;
}

2、业务校验类
POJO中的注解实现了格式校验,这里实现业务校验

public class CityValidator implements Validator {
    @Override
    public boolean supports(Class<?> aClass) {
        return City.class.equals(aClass);
    }

    @Override
    public void validate(Object target, Errors errors) {
        City city = (City) target;
        errors.rejectValue("cityName", null ,"业务校验错误");  // 这里设置的错误字段得是POJO中有的字段
    }
}

3、Controller

@Controller
@RequestMapping ("/my")
public class MyController {
    @InitBinder                                                        // 引入业务校验类
    public void initBinder(DataBinder binder ) { 
        binder.setValidator(new CityValidator());
    }

    @RequestMapping(value="/index")
    public ModelAndView index1(@Valid City city, Errors errors){  // @Valid 标明需要校验,不支持分组;@Validated({First.class})支持分组
        ModelAndView mv = new ModelAndView();
        if (errors.hasErrors()) {   // 有校验错误
            List<FieldError> errorList = errors.getFieldErrors() ;
            for (FieldError error : errorList){
                mv.addObject (error.getField(), error.getDefaultMessage());  // 出错字段 和 错误信息
            }
        }
        else{
            mv.addObject ("success","000");
        }
        mv.setView(new MappingJackson2JsonView());
        return mv;
    }
}

最佳实践
1、会话确认拦截器
preHandle()中判断session中的登录信息,未登录就重定向到登录页面,并返回false

相关文章

网友评论

      本文标题:Spring Web MVC -- 视图层

      本文链接:https://www.haomeiwen.com/subject/yzrniftx.html