一个基本的spring mvc项目搭建(入门)

本文介绍了如何搭建一个基本的Spring MVC项目,包括创建动态Web工程,引入所需jar包,构建目录结构,配置web.xml和Spring XML文件,以及编写核心逻辑代码。重点关注了Spring的bean管理和控制反转的概念,同时解决了项目中出现的资源加载、乱码和过滤器配置等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


2015-12-25
类加载路径classpath: classpath:/ 是等价的。都是相对于类的根路径。
classpath*:加载所有相同的classpath下的资源。
例如自己的项目路径和引入的jar包的路径重叠,
那么:
classpath:只扫描第一个加载的包。
classpath*: 加载所有的包


2015-12-14:
下面的classpath路径问题,其实有一个非常方便的方法解决!
就是查看项目中的build目录下的class目录。
这下面的是项目编译过后产生的,路径一目了然


注意
2015-12-10:发现一个极其奇怪的问题,即classpath
本示例完美运行,然而之后本人新建立一个项目,结构一致,然而
当我配置log的时候,
classpath*:log/log4j.properties 提示无法找到
classpath*:spring/spring.xml这个却找到了
换成
classpath:log/log4j.properties则日志OK
classpath:spring/spring.xml 也OK
classpath*:spring/spring.xml 也OK
classpath*:common/jdbc.properties 也OK
不明就里

最后全部统一
classpath:log/log4j.properties
classpath:spring/spring.xml


目录

  • 概述
  • 建立项目
  • 配置Spring.xml文件
  • 编写完整流程代码
  • 总结

No.1 概述

Spring框架在此不多介绍。本文是作为一名初学者的角度,来一步步建立起一个完整的Spring web项目并且调试通过。整个项目尽量做到简单,使用最新的jar。
环境:eclipse,mysql

No.2 建立项目

第一步:建立一个动态web工程,取名MySpring,点击next,next,选择生成web.xml
这里写图片描述

第二步:在WEB-INF的lib目录下引入jar包,基本的jar以及依赖的jar
其中包括连接mysql以及httpclient的jar
这里写图片描述

第三步:建立工程目录,本例取名com.csdn.myspring,以及简单的目录结构
- resource存放资源文件(properties,xml等)
- test存放测试用例
结构如图所示:(为了简单,并没有考虑代码的’优雅’)
这里写图片描述


No.3 配置spring xml文件

1.配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>MySpring</display-name>


    <!--之前这个地方加了个contex:param-name,contextConfigLocation以及相应的listener,后来发现每次bean都被创建了两次,貌似这种是针对放到WEB-INF下的Application.xml,我们手动指定了目录,则不要这个-->

    <!--添加对日志的监听-->
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <!--添加springmvc的servlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--容器启动的时候加载指定目录的配置文件-->
            <!--classpath*:resouce/spring/spring.xml如果resource和src是平级的,那么不加resource-->
            <param-value>classpath*:spring/spring.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--设置过滤模式,此处是全接收-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--设置编码,但是目前看来没什么用-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>


    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

2.加入相应的配置文件
(此处为了结构清晰,易于扩展,spring.xml仅仅是一个导入的功能,具体的bean或者数据库的配置在其他的xml来配置)
目录如下:
这里写图片描述

spring.xml

<?xml version="1.0" encoding="UTF-8"?>  
<!--每一个url都对应了需要使用的东西-->
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans.xsd">  

   <import resource="classpath*:spring/spring-view.xml"/>
   <import resource="classpath*:spring/spring-database.xml"/>
   <import resource="classpath*:spring/spring-bean.xml"/>
</beans>  

spring-bean.xml
ps:一般的类bean不写成这种,直接在类上加上注解,而后通过context:component-scan扫描进来,spring则会把被它所管理的类创建

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

     <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入  (controller/service/resposity注解的作用就是声明,可以被scan发现)-->
    <context:component-scan base-package="com.csdn.myspring" />

    <bean id="test" class="com.csdn.myspring.controller.TestBean" scope="singleton">
    </bean>
</beans>  

spring-database.xml
ps:使用的是c3p0数据源,以及spring JdbcTemplate

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

    <!-- jdbc配置文件 -->
    <context:property-placeholder location="classpath*:database/jdbc.properties"/>

    <!-- 配置Jdbc模板 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass">
            <value>${jdbc.driverClassName}</value>
        </property>
        <property name="jdbcUrl">
            <value>${jdbc.url}</value>
        </property>
        <property name="user">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
        <!--连接池中保留的最小连接数。 -->
        <property name="minPoolSize">
            <value>5</value>
        </property>
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize">
            <value>30</value>
        </property>
        <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
        <property name="initialPoolSize">
            <value>10</value>
        </property>
        <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime">
            <value>60</value>
        </property>
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="acquireIncrement">
            <value>3</value>
        </property>
        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
                如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
        <property name="maxStatements">
            <value>0</value>
        </property>
        <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
        <property name="idleConnectionTestPeriod">
            <value>60</value>
        </property>
        <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
        <property name="acquireRetryAttempts">
            <value>30</value>
        </property>
        <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
             获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
        <property name="breakAfterAcquireFailure">
            <value>true</value>
        </property>
        <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
             等方法来提升连接测试的性能。Default: false -->
        <property name="testConnectionOnCheckout">
            <value>false</value>
        </property>
    </bean>

<!--     配置事务管理器
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource" /> -->

<!--     通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务
    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceMethod"
            expression=" execution(* com.service..*(..))" />
        <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice> -->

</beans>

spring-view.xml

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

    <!-- 添加注解驱动(还没太理解,貌似和扫描类一个道理) -->
    <mvc:annotation-driven />
    <!-- 定义跳转的文件的前后缀 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
<!--网上有些使用&amp后跟上utf-8,多次实验证明&amp会使后面的utf-8编码失效,如果你发现中文插入数据库乱码,那么检查下jdbc这里的配置是不是用了&amp-->
jdbc.url=jdbc:mysql://localhost:3306/springwebtest?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456

log4j.properties
ps:现在还没使用

log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} [\u65E5\u5FD7\u4FE1\u606F] %m%n

No.4 逻辑流程代码

代码目录如图所示:
这里写图片描述

UserController.java

package com.csdn.myspring.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.csdn.myspring.dao.UserDao;
import com.csdn.myspring.entity.UserEntity;

/**
 * 用户控制
 * @author Ming
 *
 */
@Controller                                     // 标注为controller,便于spring管理
@RequestMapping(value = "/user")  
public class UserController {
    @Autowired                                  // 它的实现userDaoImpl因被spring创建了,所以无需初始化                                    
    private UserDao userDao;                    // 注入的是一个接口。能够自动找到它的实现,便于更改实现

    @RequestMapping(value = "/userInfoJSP") 
    public String userInfo() {  
        // return "success"; //跳转到success页面  
        return "user";  
    }

    /**
     * 查看
     * @param json
     * @return
     */
    @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET)
    @ResponseBody
    public String getUserInfo(String json) {  
        String result = null;  //返回值
        System.out.println("这是一个测试");
        return result;  
    }

    /**
     * 保存
     * @param json
     * @return
     */
    @RequestMapping(value = "/saveUserInfo", method = RequestMethod.POST)
    @ResponseBody
    public String saveUserInfo(@RequestBody String json) {  
        String result = null;  //返回值
        UserEntity user = JSONObject.parseObject(json,UserEntity.class);  //将传来的json转换为对象
        System.out.println("这是一个测试");
        userDao.save(user);
        return result;  
    }  
}

UserDaoImpl .java

package com.csdn.myspring.dao.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.csdn.myspring.dao.UserDao;
import com.csdn.myspring.entity.UserEntity;

@Repository  // 注解表明被spring管理,当被扫描到则被创建
public class UserDaoImpl implements UserDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void save(UserEntity user) {
        // 与表结构一一对应
        String sql = "insert into user(u_name,password,credits) values(?,?,?)";
        jdbcTemplate.update(sql, new Object[]{user.getuName(),user.getPassword(),user.getCredits()});
    }

    @Override
    public void update(UserEntity user) {
        // TODO Auto-generated method stub

    }

    @Override
    public UserEntity getPerson(int id) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<UserEntity> getUsers() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void delete(int personid) {
        // TODO Auto-generated method stub

    }

}

UserEntity .java

package com.csdn.myspring.entity;

/**
 * User实体
 * @author ming
 *
 */
public class UserEntity {
    private int uId;  //id
    private String uName; //名字
    private int credits;  
    private String password;

    public int getuId() {
        return uId;
    }

    public void setuId(int uId) {
        this.uId = uId;
    }

    public String getuName() {
        return uName;
    }

    public void setuName(String uName) {
        this.uName = uName;
    }

    public int getCredits() {
        return credits;
    }

    public void setCredits(int credits) {
        this.credits = credits;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

至此,全部项目代码以及配置完成。可以进行测试了。

先开启mysql服务,而后创建数据库表。

项目加入tomcat,并启动。

用postman插件输入如下:

这里写图片描述

点击send.完成后没报错。
之后查看数据库:

这里写图片描述

已经正确的插入,并且无乱码。至此一个简单的springmvc项目算是完成了!

(未涉及前端)

No.5 总结

1.最初resource目录放在src中,所以写的是
classpath*:resource/spring/spring-view.xml
这种带有resource的。之后resource目录放在与src平级的根目录,导致没有加载xml文件,将resource/去掉,
classpath*:spring/spring-view.xml
OK!成功了

2.项目乱码,web.xml设置了后,debug模式发现收到的是乱码。
在客户端需要设置application/json;charset=UTF-8(注意是分号),客户端收到了中文,但是数据库还是乱码,数据库的编码已经设置过,而后查看发现需要设置jdbc.properties:
jdbc.url=jdbc:mysql://localhost:3306/springwebtest?useUnicode=true&characterEncoding=UTF-8
OK!乱码问题解决

3.两种创建bean的方式

// 第一种
<bean id="test" class="com.csdn.myspring.controller.TestBean" scope="singleton">
    </bean>
// 第二种
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入
(controller/service/resposity注解的作用就是声明,可以被scan发现)-->
    <context:component-scan base-package="com.csdn.myspring" />

除了spring本身的一些bean需要些bean标签。其他的项目本身的代码类都通过注解后扫描的方式来实现。方便而又快捷明了

4.这一章的主要目的是搭建整个项目框架,以及学习spring的ioc(控制反转),spring aop的知识在下一章在进行探索研究。


——2015-12-9下午14:30添加:
之前web.xml中说道filter感觉没用,是因为没有配置filter-mapping,完整的过滤如下:

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>

从这个例子可以看出来,web.xml里面的都是一个东西对应一个mapping,如果没有mapping,相当于是摆设,并没使用它。加上这个filter mapping后,则postman客户端无需再设置编码utf-8。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值