Spring MVC项目功能不完全指北

  • Spring MVC角色

    Spring MVC是一款优秀的控制器框架,我们基于Servlet的思想基础,使用Spring MVC是一件比较简单的事情。只是Spring MVC会实现很多细节化的东西,使得开发的效率很高。Serlvet只是粗浅的处理了HTTP请求,其中并没有牵扯到复杂的需求定制。庆幸的是,Spring MVC实现了很多定制功能并且学习成本不高,而且开发效率大大提高了。

  • 处理HTTP请求

    如Servlet中存在doGet和doPost方法一样,如果把Spring MVC的方法声明为

method = RequestMethod.GET

    则它会处理Get请求,如果使用POST访问,则会返回405的状态号。

    HTTP API就是要把接口暴露在URL里,通过URL可以执行你写的函数去处理数据。

    在暴露API之前必须定义一个类为Controller,这样框架就会在输入URL的时候定位到这个类的方法。

    这些功能的实现原理都是使用Java的Annotation。

@Controller
public class controller{
    .....
}

    普通方法返回的值都会转化成页面URL,比如返回hello,它就会去在WebContent里去寻找相应的资源,现在普遍的框架都是前后分离,所以都使用ResponseBody来构造REST API。

    @RequestMapping(value="/invoiceStatus",produces="text/html;charset=UTF-8",method = RequestMethod.GET)
    public @ResponseBody String getStatus(){
        JSONObject jsonResult  = new JSONObject();
        jsonResult.put(InvoiceStatus.ENTERING.getCode(), InvoiceStatus.ENTERING.getName());
        jsonResult.put(InvoiceStatus.CHECKED.getCode(), InvoiceStatus.CHECKED.getName());
        jsonResult.put(InvoiceStatus.FINANCE.getCode(), InvoiceStatus.FINANCE.getName());
        return resultSuccess("success", jsonResult.toString());
    }

    如果访问上述方法,则会在页面上显示一串字符串。

    在高版本的Spring MVC中支持REST接口控制器

@RestController
@Scope("singleton")
@RequestMapping(value="/rest")
public class restController{
...
}

    RestController就是Controller和ResponseBody的组合。

    在项目中比如你想获得某些资源,比如用户信息,那么你会定义一个:项目名/user/userInfo,这样的接口,然后把信息封装成JSON字符串返回给前端,然后前端把数据渲染到页面上,这样一个REST API就做好了。

    为了更优雅的使用GET请求,Spring MVC支持 "/参数" 这样的形式,替代"?参数名=aaa&参数名=bbb"这样久形式。

    @RequestMapping(value="/noNeedLogin/validateUser/{username}",produces="text/html;charset=UTF-8",method = RequestMethod.GET)
    @ResponseBody
    public String validateUser(@PathVariable("username")String username){
        User u = null;
        try{
            u = uService.validateUser(username);
        }catch (Exception e) {
            logger.debug("验证用户出错 : "+e.getMessage());
            return exception("验证方法出现异常");
        }
        if(u == null)
            return failure("不存在此用户");
        else
            return success("用户已存在");
    }

    如上述实例,将形参映射到URL上,就可以把GET请求变得很“好看”了。

    如果要使用Request,Response,Session,则在请求方法中指定形参,方法体内就可使用,框架会对形参进行注入。

    public void test(HttpServletRequest request,HttpServletResponse response,HttpSession session){

    }
  • 事务功能

    Spring框架提供了事务管理机制,来控制数据库事务的提交。

    事务有ACID特性,在Spring中提供一个注解可以控制事务的隔离性,以及事务的传播特性、超时、只读属性。对于以前写重复的commit来说,框架把重复代码抽取出来,提高了开发效率。

    首先在配置文件中添加事务管理器。

    在业务类中配置@Service标签,然后再Spring配置文件中写入自动检索Service标签并添加事务。

    Spring配置头文件记录,适用于4.0以上的版本:

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-4.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
     http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
</beans>

    配置事务管理器:

    <!--加入过滤的配置是为了使mybatis的事务起作用-->
    <context:component-scan base-package="Service" />
    <!-- 进行主数据库的事务配置,采用默认策略 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" />
        <!-- 配置数据源 使用dbcp连接池-->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"  destroy-method="close">
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
        <!--initialSize: 初始化连接-->
        <property name="initialSize" value="25"/>
        <property name="maxTotal" value="20"/>
        <property name="maxIdle" value="5"/>
    </bean>

    数据源采用了DBCP2连接池。

    然后在方法前面适用@Transactional标签

    rollbackfor是产生什么样的异常时候回滚,

    readOnly是表示只读事务,如果有写操作则会报错,

    propagation是事务的传播属性,说明的是事务和事务之间调用的关系,比如一个事务调用另一个事务开不开起一个新事务,

    timeout是超时,事务15s内不完成视为超时,

    还有一个属性就是事务的隔离级别,isolation,值就是四大隔离级别。

    @Transactional(rollbackFor=Exception.class,readOnly = true, propagation = Propagation.REQUIRED,timeout=15)
    public List<Invoice> getByUserid(long userid){
        List<Invoice> results = iDao.findByUserId(userid);
        return results;
    }
  • 方法级控制-拦截器

    通常在前后端架构分离的时候,后台只需要编写数据接口,而数据接口的访问权限,可以采用拦截器来实现。

    拦截器主要会过滤url中指定拦截规则的接口,也就是方法级的屏障。

    编写拦截器需要实现一个HandlerInterceptor接口,然后配置到mvc的配置文件中。

    比如登录拦截器:

package Common.Interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import Common.CommonInfo;
import Model.User;

/**
 * 登录过滤器
 * @author ctk
 *
 */
public class UserLoginInterceptor implements HandlerInterceptor{
    private static Logger logger = Logger.getLogger(UserLoginInterceptor.class);
    //后置执行
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
    }

    //前置执行
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        logger.debug("用户登录拦截器的前置方法.....");

        HttpSession session = arg0.getSession();
        User u = (User)session.getAttribute(CommonInfo.userInfo);
        if(u == null)
        {
            logger.debug("用户未登录");
            arg1.setStatus(401);
            return false;
        }
        else
            logger.debug("用户已登录:"+u.getUsername());

        return true;
    }
}

    他会校验session中是否存在用户,不存在用户过滤方法访问就会返回405,return false是不执行所拦截的方法,目前只使用前置拦截,其他两个方法暂时没有研究,配置拦截器的规则如下:

    <!--配置拦截器-->
    <mvc:interceptors>
        <!--login-->
        <mvc:interceptor>
            <mvc:mapping path="/user/**"/>
            <mvc:mapping path="/invoice/**"/>
            <mvc:mapping path="/supplier/**"/>
            <!-- 需排除拦截的地址 -->
               <mvc:exclude-mapping path="/user/noNeedLogin/**"/>
              <bean class="Common.Interceptor.UserLoginInterceptor">
              </bean>
        </mvc:interceptor>
    </mvc:interceptors>

    如果需要配置多个拦截器,则顺序的添加到后面即可,只要url符合上述规则就会拦截,除了不需要登录的接口,其他都会拦截。

  • MVC跨域配置

    跨域配置是前后分离的基础,如果一个网页不在你的项目之下,而是另一个项目启动在Ngnix静态服务器中,它写的请求大多数会试Ajax请求,Ajax请求如果访问了非项目域名,就会有跨域异常,即使解决了浏览器端请求的配置,如果服务端不开放跨域请求的话,前端也拿去不到数据。

    MVC在4.0有了很轻松的跨域配置。

    <!--配置跨域-->
   <mvc:cors>
       <mvc:mapping path="/**" allowed-origins="*" allow-credentials="true" max-age="3000" allowed-methods="GET,POST,OPTIONS"/>
   </mvc:cors>  

    对于path下,项目路径下所有方法,允许域名服务器为allowed-origins的跨域请求。

    如果需要对接口进行单独跨域,也有一个注解可以实现。

@CrossOrigin(origins = "*", maxAge = 3600)

    如果mvc配置文件添加跨域出错,则可能是xsd没有添加到正确的版本。

  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd

    我从4.0改成4.2之后,就通过了。

  • 单例模式与原型模式的需求性

    如果新建了一个Controller,使用Autowired配置在Spring里面的bean,它正常情况下都是属于单例模式。也就是无论多少次请求,只会生成一个Controller类。博主刚开始的时候很疑惑,单例模式在多用户下是否会有线程安全问题,就本质思考来说,线程安全产生的根本就是对临界区资源的访问,而Spring MVC的设计是,在一个方法内进行业务,并且根据方法的实参不同计算不同的事务,所以不存在单例模式下线程安全问题。如果你的设计需要你把属性写在Controller类下,或者Service类共享某些字段,那样就需要对Bean进行配置,变为原型模式或者是请求模式。就绝大部分需求来说,它们的执行路径就是Controller->Service->Dao->SQL,它们都是根据实参不同而生成不同的SQL,进而展现数据。如果是计算性业务,比如统计登录IP,需要在内存中统计使用到公共数据结构的话,就需要考虑线程安全了。单例模式还有一个很好的优势,就是服务器内存节省,无论多少请求,也不会对堆内存增加压力,因为只会新建一个对象,你能想象就如一个高性能的机器手,在一条流水线上对不同的半成品进行加工的场景么?

    配置原型模式和单例模式,只需要一个注解Scope。

@Scope("request")
  • 最后,有关web应用

    日志是很重要的,对于Log4j的配置,把一切日常的Info打印到一个文件中,然后error打印到另外一个文件,大概就是这样的思路。在实际开发中,大项目情况下,不会像eclipse这样本地运行虚拟机,而是配置一台Linux服务器,然后部署项目,这样就少了直接查看错误的方式了,因为以前都是在eclipse中点击错误调用栈的顶部,看是哪个代码。这时候日志就显得非常重要,日志会把错误信息写到文件中,方便查看追踪错误。其实tomcat提供了一种方便查看控制台的方式,就是logs下有个catalina.out日志,你写了SystemOut它会直接打印出来,这样开发测试就方便了不少。

    tomcat每日会做日志分割,实时日志就是没有日期的那个文件。

    查询错误或者持续查看使用tail命令

tail -f catalina.out

    查询错误使用grep命令,比如

    有些莫名的错误需要查看access这个日志,它是记录了http请求响应和状态码的日志。

时间: 2024-10-06 09:06:37

Spring MVC项目功能不完全指北的相关文章

maven Spring MVC项目

IntelliJ IDEA上创建maven Spring MVC项目 各软件版本 利用maven骨架建立一个webapp 建立相应的目录 配置Maven和SpringMVC 配置Maven的pom.xml 配置web.xml 配置contextConfigLocation文件 配置log4j.properties controller和view的编写 servlet容器的配置和运行 配置本地的tomcat服务器 配置maven插件 运行第一个Spring MVC应用 目前java开发主流的IDE

maven建spring mvc 项目访问不到uri 解决:

用maven 测试一下spring+springmvc+hibernate时,springmvc按以前本地jar建的web项目测试来配置,可怎么也访问不了uri,新建了几个项目,一直找不到,或报错! 搞了大半天,终于解决了!主要是mvc的配置如下: 其他配置照旧! <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/sche

使用maven, myeclipse工具构建spring mvc项目

一.使用myeclipse 创建一个新的 maven项目. (ps:1.在filter过滤的时候输入 webapp 选择"maven-archetype-webapp". 2.在main下建一个java文件夹(建source folder可能不能成功)) 具体可参考:http://www.cnblogs.com/waniu/p/3798775.html 二.将project 转变成webproject.(右键--properties--myeclipse--project facets

Java Spring MVC项目搭建(一)——Spring MVC框架集成

1.Java JDK及Tomcat安装 我这里安装的是JDK 1.8 及 Tomcat 8,安装步骤详见:http://www.cnblogs.com/eczhou/p/6285248.html 2.下载Eclipse并安装 我这里安装的是Java EE neon 64位版本. 3.建立Spring MVC项目 3.1.打开安装好的eclipse ,选择File->new->other.在弹出的框内选择Web->Dynamic Web Project , 选择Next. 3.2.给项目起

【Spring】搭建最简单的Spring MVC项目

每次需要Spring MVC的web项目测试一些东西时,都苦于手头上没有最简单的Spring MVC的web项目,现写一个. > 版本说明 首先要引入一些包,Spring的IOC.MVC包就不用说了.还有Jackson的包,因为默认情况下Controller的方法如要返回Json,用的是此框架. <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>

第一个使用Spring Tool Suite(STS)和Maven建立的Spring mvc 项目

一.目标 在这篇文章中.我将要向您展示怎样使用Spring Frameworks 和 Maven build创建您的第一个J2ee 应用程序. 二.信息 Maven是一个java项目的构建工具(或者自己主动构建工具).它与Ant或Gradle非常想.Maven能够自己主动下载您项目中依赖的组件. 三.要求 1.应用于Java EE 的Spring Tool Suite(STS) (http://spring.io/tools/sts/all). 请选择与您的操作系统相应的安装文件. 我比較喜欢下

Eclipse使用Maven创建Spring MVC项目(包含实例)以及部署到tomcat服务器

1.安装Maven并配置环境变量 2.eclipse中配置Maven 3.eclipse创建Maven项目 选择项目路径,next 选择maven项目类别[maven-archetype-webapp],next 输入Group Id(顶级包名),Artifact Id(项目名),Package根据两者自动生成,finish 生成的项目如上图所示. 报错原因是缺失Server Runtime Library,添加即可,同时jre替换为System Library. 替换后项目目录如下: src文

IntelliJ IDEA 创建spring mvc项目(图)

本文主要介绍怎么在IntelliJ IDEA 创建spring mvc项目,导入jar文件,tomcat配置(编辑器). 一.创建spring mvc项目 1.打开IntelliJ IDEA点击 创建新项目(Create New Project),SDK选择,然后选择sping>spring mvc,下一步 2.填写项目名称与选择项目路径 二.导入jar文件 1.选中lib文件夹,右键打开资源管理器 2.把准备好的jar文件复制粘贴到lib文件夹里面 3.点击文件(file)在列表中选择proj

Myeclipse/STS 首次在本地部署配置一个Spring MVC 项目 (十二)

1. 在本地新创建一个文件夹 ,做为项目工作空间; 2. 用 Myeclipse 或 STS 进入该文件夹,该文件夹就成为项目的工作空间: 3. 就要进 窗口-首选项,配置: 环境默认编码: 1>. 常规下面 内容类型 .txt 文本 UTF-8 更新 2>. 常规 – 工作空间 , 文本文件编码 3>. 常规 – 编辑器 – 文本编辑器 – 拼写 配置 java JDK 为 项目需要的版本 比如 (1.7) : 配置 Myeclipse 下的 Servers 及 validation