简体   繁体   中英

Spring Java - Request method 'POST' not supported (Method not allowed)

I'm still a little new to Java and Spring. I'm currently developing and application for a local baseball league. I've created two models for stat keeping. What I want to be able to do is add a player then direct to a form to collect offensive stats and then to another to collect pitching stats(if any). However, I'm running into a 405 error 'POST' not allowed after the offense stats are submitted and being redirected to the next for to collect the rest of the stats. Flow: Add Player --> Add Players Offensive Stats --> Add Players Pitching Stats

I've thought about including all Stats in a single model but I'm a little unsure if I'd have the same amount of control in the views if I did.

    package com.example.bevofuzzball.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.text.DecimalFormat;
import java.text.NumberFormat;

@Entity
public class Offense {

    @Id
    @GeneratedValue
    private int id;
    private double atBats;
    private double hits;
    private double battingAverage;
    private double onBase;
    private double slug;
    private double walks;
    private double hitByPitch;
    private double singles;
    private double doubles;
    private double triples;
    private double homeRuns;
    private double totalBases;

    @Column(name = "ops", precision = 5, scale = 5)
    private double OPS;
    private int playerId;

    public Offense(double atBats, double hits, double walks, double hitByPitch, double singles, double doubles, double triples, double homeRuns, int playerId) {
        this.atBats = atBats;
        this.hits = hits;
        this.walks = walks;
        this.hitByPitch = hitByPitch;
        this.singles = singles;
        this.doubles = doubles;
        this.triples = triples;
        this.homeRuns = homeRuns;
        this.playerId = playerId;
    }

    public Offense() {
    }

    // Methods to calculate statistics

    public void calcAvg(double hits, double atBats){
        NumberFormat formatter = new DecimalFormat("#.000");
        this.battingAverage = hits / atBats;
        System.out.println("Your batting average is " + formatter.format(battingAverage));
    }

    public void calcSlug(double singles, double doubles, double triples, double homeRuns, double atBats){
        NumberFormat formatter = new DecimalFormat("#.000");
        this.totalBases = singles + doubles * 2 + triples * 3 + homeRuns * 4;
        this.slug = totalBases / atBats;
        System.out.println("Your slugging percentage is " + formatter.format(slug));
    }

    public void calcOnBase(double hits, double atBats, double walks, double hitByPitch){
        NumberFormat formatter = new DecimalFormat("#.000");
        this.onBase = (hits + walks + hitByPitch) / (atBats + walks + hitByPitch);
        System.out.println("Your OBP is " + formatter.format(onBase));
    }

    public void calcOPS(double onBase, double slug){
        NumberFormat formatter = new DecimalFormat("#0.0000");
        this.OPS = onBase + slug;
        System.out.println("Your OPS is " + formatter.format(OPS));
    }

    //Getters and Setters


    public int getId() {
        return id;
    }

    public double getAtBats() {
        return atBats;
    }

    public void setAtBats(double atBats) {
        this.atBats = atBats;
    }

    public double getHits() {
        return hits;
    }

    public void setHits(double hits) {
        this.hits = hits;
    }

    public double getBattingAverage() {
        return battingAverage;
    }

    public void setBattingAverage(double battingAverage) {
        this.battingAverage = battingAverage;
    }

    public double getOnBase() {
        return onBase;
    }

    public void setOnBase(double onBase) {
        this.onBase = onBase;
    }

    public double getSlug() {
        return slug;
    }

    public void setSlug(double slug) {
        this.slug = slug;
    }

    public double getWalks() {
        return walks;
    }

    public void setWalks(double walks) {
        this.walks = walks;
    }

    public double getHitByPitch() {
        return hitByPitch;
    }

    public void setHitByPitch(double hitByPitch) {
        this.hitByPitch = hitByPitch;
    }

    public double getSingles() {
        return singles;
    }

    public void setSingles(double singles) {
        this.singles = singles;
    }

    public double getDoubles() {
        return doubles;
    }

    public void setDoubles(double doubles) {
        this.doubles = doubles;
    }

    public double getTriples() {
        return triples;
    }

    public void setTriples(double triples) {
        this.triples = triples;
    }

    public double getHomeRuns() {
        return homeRuns;
    }

    public void setHomeRuns(double homeRuns) {
        this.homeRuns = homeRuns;
    }

    public double getTotalBases() {
        return totalBases;
    }

    public void setTotalBases(double totalBases) {
        this.totalBases = totalBases;
    }

    public double getOPS() {
        return OPS;
    }

    public void setOPS(double OPS) {
        this.OPS = OPS;
    }

    public int getPlayerId() {
        return playerId;
    }

    public void setPlayerId(int playerId) {
        this.playerId = playerId;
    }
}

Add Offense View

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head th:replace = "fragments :: head"></head>

<nav th:replace = "fragments :: nav"></nav>
<body class = "container">
<h1 th:text ="${player.name}"></h1>
<form method="post" style="max-width:100px;" th:object = "${offense}">
    <div class="form-group">
        <label th:for="hits">Hits</label>
        <input class="form-control" th:field = "*{hits}"/>
    </div>
    <div class="form-group">
        <label th:for="atbats">At Bats</label>
        <input class="form-control" th:field = "*{atBats}"/>
    </div>
    <div class="form-group">
        <label th:for="walks">Walks</label>
        <input class="form-control" th:field = "*{walks}"/>
    </div>
    <div class="form-group">
        <label th:for="hitbypitch">Hit By Pitch</label>
        <input class="form-control" th:field = "*{hitByPitch}"/>
    </div>
    <div class="form-group">
        <label th:for="singles">Singles</label>
        <input class="form-control" th:field = "*{singles}"/>
    </div>
    <div class="form-group">
        <label th:for="doubles">Double</label>
        <input class="form-control" th:field = "*{doubles}"/>
    </div>
    <div class="form-group">
        <label th:for="triples">Triples</label>
        <input class="form-control" th:field = "*{triples}"/>
    </div>
    <div class="form-group">
        <label th:for="homeruns">Home Runs</label>
        <input class="form-control" th:field = "*{homeRuns}"/>
    </div>
    <div class="form-group">
    </div>

    <input type="submit" value="Add Stats" />
</form>

</body>
</html>

Player Controller

package com.example.bevofuzzball.controllers;

import com.example.bevofuzzball.models.Offense;
import com.example.bevofuzzball.models.Pitch;
import com.example.bevofuzzball.models.Player;
import com.example.bevofuzzball.models.data.OffenseDao;
import com.example.bevofuzzball.models.data.PlayerDao;
import com.example.bevofuzzball.models.data.TeamsDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@Controller
@RequestMapping(value = "player")
public class PlayerController {

    @Autowired
    private TeamsDao teamsDao;

    @Autowired
    private PlayerDao playerDao;

    @Autowired
    private OffenseDao offenseDao;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String displayPlayers(Model model){
        model.addAttribute("players", playerDao.findAll());
        return "player/index";
    }

    @RequestMapping(value = "add", method = RequestMethod.GET)
    public String displayAddPlayer(Model model){
        model.addAttribute("title", "Add Player");
        model.addAttribute("players", new Player());
        model.addAttribute("teams", teamsDao.findAll());

        return "player/addplayer";
    }

    @RequestMapping(value = "add", method = RequestMethod.POST)
    public String processplayeradd(@ModelAttribute @Valid Player newPlayer, @RequestParam int teamId, Model model){
        newPlayer.setTeamid(teamId);
        playerDao.save(newPlayer);

        return "redirect:addoffense/" + newPlayer.getId();
    }

    @RequestMapping(value = "addoffense/{id}", method = RequestMethod.GET)
    public String displayAddOffense(Model model, @PathVariable int id) {
        model.addAttribute("player", playerDao.findOne(id));
        model.addAttribute("offense", new Offense());
        return "player/addoffense";
    }

    @RequestMapping(value = "addoffense", method = RequestMethod.POST)
    public String processAddOffense(@ModelAttribute @Valid Offense newOffense, @RequestParam int id, Model model){
        newOffense.setPlayerId(id);
        newOffense.calcSlug(newOffense.getSingles(), newOffense.getDoubles(), newOffense.getTriples(), newOffense.getHomeRuns(), newOffense.getAtBats());
        newOffense.calcAvg(newOffense.getHits(), newOffense.getAtBats());
        newOffense.calcOnBase(newOffense.getHits(), newOffense.getAtBats(), newOffense.getWalks(), newOffense.getHitByPitch());
        newOffense.calcOPS(newOffense.getOnBase(), newOffense.getSlug());
        offenseDao.save(newOffense);

        return"redirect:addpitch/" + newOffense.getPlayerId();
    }

    @RequestMapping(value = "addpitch/{id}", method = RequestMethod.GET)
    public String displayAddPitch(Model model, @PathVariable int id) {
        model.addAttribute("player", playerDao.findOne(id));
        model.addAttribute("pitch", new Pitch());

        return "player/addpitch";
    }
}

Add Pitch Form

<!DOCTYPE html>
<html lang="en" xmlns:th="www.thymeleaf.org">
<head th:replace = "fragments :: head"></head>

<nav th:replace = "fragments :: nav"></nav>
<body class = "container">
<form method="post" style="max-width:600px;" th:object = "${pitch}">
    <div class="form-group">
        <label th:for="wins">Wins</label>
        <input class="form-control" th:field = "*{wins}"/>
    </div>
    <div class="form-group">
        <label th:for="save">Saves</label>
        <input class="form-control" th:field = "*{saves}"/>
    </div>
    <div class="form-group">
        <label th:for="inningspitched">Innings Pitched</label>
        <input class="form-control" th:field = "*{inningsPitched}"/>
    </div>
    <div class="form-group">
        <label th:for="strikeouts">Strikeouts</label>
        <input class="form-control" th:field = "*{strikeouts}"/>
    </div>
    <div class="form-group">
        <label th:for="walks">Walks</label>
        <input class="form-control" th:field = "*{walks}"/>
    </div>
    <div class="form-group">
        <label th:for="hitsallowed">Hits Allowed</label>
        <input class="form-control" th:field = "*{hitsAllowed}"/>
    </div>
    <div class="form-group">
        <label th:for="runsallowed">Runs Allowed</label>
        <input class="form-control" th:field = "*{runsAllowed}"/>
    </div>
    <div class="form-group">
        <label th:for="hrallowed">Home Runs Allowed</label>
        <input class="form-control" th:field = "*{hrAllowed}"/>
    </div>
    <div class="form-group">
    </div>

    <input type="submit" value="Add Stats" />
</form>

</body>
</html>

Error clearly says that you are trying to access a URL with POST method, but it does not have that METHOD TYPE + URL endpoint. (an HTTP status 405 means method not allowed, so end point exists but the method does not match)

can you check you browser network tab (inspect element work on chrome/firefox/safari) and see what URL its calling on submit call which is failing. Right click and select Inspect.

Url end point should be

POST : http://youripd:port/player/addoffense (if you are running standalone executable jar eg spring boot)

Or

POST : http://youripd:port/nameofwarfile/player/addoffense (if you are running inside some container like tomcat)

Another thing i would like to suggest is, Instead of auto redirect/forward, let UI take care of which would be the next flow it should be sent to. So that each form is independent component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM