spring MVC(一)常用注解使用、工作原理介绍

数字IC笔记-逻辑单元库和库文件 逻辑单元库的建立: 一个完整的单元库是由不同的功能电路所组成,在芯片应用中可分为三类: 标准单元:反相器、与门、寄存器、选择器、全加器。组合逻辑电路和时序逻辑电路。互补,反向,非反向,其他。锁存器、寄存器。 模块宏单元:ROM、RAM 输入输出单元 库文件: 在逻辑综合产生门级网表和物理设计做布局布线的过程中需要两个重要的库文件,就是物理库(lef)和时序库(lib) 1.物理库LEF文件 LEF是版图级的抽象文件,主要用于布局和布线。目前普遍使用的是由Candence开发的LEF文件格式,以le 阅读详情

Spring MVC 工作原理

  1. 发起请求到前端控制器(DispatcherServlet);
  2. 前端控制器请求HandlerMapping查找Handler,可以根据xml配置、注解进行查找;
  3. 处理器映射器HandlerMapping向前端控制器返回Handler;
  4. 前端控制器调用处理器适配器去执行Handler;
  5. 处理器适配器去执行Handler;
  6. Handler执行完成给适配器返回ModelAndView;
  7. 处理器适配器向前端控制器返回ModelAndView(是springmvc框架的一个底层对象,包括Model和View);
  8. 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名称解析真正的视图(jsp...);
  9. 视图解析器向前端控制器返回View;
  10. 前端控制器进行视图渲染,视图渲染就是将模型数据(在ModelAndView对象中)填充到request域中。
  11. 前端控制器向用户响应结果。 

 组件介绍

1、前端控制器DispatcherServlet(不需要攻城师开发),由框架提供
  作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
       用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2、处理器映射器HandlerMapping(不需要攻城师开发),由框架提供
  作用:根据请求的url查找Handler
       HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter
  作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
       通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
4、处理器Handler(需要攻城师开发)
  注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
     Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
     由于Handler涉及到具体的用户业务请求,所以一般情况需要攻城狮根据业务需求开发Handler。
5、视图解析器View resolver(不需要攻城师开发),由框架提供
  作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
  View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
  一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由攻城狮根据业务需求开发具体的页面。
6、视图View(需要攻城师开发jsp...)
  View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)

 

spring MVC常用注解介绍

注解描述

@Controller

负责注册一个bean 到spring 上下文中

@Scope

设置bean的作用域,基本作用域(singleton、prototype),Web 作用域(reqeust、session、globalsession),自定义作用域
@RequestMapping注解为控制器指定可以处理哪些 URL 请求

@Resource 

@Autowired

用于自动装配(注入)Bean到类中

@RequestParam

在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法

@PathVariable

将URL上的部分路径按占位符绑定到入参

@ModelAttribute

可以修饰方法、参数、返回值。会在@RequestMapping方法之前调用被修饰的方法;为属性(参数)绑定模型对象。

@SessionAttributes

@SessionAttribute

 
@RequestAttribute 

@ResponseBody

该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区,通常用来返回JSON数据或者是XML数据。

需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

@RequestBody该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上
@ExceptionHandler注解到方法上,出现异常时会执行该方法
@ControllerAdvice使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常

 

注解的使用

一、@Controller

使用位置:类

在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。

@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:

  (1)在SpringMVC 的配置文件中定义MyController 的bean 对象。

  (2)在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器
 

<!--方式一-->
<bean class="com.host.app.web.controller.MyController"/>
<!--方式二-->
< context:component-scan base-package = "com.host.app.web" />//路径写到controller的上一层(扫描包详解见下面浅析)

 

二、@RequestMapping

使用位置:类、方法

RequestMapping是一个用来处理请求地址映射的注解

@Controller
@RequestMapping ( "/test" )//在类上修饰,提供理论初步的请求映射信息,相对于WEB的根目录。请求的父路径"/test"
//@RequestMapping ( path="/test" )//与上面效果相同,直接用双引号写url默认为path
//@RequestMapping ( value="/test" )//在servlet环境下value是path的别名,与上面效果相同
public class MyController {

    /**
    *在方法上修饰,提供进一步的细分映射信息,相对于类定义处的url
    *若类处未定义映射请求,则方法处标记的url相对于WEB的根目录
    */
    @RequestMapping ( "/showView" )//调用这个方法的请求路径为"/test/showView"
    public ModelAndView showView() {

       return new ModelAndView();
    }

    @RequestMapping(path = "/showAll", method = RequestMethod.GET)
    public void showAllStudent(){
        System.out.println("StudentController.showAllStudent()");

    }
}

用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping注解有八个属性。

属性描述
path

请求的URL,直接用双引号写url默认为path(该属性仅在servlet环境中使用)

在类型级使用时,所有方法级映射都继承这个主映射,从而为特定的处理程序方法缩小其范围。

value

指定请求的实际地址,指定的地址可以是URI Template 模式(该属性可以在servle和portlet环境中使用)

在类型级使用时,所有方法级映射都继承这个主映射,从而为特定的处理程序方法缩小其范围。

在Servlet环境中,这是path()的别名。例如,@RequestMapping("/foo")等价于@RequestMapping(path="/foo")。

method指定请求的method类型, GET、POST、PUT、DELETE等,不写默认可以处理四种中的任意类型
name为这个映射分配一个名称
consumes指定处理请求的提交内容类型(Content-Type),例如application/json, text/html
produces指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
params指定request中必须包含某些参数值时,才让该方法处理
headers指定request中必须包含某些指定的header值,才能让该方法处理请求

注意:实际操作中容易遇到的问题

1)找不到对应的请求方法

原因:由提示我们可以很清楚的看到是没有POST的请求方法,因为在方法上明文设定了RequestMethod为GET或者POST,而发过来的请求并非是我们所设定的。找到了对应的请求的路径但是没有匹配到对应的RequestMethod类型。

解决方案:

  • 把方法上明文设定的“method = RequestMethod.GET”这个去掉,就可以同时处理GET和POST请求
  • 再添加一个相同请求路径的方法,并且明文设定对应的RequestMethod类型

2)一次请求登录失败后返回登录页再次登录出现路径重复而拼接出错误的路径

原因:这是由于自动以相对路径而发起的请求,开发中经常会存在一个请求方法中发起另一个请求从而实现请求间的跳转,或请求跳往页面后页面发起请求(如下面代码),这样容易引起在相对路径请求中,请求路径重复嵌套的问题。

解决方案:将相对路径设定为以根目录起始的绝对路径,在jsp请求的时候添加${pageContext.request.contextPath}/,每次都从根路径发起请求,从而避免请求混乱错误拼接的情况。

<%--添加${pageContext.request.contextPath}从根目录开始发起请求--%>
<form action="${pageContext.request.contextPath}/user/login" method="post">
    <table border="1">
        <tr>
            <td>userame:</td>
            <td><input name="username" type="text"></td>
        </tr>
        <tr>
            <td>password:</td>
            <td><input name="password" type="password"></td>
        </tr>
        <tr>
            <td colspan="2">
                <button type="submit">submit</button>
                <button type="reset">reset</button>
            </td>
        </tr>
    </table>
</form>
@Controller
@RequestMapping(path = "/user")
public class StudentController {

    @Resource(name = "studentServiceImpl")
    private StudentService studentService;

    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public String login(HttpServletRequest request){
        String username=request.getParameter("username");
        String password=request.getParameter("password");

        if(null==studentService.getStudent(username,password)){
            System.out.println("登录失败");
            return "/index";//此问题执行这里
        }else{
            System.out.println("登录成功");
            return "forward:/user/showAll";
        }
    }

    @RequestMapping(path = "/showAll",method = RequestMethod.POST)
    public ModelAndView showAllStudent(){
        ......
        return mav;
    }
}

 

 

三、@Resource  and @Autowired

1、@Autowired注解 / @Qualifier注解(不推荐使用,建议使用@Resource)

(1)@Autowired

  • 可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。
  • @Autowired是根据类型进行自动装配的。
  • 如果Spring上下文中存在不止一个UserDao类型的bean时,就会抛出BeanCreationException异常
  • 如果Spring上下文中不存在UserDao类型的bean,也会抛出BeanCreationException异常
  • @Autowired的标注位置不同,它们都会在Spring在初始化这个bean时,自动装配这个属性。要使@Autowired能够工作,还需要在配置文件中加入以下
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> 

(2)@Qualifier

我们可以使用@Qualifier配合@Autowired来解决上面的问题

1. 可能存在多个UserDao实例

@Autowired       
@Qualifier("userServiceImpl")         
public IUserService userService;  

or

@Autowired       
public void setUserDao(@Qualifier("userDao") UserDao userDao) {        
    this.userDao = userDao;        
}

这样,Spring会找到id为userServiceImpl和userDao的bean进行装配
===========================================================

2.可能不存在UserDao实例

@Autowired(required = false)        
public IUserService userService; 

2、@Resource

  • JSR-250标准注解,推荐使用它来代替Spring专有的@Autowired注解。@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName自动注入罢了。
  • @Resource有两个属性是比较重要的,分别是name和type,Spring将 @Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。要使@Autowired能够工作,还需要在配置文件中加入以下:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
@Resource(name = "studentServiceImpl")
    private StudentService studentService;

@Resource装配顺序:

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(见2);如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配;

 

 

四、@RequestParam

使用位置:方法参数

在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法

java code

@RequestMapping(path = "user/login", method = RequestMethod.POST)
    public void login(@RequestParam("username")String name,@RequestParam("password")String password){
        System.out.println("username="+name);
        System.out.println("password="+password);
    }

jsp code

//建议加上${pageContext.request.contextPath},每次从根目录发起请求,从而避免请求路径重复叠加
<form action="${pageContext.request.contextPath}/user/login" method="post">
    <table border="1">
        <tr>
            <td>userame:</td>
            <td><input name="username" type="text"></td>
        </tr>
        <tr>
            <td>password:</td>
            <td><input name="password" type="password"></td>
        </tr>
        <tr>
            <td colspan="2">
                <button type="submit">submit</button>
                <button type="reset">reset</button>
            </td>
        </tr>
    </table>
</form>

 

五、@PathVariable

使用位置:方法参数

将URL上的部分路径按占位符绑定到入参

java code

@RequestMapping(path = "user/delete/{userId}")
    public void delete(@PathVariable("userId") String userId){
        System.out.println("userid="+userId);
    }

jsp code

<table>
    <thead>展示所及学生</thead>
    <tbody>
      <tr>
        <td>学号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>性别</td>
        <td>操作</td>
      </tr>
      <c:forEach var="s" items="${studentList}">
      <tr>
        <td>${s.id}</td>
        <td>${s.name}</td>
        <td>${s.age}</td>
        <td>${s.sex}</td>
        <td>
          <button onclick="">修改</button>
          <button onclick="window.location.href='${pageContext.request.contextPath}/user/delete/${s.id}'">删除</button>
        </td>
      </tr>
      </c:forEach>
    </tbody>
  </table>

 

 

六、@ResponseBody

使用位置:类、方法

这个注释可以放在方法上,并指示返回类型应该直接写到HTTP响应体(而不是放在模型中,或者解释为视图名)

    /**
     * 这个是测试方法,只为测试@ResponseBody返回json的结果
     */    
    @RequestMapping(path = "/user/userlistTest")
    @ResponseBody
    public Object getUserListTest(){
        try {
            List<UsersBean> usersList = usersServiceImpl.getAllBeans();
            return usersList;
        } catch (Exception e) {
            return "ErrorPage";
        }
    }

注意:一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径, 加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中 

@ReqestMapping("/something")
@ResponseBody
public String helloWorld() {
    return "Hello World";
}

上面的示例将导致文本Hello World被写入HTTP响应流

比如异步获取json数据,加上@Responsebody后,会直接返回json数据。 

这是我的一个例子(由于没玩过ajax,所以简单的写一下)

jsp code

<h5 id="responseBodyValue"></h5>
<script>
    function testAjax(){
        alert("start Ajax action");
        $.ajax({
            url:'${pageContext.request.contextPath}/user/ajaxRequestFunction',//请求的地址
            type: 'POST',   // 请求方式
            success: function(data){//data是返回的参数(响应)
                alert("success:"+data);
                $("#responseBodyValue").html(data);//jequey 使用ID选择器,更改标签内容
            },
            error: function () {
                alert("fail");
//            console.log('Send Request Fail..'); // 请求失败时的回调函数
            }
        });
        alert("end Ajax action");
    }
</script>
<button onclick="testAjax()">Ajax send request to controller</button>

Java code

    @RequestMapping("/user/ajaxRequestFunction")
    @ResponseBody//只有写了ResponseBody才能将return的数据返回给JSP页面
    public String ajaxRequestFunction(){
        System.out.println("now in ajaxRequest Function ");
        return "result testButton action";
    }

注意:

  • 这个例子中只有写了@ResponseBody才能将return的数据返回给JSP页面,走success的方法,方法中的data是Java方法返回的数据result testButton action;
  • 不写@ResponseBody,jsp的AJAX会走error

 

七、@RequestBody(重点,坑多)

使用位置:方法参数

1、将JSON数据请求到方法参数

而 json 传递的数据都是 String 形式

设置请求类型为 application/json;charset=UTF-8,意思是以JSON方式传递数据。

(如果不设置,默认是form类型传递,这里的form并非单指form表单标签,而是一直传递类型)

contentType: "application/json;charset=UTF-8",

 

jsp code

<h5 id="responseBodyValue"></h5>
<script>
    function testAjax(){
        alert("start Ajax action");
        $.ajax({
            //请求的地址
            url:'${pageContext.request.contextPath}/user/ajaxRequestFunction',
            //请求方式
            type: 'POST', 
            //需要发送的数据
            data:'{"username":"123"}',
            //设定发送请求的数据类型为json
            contentType: "application/json;charset=UTF-8",
//            dataType:'text',//返回的数据类型
            // 请求成功时的回调函数
            success: function(data){//data是返回的参数(响应)
                alert("success:"+data);
                $("#responseBodyValue").html(data);//jequey 使用IDd选择器,更改标签内容
            },
            // 请求失败时的回调函数
            error: function () {
                alert("fail");
//            console.log('Send Request Fail..'); 
            }
        });
        alert("end Ajax action");
    }
</script>
<button onclick="testAjax()">Ajax send request to controller</button>

java code

接收的是json,而 json是以String 类型传递的

@RequestMapping("/user/ajaxRequestFunction")
    @ResponseBody
    public String ajaxRequestFunction(@RequestBody String data){
        System.out.println("now in ajaxRequest Function ");
        System.out.println("username="+data);
        return "ressult testButton action";
    }

 

 

2、将json数据请求自动绑定到pojo参数(坑在这里)

需要添加 jackson 依赖!!!!!

需要添加 jackson 依赖!!!!!

需要添加 jackson 依赖!!!!!

重要的事情说三遍

需要添加jackson-databind jar包

@RequestBody 为了可以解析json 并将数据自动映射到POJO里面,会去调用 jackson 依赖。

(这里感觉spring做的很不好,自己的注解需要引用外部的依赖,如果不引用请求会报415,由于当时不知道,报的我想砸电脑)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.8.1</version>
</dependency>

使用post协议提交时,请检查Content type类型

$.ajax({
    type: "POST",
    contentType: "application/json;charset=UTF-8",
    url: "/reg",
    data: JSON.stringify(data.field),
    dataType: 'json',
    success: function(result) {
        if(result.code == 0) {
            layer.msg('注册成功!');
        } else {
            layer.msg(result.msg);
        }
    }
});

请检查上方contentType类型,如果想用springmvc @RequestBody注解做提交json字符串自动绑定到pojo入参时,类型需要是"application/json;charset=UTF-8",否则会抛"not supported"异常。

@RequestMapping(value = "/reg", method = RequestMethod.POST)
    @ResponseBody
    public ResponseVo reg(@RequestBody user u) throws Exception {
       //其他crud逻辑
    }

注意:

1、遇到org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported或其他Content type不支持处理时请按下列方式排查

  • 使用post协议提交时,请检查Content type类型
  • 缺少jackson-databind jar包

2、遇到AJAX发送 json 请求时,报415错误,请按下列方式排查

  • 检查请求传输类型contentType: "application/json;charset=UTF-8"
  • 检查数据已经转换为json格式,data: JSON.stringify(data)
  • 检查 Jackson 依赖已经添加(这里巨坑!!!一定要注意!!!)

 

八、@ModelAttribute

使用位置:方法、参数、返回值 

1、@ModelAttribute注释在方法上

在调用目标处理方法前,会在@RequestMapping方法之前调用,优先调用所有在方法级上标注了@ModelAttribute 的方法,返回值会被添加到Model中,默认key为返回值类型的首字符小写

注意:

  • @ModelAttribute(value="")注释返回具体类的方法。value属性,来指定model属性的名称。model属性对象就是方法的返回值。它无须要特定的参数
  • 如果不设定value,默认名称为返回类型对象,首字母小写
/**
*设定model属性的名字,model属性对象就是方法的返回值
*相当于在request中封装了key="student1",value=student.Object
*/
@ModelAttribute("student1")
    public Student beforModelAttributMethod(){
        System.out.println("beforModelAttributMethod");
        Student student = new Student();
        student.setName("aaa");
        student.setPwd("bbb");
        return student;
    }
    @RequestMapping("/testModelAttributMethod")
    public void testModelAttributMethod(Map<String, Object> map){
        System.out.println("testModelAttributMethod");
        Student student=(Student)map.get("student1");//获取key(model属性名)对应的value
        System.out.println(student.getName()+"~~~~~"+student.getPwd());
    }

当我们发出/user/testModelAttributMethod这个请求时,SpringMvc 在执行该请求前会优先调用所有(没有发现执行顺序)在方法级上标注了@ModelAttribute 的方法,然后将该模型参数放入testModelAttributMethod()函数的Map参数中。因此对于一个controller映射多个URL的用法来说,要谨慎使用。

 

@ModelAttribute和@RequestMapping同时注释一个方法

@Controller 
 public class HelloWorldController { 
     @RequestMapping(value = "/helloWorld.do") 
     @ModelAttribute("attributeName") 
     public String helloWorld() { 
          return "hi"; 
       } 
   }

这时这个方法的返回值并不是表示一个视图名称,而是model属性的值,视图名称由RequestToViewNameTranslator根据请求"/helloWorld.do"转换为逻辑视图helloWorld 

 

2、@ModelAttribute注释方法的参数 

(1)从model中获取数据

  1. 相当于在入参时就将指定的key的value对象赋值给方法参数,对比上面的例子,代码中省去了从Map里面拿值的步骤
  2. 默认情况下@ModelAttribute注解不带注解参数,那么会使用参数User user中的user作为key,然后从Model取出该key的value然后传入给user
  3. 如果@ModelAttribute注解用注解参数指定了key,则使用指定的key从Model中取出该key对应的value然后传入给pet
  4. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.
  5. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, 
    若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所
    对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常. 
  6. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则
    会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数(如果查不到,就通过反射来创建一个新的对象赋值给参数)
@Controller 
 public class HelloWorldController { 
     @ModelAttribute("user") 
     public User addAccount() { 
         return new User("jz","123"); 
      } 
 
    //直接将key(user)的value赋值给方法参数,省去从Map中拿的代码
     @RequestMapping(value = "/helloWorld") 
     public String helloWorld(@ModelAttribute("user") User user) { 
            user.setUserName("jizhou"); 
            return "helloWorld"; 
         } 
   }

注意:在这个例子里,@ModelAttribute("user") User user注释方法参数,参数user的值来源于addAccount()方法中的model属性。此时如果方法体没有标注@SessionAttributes("user"),那么scope为request,如果标注了,那么scope为session

 

(2)从Form表单或URL参数中获取(实际上,不做此注释也能拿到user对象)

@Controller 
 public class HelloWorldController { 
     @RequestMapping(value = "/helloWorld") 
     public String helloWorld(@ModelAttribute User user) { 
         return "helloWorld"; 
      } 
 }

它的作用是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页面展示使用。我们此时可以在视图页面使用${user.username}来获取绑定的命令对象的属性

3、@ModelAttribute注释方法的返回值

放在方法的返回值之前,添加方法返回值到模型对象中,用于视图页面展示时使用

@Controller 
 public class HelloWorldController { 
     @RequestMapping(value = "/helloWorld") 
     public @@ModelAttribute("user2") User helloWorld(@ModelAttribute User user) { 
         return new User(); 
      } 
 }

可以看到返回值类型是对象类型,而且通过 @ModelAttribute("user2") 注解,此时会添加返回值到模型数据( 名字为user2 ) 中供视图展示使用

此例子中@ModelAttribute注解的返回值会覆盖 @RequestMapping注解方法中的@ModelAttribute注解的同名命令对象

 

九、@SessionAttributes 和 @SessionAttribuite

1、@SessionAttributes

使用位置:只能使用在类定义上

若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC将在模型中对应的属性暂存到 HttpSession 中。

通过@SessionAttributes注解设置的参数有3类用法:

  • 在视图中通过request.getAttribute或session.getAttribute获取
  • 在后面请求返回的视图中通过session.getAttribute或者从model中获取
  • 自动将参数设置到后面请求所对应处理器的Model类型参数或者有@ModelAttribute注释的参数里面。

将一个参数设置到SessionAttributes中需要满足两个条件:

  • 在@SessionAttributes注解中设置了参数的名字或者类型
  • 在处理器中将参数设置到了model中。

@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中

@SessionAttributes(types=User.class) //会将隐含模型中所有类型为 User.class 的属性添加到会话中。
@SessionAttributes(value={"user1", "user2"})
@SessionAttributes(types={User.class, Dept.class})
@SessionAttributes(value={"user1", "user2"},types={Dept.class})

在下面这个例子中,SpringMVC会把数据模型中的user1对象放入session中,所以我们在doHello4()中可以在session中取到user1对象。 

@Controller
@RequestMapping("hello")
@SessionAttributes(value = {"user1"})
public class HelloAction {
 
 @RequestMapping(value = "hello4", method = {RequestMethod.GET, RequestMethod.POST})
    public String doHello4(Map<String, Object> map, HttpSession session) {
 
        System.out.println(map.get("user1"));
        System.out.println("session:" + session.getAttribute("user1"));
 
        return "success";
    }
@ModelAttribute("user1")
    public User getUser() {
        User user = new User();
        user.setId(1L);
        user.setName("jjjj");
        user.setPassword("iiiii");
        return user;
 
    }

注意一下这种情况:

这种情况表明了ModelAndView里的符合@SessionAttributes(value = {"user1", "msg"})这里面定义的value值,那么这个属性也会被放入到Session对象里。并且同时证明如果在一个方法里带有Map参数,SpringMVC不仅会把标有@ModelAttribute注解的属性放入Map中,也会把@SessionAttributes(value = {"user1", "msg"})中的属性放入Map中。

注意如果通过session.setAttribute("xxx", "kkkk");这种方法放入到session中的属性的不会被放入到map中的。

但是当我们在@SessionAttributes(value = {"user1", "msg", "xxx"})这里添加上“xxx”这个值,再执行代码可以看到map中取出"xxx"的值。

@Controller
@RequestMapping("hello")
@SessionAttributes(value = {"user1", "msg"})
public class HelloAction {

    //我们请求的是这个方法
    @RequestMapping(value = "hello7")
    public ModelAndView doHello6( @ModelAttribute("user1") User user, ModelAndView modelAndView, HttpSession session) {
 
        //这里我们使用的是HttpSession对象存值,而不是通过springmvc设置,所以不会被存入Map
        session.setAttribute("xxx", "kkkk");
         
        //这里的msg符合@SessionAttributes的格式标准所以可以被设置到SessionAttributes上放入Map中
        modelAndView.addObject("msg", user.getId() + ":" + user.getName() + ":" + user.getPassword() + ":" + user.getCars());
        System.out.println(user + ":hello7");

        modelAndView.setViewName("redirect:/hello/hello4.do");
        return modelAndView;
    }

   @RequestMapping(value = "hello4", method = {RequestMethod.GET, RequestMethod.POST})
    public String doHello4(Map<String, Object> map, HttpSession session) {
         
        //user1和msg都在SessionAttributes中添加了,所以会自动被放入Map中,使用两种方式都可以获取到
        System.out.println(map.get("user1"));
        System.out.println("session:" + session.getAttribute("user1"));
        System.out.println(map.get("msg"));
        System.out.println("session:" + session.getAttribute("msg"));

        //有于"xxx"没有被spring放入Map,所以这里会是null
        System.out.println("map:" + map.get("xxx"));
        //只能通过HttpSession对象才能获取到
        System.out.println("session:" + session.getAttribute("xxx"));

        return "success";
    }
 

 @ModelAttribute("user1")
    public User getUser() {
        User user = new User();
        user.setId(1L);
        user.setName("jjjj");
        user.setPassword("mmmmm");
        return user;
 
    }
}

清除@SessionAttributes中的参数

用户后可以调用SessionStatus.setComplete来清除,这个方法只是清除SessionAttribute里的参数,而不会应用Session中的参数。

示例如下:注解@SessionAttribute中设置book、description和types={Double},这样值会被放到@SessionAttributes中,但Redirect跳转时就可以重新获得这些数据了,接下来操作sessionStatus.setComplete(),则会清除掉所有的数据,这样再次跳转时就无法获取数据了

@Controller
@RequestMapping("/book")
@SessionAttributes(value ={"book","description"},types={Double.class})
public class RedirectController {
    @RequestMapping("/index")
    public String index(Model model){
		model.addAttribute("book", "金刚经");
		model.addAttribute("description","不擦擦擦擦擦擦擦车");
		model.addAttribute("price", new Double("1000.00"));
		//跳转之前将数据保存到book、description和price中,因为注解@SessionAttribute中有这几个参数
		return "redirect:get.action";
	}
 
 
    @RequestMapping("/get")
    public String get(@ModelAttribute ("book") String book,ModelMap model, SessionStatus sessionStatus){
 
		//可以获得book、description和price的参数System.out.println(model.get("book")+";"+model.get("description")+";"+model.get("price"));
		sessionStatus.setComplete();
		return "redirect:complete.action";
	}

	@RequestMapping("/complete")
	public String complete(ModelMap modelMap){
 
		//已经被清除,无法获取book的值
		System.out.println(modelMap.get("book"));
		modelMap.addAttribute("book", "妹纸");
		return "sessionAttribute";
	}
}

2、@SessionAttribute

使用@SessionAttribute来访问预先存在的全局会话属性

如果你需要访问预先存在的、以全局方式管理的会话属性的话,比如在控制器之外(比如通过过滤器)可能或不可能存在在一个方法参数上使用注解@SessionAttribute

  /**
     * 在处理请求 /helloWorld/jump 的时候,会在会话中添加一个 sessionStr 属性。
     * <p/>
     * 这里可以通过@SessionAttribute 获取到
     */
    @RequestMapping("/sesAttr")
    public String handleSessionAttr(@SessionAttribute(value = "sessionStr") String sessionStr, Model model){
        System.out.println("--> sessionStr : " + sessionStr);
        model.addAttribute("sth", sessionStr);
        return "/examples/targets/test1";
}

为了使用这些需要添加或移除会话属性的情况,考虑注入org.springframework.web.context.request.WebRequest或javax.servlet.http.HttpSession到一个控制器方法中。

ROSTEA软件下载及情感分析详细操作教程(附网盘链接) 原ROST虚拟团队出品的ROST系列文本内容挖掘分析平台,是辅助人文社会科学研究的免费计算平台。该软件可以实现文本预处理、分字、分词、词性识别、特殊名词抽取、词频统计、英文词频统计、情感计算、分类算法、聚类算法等一系列文本挖掘,是人文社科研究和论文写作的一把利器。该软件用户量超过一万人,遍布海内外100多所大学,包括剑桥大学、日本北海道大学、北京大学、清华大学、香港城市大学、澳门大学等众多高校。关于ROSTCM6的安装介绍可以参考之前的文章ROSTCM6软件下载及语义网络分析详细操作教程ROST EA。 阅读详情

相关推荐

伺服电机三环控制实战:从参数整定到系统优化

本文以实战视角,深入解析伺服电机三环控制(位置环、速度环、电流环)的参数整定与系统优化全流程。文章摒弃复杂理论,通过生动的比喻和分步调试指南,详细阐述了从电流环快速响应、速度环平滑调节到位置环精准定位的调试方法,并提供了常见问题排查与进阶优化技巧,帮助工程师有效提升伺服系统性能与稳定性。

weixin_29201933的博客 244

springMVC的所有注解的原理

1、@Controller @Controller用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。@Controller只是定义了一个控制器类,而使用@RequestMapping注解的方法才是真正处理请求的处理器。 2、@RequestMapping RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所...

披风秃头侠的博客 913

手把手教你用Kokoro-82M-v1.1-zh搭建本地TTS服务(含WebSocket接口)

本文详细介绍了如何使用Kokoro-82M-v1.1-zh模型搭建本地TTS服务,包括环境配置、模型部署、WebSocket接口实现及性能优化。通过实战指南,开发者可以快速掌握本地部署TTS系统的关键技术,提升语音交互应用的开发效率。

weixin_30776273的博客 183

SpringMVC工作原理和常用注解

一、简单介绍 JavaEE体系结构包括四层,从上到下分别是应用层、Web层、业务层、持久层。Struts和SpringMVC是Web层的框架,Spring是业务层的框架,Hibernate和MyBatis是持久层的框架。 1.1、首先来对SpringMVC做一个简单的介绍 springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。 springmv...

qq_44322555的博客 1118

CANOE DIVA 工程怎样在具体服务前增加前置条件

然后会在CANoe的Test Module视窗中发现一个跟系统条件相关的Test Module模块,在该模块中有生成跟系统条件相关的CAPL 脚本。这里需要根据你的实际项目进行更改,diva工程加载到canoe的工程的时候,会同步加入你创建的cdd文件,这里示例的ABS_ESP 就是你的cdd的ECU命名,后面就是具体的前置条件服务。4、配置完成后,测试用例就会如下图Trace窗口所示,在每一次10 02请求之前都会调用CAPL Function的PreconditionCheck函数中定义的脚本。

weixin_45940007的博客 1967

IEEE PHM 2012轴承数据实战:用LSTM预测剩余寿命的完整流程与调参心得

本文详细解析了如何利用IEEE PHM 2012轴承数据集和LSTM模型进行轴承剩余寿命预测。从数据预处理、特征工程到LSTM模型架构设计和调参技巧,提供了完整的实战流程。特别分享了FEMTO-ST数据集的处理方法、RUL标签构建策略以及提升预测精度的关键技巧,帮助工程师实现更准确的预测性维护。

weixin_31100517的博客 368

AOP_Proxy代理过程理解(重新理解@Resource中name注入)

@Resource 和 @Autowired 注解都是用来实现依赖注入的, @Resource 默认按 byName 自动注入,@Autowired 默认按 byType 自动注入, @Resource 有两个重要的属性,分是 name 和 type, @Resource(name="xxx"),使用 byName 策略自动注入, Spring 将 name 属性解析为 bean 的名字...

qiudechao1的博客 1010

NVIDIA DGX Spark实战:如何在桌面上轻松运行200B参数大模型?

本文详细介绍了如何利用NVIDIA DGX Spark在桌面端轻松运行200B参数大模型。通过实战演示,从系统初始化、模型获取部署到内存管理与性能调优,重点解析了其统一内存架构如何解决本地推理的显存瓶颈,并探讨了进行轻量化微调(如LoRA)的可能性,为AI开发者和研究团队提供了高效的本地化大模型操作方案。

weixin_29054195的博客 885

@Recource注解的意思

@Resource 注解被用来激活一个命名资源(named resource)的依赖注入,在JavaEE应用程序中,该注解被典型地转换为绑定于JNDI context中的一个对象。 Spring确实支持使用@Resource通过JNDI lookup来解析对象,默认地,拥有与@Resource注解所提供名字相匹配的“bean name(bean名字)”的Spring管理对象会被注入。 在下面的例子

zhaobokaigod的专栏 1399

论文必备 - YOLOv12热力图可视化,支持指定模型,指定显示层,设置置信度,以及10种可视化实现方式

本文带来的是YOLOv12热力图可视化功能,支持,以及。我们经常看到一些论文里绘制了不同的热力图,一方面能够直观的感受其模型的有效性,另一方面也丰富了论文内容。特别是在使用了注意力模块的网络中,热力图就可以验证注意力机制是否真正聚焦到了预期的重要特征上,以便对模型的有效性和合理性进行评估。例如这篇文章中展示的,就很能够表达作者改进后的模型相比之前模型的优越性。

Limiiiing的博客 1706

全志F1C100S/F1C200S学习笔记(1)——基础简介及资料

资料: 荔枝派资料下载站 荔枝派github 荔枝派中文论坛 荔枝派DIY-github资料 荔枝派Nano 全流程指南 芒果派 坑网

丨晋丨 1万+

@RequestMapping和Rest基本介绍和应用

REST风格详细介绍REST:即 Representational State Transfer,表述性状态传递。它结构清晰,同时可以隐藏行为。

weixin_39158966的博客 1348

材料仿真软件:Materials Studio_(14).电学性质计算

设置计算参数,包括 k 点网格、交换相关泛函等。

kkchenjj的博客 1863

Spring MVC工作原理 及注解说明

SpringMVC框架介绍     1) Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。 Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring

shuyeshangdemayi的专栏 3908

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Spring MVC : 注解@ControllerAdvice的工作原理

Spring MVC中,通过组合使用注解@ControllerAdvice和其他一些注解,我们可以为开发人员实现的控制器类做一些全局性的定制,具体来讲,其效果如下 : 结合@ExceptionHandler使用 ==> 添加统一的异常处理控制器方法 结合@ModelAttribute使用 ==> 使用共用方法添加渲染视图的数据模型属性 结合@InitBinder使用 ==> ...

Details Inside Spring 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

spring mvc原理_Spring MVC工作原理 及注解说明

SpringMVC框架介绍 1) spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置的,而...

weixin_39899630的博客 162

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Spring AOP、Spring MVC工作原理、发展演变、常用注解

Spring-AOP 、Spring-MVC

m0_67496588的博客 1036

Spring MVC工作原理和注解浅析

SpringMVC框架介绍    1) spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置...

memory_CC的博客 568
上一篇: [Problem] Maven工程WEB-INF下的的JSP页面无法加载 js\css\images资源解决方案
下一篇: spring MVC(二)数据传递
Marvin-Fox
博客等级 码龄11年 190粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值