Spring MVC实战二

11 篇文章 0 订阅

在实战一中,我们已经完成了实体层和Dao层的代码编写,这篇文章中,我们将会完成剩余的代码编写工作。
新建一个UserService类,作为我们的业务类。UserService负责将UserDao与LoginDao组织起来,完成用户的登录验证,以及登录日志的记录等操作。

@Service // 将UserService标注为一个服务层的Bean
public class UserService {
    private UserDao userDao;
    private LoginLogDao loginLogDao;

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

    @Autowired
    public void setLoginLogDao(LoginLogDao loginLogDao) {
        this.loginLogDao = loginLogDao;
    }

    public boolean hasMatchUser(String userName, String password) {
        int matchCount = userDao.getmatchCount(userName, password);
        return matchCount > 0;
    }

    public User findUserByUserName(String userName) {
        return userDao.findUserByUserName(userName);
    }

    @Transactional // 事务注解
    public void loginSuccess(User user) {
        user.setCredits(5 + user.getCredits());
        LoginLog loginLog = new LoginLog();
        loginLog.setUserId(user.getUserId());
        loginLog.setIp(user.getLastIp());
        loginLog.setLoginDate(user.getLastVisit());
        userDao.updateLoginInfo(user);
        loginLogDao.insertLoginLog(loginLog);
    }
}

以上代码也十分简单,首先注解@Service将UserService类声明为一个Bean,@Autowired则自动装配UserDao 和LoginLogDao 两个Bean,注解@Transactional标注了该方法需要在事务环境中执行,而我们需要做的仅仅是在smart-context.xml中配置事务管理器。

<!-- 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource" />
    <!-- 以AOP的方式,让com.smart.service包下所有类标注了@Transactional的所有方法,都工作在事务环境中 -->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceMethod"
            expression=" (execution(* com.smart.service..*(..))) and
            (@annotation(org.springframework.transaction.annotation.Transactional))" />
        <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>

完成以上工作后,其实我们代码已经可以运行了,只是缺少展现层,但是这没关系,我们可以先通过单元测试来验证我们的代码功能是否正确。
本次单元测试采用Junit,而对于Junit的依赖引用,已经在实战一的pom.xml中贴出来了。为了区别于正常功能的代码,Maven已经帮我们的工程结构做了很好的规划了,单元测试的代码,我们可以在src/test/java中编写。
新建一个UserServiceTest类,package为com.smart.service,这样与正常功能代码保持一致。

@RunWith(SpringJUnit4ClassRunner.class) // @RunWith就是一个运行器,使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。
@ContextConfiguration("classpath*:smart-context.xml")
public class UserServiceTest {
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Test
    public void testHashMatchUser() {
        // System.out.println("Test...hashMatchUser!");
        boolean b1 = userService.hasMatchUser("admin", "123456");
        boolean b2 = userService.hasMatchUser("admin", "4321");
        assertTrue(b1);
        assertTrue(!b2);
    }

    @Test
    public void testFindUserByUserName() {
        User user = userService.findUserByUserName("admin");
        assertEquals(user.getUserName(), "admin");
    }

    @Test
    public void testAddLoginLog() {
        User user = userService.findUserByUserName("admin");
        userService.loginSuccess(user);
    }
}

OK。那么接下来就只要右键这个类,Run as->Juint Test执行一下,就能看到结果了。
以上这些工作做完之后,就该到了去实现展现层功能的时候了。废话不多说,马上来配置Spring MVC框架。

    <!-- ①从类路径下加载Spring配置文件,classpath关键字特指类路径下加载 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:smart-context.xml</param-value>
    </context-param>
    <!-- 负责启动Spring容器的监听器,它将引用①处的上下文参数获得Spring配置文件的地址 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- Spring MVC的主控Servlet -->
    <servlet>
        <servlet-name>smart</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <!-- Spring MVC处理的URL -->
    <servlet-mapping>
        <servlet-name>smart</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

在web.xml中,我们声明了一个smart的Servlet,则必须提供一个smart-servlet.xml的配置文件,但这个配置文件的路径我们无需声明,因为Spring会自动的将这些配置文件进行拼装。若是smart-servlet.xml的文件名不是采用Servlet名字-servlet的形式的话,则需要我们自己去主动声明路径。
在smart中,我们让.html结尾的URL请求都被截获,进而转由Spring MVC框架进行处理。请求被截获之后,会根据请求的URL查找到目标的处理控制器。

@Controller // 标注成为一个Spring MVC的Controller
public class LoginController {
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    // 负责处理/index.html的请求
    @RequestMapping(value = "/index.html")
    public String loginPage() {
        return "login";
    }

    @RequestMapping(value = "/loginCheck.html")
    public ModelAndView loginCheck(HttpServletRequest request, LoginCommand loginCommand) {
        boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(), loginCommand.getPassword());
        if (!isValidUser) {
            return new ModelAndView("login", "error", "用户名或密码错误!");
        } else {
            User user = userService.findUserByUserName(loginCommand.getUserName());
            user.setLastIp(request.getLocalAddr());
            user.setLastVisit(new Date());
            userService.loginSuccess(user);
            request.getSession().setAttribute("user", user);
            return new ModelAndView("main");
        }

    }

}

public class LoginCommand {
    private String userName;
    private String password;
    //此处省略get() set()方法
}

上面说到配置了名为smart的Servlet之后,还需要配置smart-servlet.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-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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd   
        ">
    <context:component-scan
        base-package="com.smart.web" />

    <!-- 配置视图解析器,将ModelAndView及字符串解析为具体的页面 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:viewClass="org.springframework.web.servlet.view.JstlView"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" p:order="100" />
    <!--<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
        p:prefix="/WEB-INF/html/" p:suffix=".htm" p:order="1" /> -->
    <!-- 静态资源访问处理 -->
    <!-- 为了让正常的@RequestMapping不会被影响    -->
    <mvc:annotation-driven/>
    <!--  <mvc:default-servlet-handler />-->
    <mvc:resources mapping="/html/**"
        location="/html/" cache-period="31556926" />eans>

我们需要在smart-servlet中声明LoginController 控制器,以及配置视图解析器。完成MVC配置和控制器之后,就只剩JSP视图界面了,那么我们只能上代码。
login.jsp

<body>
    <c:if test="${!empty error} }">//使用JSTLL标签对登录错误返回的信息进行处理
        <font color="red"><c:out value="${error}" /></font>
    </c:if>
    <form action="<c:url value="/loginCheck.html" />" method="post">
        用户名: <input type="text" name="userName"> <br> 密码: <input
            type="password" name="password"> <br> <input
            type="submit" value="登录"> <input type="reset" value="重置">
    </form>
</body>

main.jsp

<body>${user.userName},欢迎您,您当前积分${user.credits};
</body>

OK。至此,我们已经完成了本次Spring MVC实战的所有代码工作了。剩下的就是运行此Web应用,我们采用在pom.xml文件配置Jetty插件的形式来运行。配置如下:

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <!-- Jetty插件 -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.5.v20170502</version>
                <!-- 配置说明 -->
                <configuration>
                    <httpConnector>
                        <port>8099</port>
                    </httpConnector>
                    <!-- 默认值是 0。大于 0 的数值表示开启,0 表示关闭,单位为秒。以配置数值为一个周期,自动的扫描文件检查其内容是否有变化,如果发现文件的内容被改变,则自动重新部署运用。 -->
                    <!-- <scanIntervalSeconds>2</scanIntervalSeconds> -->
                    <!-- 默认值为 automatic,它与大于 0 的 scanIntervalSeconds 节点一起作用,实现自动热部署的工作。设为 
                        manual 的好处是,当你改变文件 内容并保存时,不会马上触发自动扫描和重部署的动作,你还可以继续的修改,直至你在 Console 或命令行中敲回车键(Enter)的时候才触发重新加载的动作。这样可以更加的方便调试修改。 
                        命令行的方式是:mvn -Djetty.reload=manual jetty:run 。 -->
                    <reload>manual</reload>
                    <dumpOnStart>true</dumpOnStart>
                    <webApp>
                        <contextPath>/${project.artifactId}</contextPath>
                        <descriptor>${project.basedir}/src/main/webapp/WEB-INF/web.xml</descriptor>
                    </webApp>
                    <requestLog
                        implementation="org.eclipse.jetty.server.NCSARequestLog">
                        <filename>target/access-yyyy_mm_dd.log</filename>
                        <filenameDateFormat>yyyy_MM_dd</filenameDateFormat>
                        <logDateFormat>yyyy-MM-dd HH:mm:ss</logDateFormat>
                        <logTimeZone>GMT+8:00</logTimeZone>
                        <append>true</append>
                        <logServer>true</logServer>
                        <retainDays>120</retainDays>
                        <logCookies>true</logCookies>
                    </requestLog>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.17</version>
                <configuration>
                    <parallel>methods</parallel>
                    <threadCount>10</threadCount>
                </configuration>
            </plugin>
        </plugins>
    </build>

接下来,我们就对项目右键run as->maven build吧。
这里写图片描述
Goals处填写jetty:run。
这里写图片描述
至此,我们已经完成了这次Demo的编写了,如有不足的地方,希望大家多多指教~~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值